diff --git a/.gitignore b/.gitignore index 94dc092c602..1b292a0ed77 100644 --- a/.gitignore +++ b/.gitignore @@ -187,6 +187,19 @@ packages/kie-sandbox-fs/coverage packages/kie-sandbox-fs/junit packages/kie-sandbox-fs/*-0.0.0-development.tgz +# kogito-serverless-operator +# These files are generated by Cekit, we can ignore the operator-sdk ones. +packages/kogito-serverless-operator/bundle.Dockerfile +packages/kogito-serverless-operator/Dockerfile +# Test binary, built with `go test -c` +packages/kogito-serverless-operator/**/*.test +# Output of the go coverage tool, specifically when used with LiteIDE +packages/kogito-serverless-operator/**/*.out +# Build +packages/kogito-serverless-operator/bin/ +packages/kogito-serverless-operator/target/ +packages/kogito-serverless-operator/e2e-test-report.xml + #angular **/.angular @@ -279,5 +292,16 @@ packages/bpmn-marshaller/**/ts-gen packages/dmn-marshaller/**/ts-gen packages/scesim-marshaller/**/ts-gen +# kogito-sf-{builder|devmode}-image: excluding module build folders +!packages/kogito-swf-common/resources/**/build +!packages/kogito-swf-builder/resources/**/build +!packages/kogito-swf-devmode/resources/**/build +!packages/kogito-swf-common/test-resources/ +!packages/kogito-swf-builder/test-resources/ +!packages/kogito-swf-devmode/test-resources/ + +__pycache__ +packages/python-venv/venv + # devbox -.devbox \ No newline at end of file +.devbox diff --git a/devbox.json b/devbox.json index 9627108022d..f2127023860 100644 --- a/devbox.json +++ b/devbox.json @@ -7,9 +7,7 @@ "kubernetes-helm": "3.13.3", "gnumake": "4.4.1", "go": "1.21.8", - "python": "3.12.2", - "operator-sdk": "1.34.1", - "kubebuilder": "3.14.0" + "python": "3.12.2" }, "env": { "PLAYWRIGHT_BROWSERS_PATH": "0", @@ -17,13 +15,16 @@ "DEVBOX_COREPACK_ENABLED": "true", "GOFLAGS": "-modcacherw", "GOPATH": "$DEVBOX_PROJECT_ROOT/.devbox/gopkgs", - "PATH": "$PATH:$DEVBOX_PROJECT_ROOT/.devbox/gopkgs/bin" + "PATH": "$DEVBOX_PROJECT_ROOT/.devbox/gopkgs/bin:$PATH" }, "shell": { - "init_hook": [". $VENV_DIR/bin/activate"], + "init_hook": [ + ". $VENV_DIR/bin/activate", + "[[ $OSTYPE == 'darwin'* ]] && export PATH=$(echo $PATH | tr ':' '\n' | grep -vi 'xcode\\|clang\\|cctools' | paste -sd ':' -)" + ], "scripts": { "versions": [ - "java --version && mvn -v && node -v && pnpm -v && go version && helm version && make -v && python --version && pip --version" + "java --version && mvn -v && node -v && pnpm -v && go version && helm version && make -v && python3 --version && pip3 --version" ] } } diff --git a/devbox.lock b/devbox.lock index e2408302f2a..687c17f6d29 100644 --- a/devbox.lock +++ b/devbox.lock @@ -141,54 +141,6 @@ } } }, - "kubebuilder@3.14.0": { - "last_modified": "2024-03-22T07:26:23-04:00", - "resolved": "github:NixOS/nixpkgs/a3ed7406349a9335cb4c2a71369b697cecd9d351#kubebuilder", - "source": "devbox-search", - "version": "3.14.0", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/hdggigkq5ibqvk3ksmq7cwlyn1l2gdsv-kubebuilder-3.14.0", - "default": true - } - ], - "store_path": "/nix/store/hdggigkq5ibqvk3ksmq7cwlyn1l2gdsv-kubebuilder-3.14.0" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/7ykpi9d6jd4zhxs5c6lfbb9p5kgm5m3p-kubebuilder-3.14.0", - "default": true - } - ], - "store_path": "/nix/store/7ykpi9d6jd4zhxs5c6lfbb9p5kgm5m3p-kubebuilder-3.14.0" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/jpqwxd42bcfkxljy0pkqagbnpifdxvpx-kubebuilder-3.14.0", - "default": true - } - ], - "store_path": "/nix/store/jpqwxd42bcfkxljy0pkqagbnpifdxvpx-kubebuilder-3.14.0" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/c492irdhgzr6wbl6zggn5bw23dlgxb9r-kubebuilder-3.14.0", - "default": true - } - ], - "store_path": "/nix/store/c492irdhgzr6wbl6zggn5bw23dlgxb9r-kubebuilder-3.14.0" - } - } - }, "kubernetes-helm@3.13.3": { "last_modified": "2024-01-27T14:55:31Z", "resolved": "github:NixOS/nixpkgs/160b762eda6d139ac10ae081f8f78d640dd523eb#kubernetes-helm", @@ -350,54 +302,6 @@ } } }, - "operator-sdk@1.34.1": { - "last_modified": "2024-03-22T07:26:23-04:00", - "resolved": "github:NixOS/nixpkgs/a3ed7406349a9335cb4c2a71369b697cecd9d351#operator-sdk", - "source": "devbox-search", - "version": "1.34.1", - "systems": { - "aarch64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/39bndv1fk8rrdi1a0xlfaw5qhgylnzkk-operator-sdk-1.34.1", - "default": true - } - ], - "store_path": "/nix/store/39bndv1fk8rrdi1a0xlfaw5qhgylnzkk-operator-sdk-1.34.1" - }, - "aarch64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/n9ln3a2whzwp0x2ik3rxh10wn7ra85r5-operator-sdk-1.34.1", - "default": true - } - ], - "store_path": "/nix/store/n9ln3a2whzwp0x2ik3rxh10wn7ra85r5-operator-sdk-1.34.1" - }, - "x86_64-darwin": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/y0vi2nvhsgakbvlmbhdpsqdnl83l8q65-operator-sdk-1.34.1", - "default": true - } - ], - "store_path": "/nix/store/y0vi2nvhsgakbvlmbhdpsqdnl83l8q65-operator-sdk-1.34.1" - }, - "x86_64-linux": { - "outputs": [ - { - "name": "out", - "path": "/nix/store/h607xcilqpwsc0mna9bc6yilj4v3q4y3-operator-sdk-1.34.1", - "default": true - } - ], - "store_path": "/nix/store/h607xcilqpwsc0mna9bc6yilj4v3q4y3-operator-sdk-1.34.1" - } - } - }, "python@3.12.2": { "last_modified": "2024-03-22T11:26:23Z", "plugin_version": "0.0.3", diff --git a/examples/commit-message-validation-service/go.mod b/examples/commit-message-validation-service/go.mod index 77de44205cf..c8dc6326042 100644 --- a/examples/commit-message-validation-service/go.mod +++ b/examples/commit-message-validation-service/go.mod @@ -26,9 +26,9 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/net v0.23.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/examples/commit-message-validation-service/go.sum b/examples/commit-message-validation-service/go.sum index 29a1b7816b0..0b4def35e9c 100644 --- a/examples/commit-message-validation-service/go.sum +++ b/examples/commit-message-validation-service/go.sum @@ -91,19 +91,19 @@ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUu golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -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.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-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-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/examples/drools-process-usertasks-quarkus-example/README.md b/examples/drools-process-usertasks-quarkus-example/README.md new file mode 100644 index 00000000000..493e71e7191 --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/README.md @@ -0,0 +1,215 @@ +# Process user task orchestration + +## Description + +A quickstart project shows very typical user task orchestration. It comes with two tasks assigned +to human actors via groups assignments - `managers`. So essentially anyone who is a member of that +group can act on the tasks. Though this example applies four eye principle which essentially means +that user who approved first task cannot approve second one. So there must be always at least two +distinct manager involved. + +This example shows + +- working with user tasks +- four eye principle with user tasks + +

+ +- Diagram Properties (top) +

+ +- Diagram Properties (bottom) +

+ +- First Line Approval (top) +

+ +- First Line Approval (bottom) +

+ +- First Line Approval (Assignments) +

+ +- Second Line Approval +

+ +- Second Line Approval (Assignments) +

+ +## Build and run + +### Prerequisites + +You will need: + +- Java 17+ installed +- Environment variable JAVA_HOME set accordingly +- Maven 3.9.6+ installed + +When using native image compilation, you will also need: + +- GraalVM 19.3+ installed +- Environment variable GRAALVM_HOME set accordingly +- GraalVM native image needs as well native-image extension: https://www.graalvm.org/reference-manual/native-image/ +- Note that GraalVM native image compilation typically requires other packages (glibc-devel, zlib-devel and gcc) to be installed too, please refer to GraalVM installation documentation for more details. + +### Compile and Run in Local Dev Mode + +```sh +mvn clean compile quarkus:dev +``` + +NOTE: With dev mode of Quarkus you can take advantage of hot reload for business assets like processes, rules, decision tables and java code. No need to redeploy or restart your running application. + +### Package and Run in JVM mode + +```sh +mvn clean package +java -jar target/quarkus-app/quarkus-run.jar +``` + +or on windows + +```sh +mvn clean package +java -jar target\quarkus-app\quarkus-run.jar +``` + +### Package and Run using Local Native Image + +Note that this requires GRAALVM_HOME to point to a valid GraalVM installation + +```sh +mvn clean package -Pnative +``` + +To run the generated native executable, generated in `target/`, execute + +```sh +./target/process-usertasks-quarkus-runner +``` + +### OpenAPI (Swagger) documentation + +[Specification at swagger.io](https://swagger.io/docs/specification/about/) + +You can take a look at the [OpenAPI definition](http://localhost:8080/openapi?format=json) - automatically generated and included in this service - to determine all available operations exposed by this service. For easy readability you can visualize the OpenAPI definition file using a UI tool like for example available [Swagger UI](https://editor.swagger.io). + +In addition, various clients to interact with this service can be easily generated using this OpenAPI definition. + +When running in either Quarkus Development or Native mode, we also leverage the [Quarkus OpenAPI extension](https://quarkus.io/guides/openapi-swaggerui#use-swagger-ui-for-development) that exposes [Swagger UI](http://localhost:8080/swagger-ui/) that you can use to look at available REST endpoints and send test requests. + +### Submit a request to start new approval + +To make use of this application it is as simple as putting a sending request to `http://localhost:8080/approvals` with following content + +```json +{ + "traveller": { + "firstName": "John", + "lastName": "Doe", + "email": "jon.doe@example.com", + "nationality": "American", + "address": { + "street": "main street", + "city": "Boston", + "zipCode": "10005", + "country": "US" + } + } +} +``` + +Complete curl command can be found below: + +```sh +curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{"traveller" : { "firstName" : "John", "lastName" : "Doe", "email" : "jon.doe@example.com", "nationality" : "American","address" : { "street" : "main street", "city" : "Boston", "zipCode" : "10005", "country" : "US" }}}' http://localhost:8080/approvals +``` + +### Show active approvals + +```sh +curl -H 'Content-Type:application/json' -H 'Accept:application/json' http://localhost:8080/approvals +``` + +### Show tasks + +```sh +curl -H 'Content-Type:application/json' -H 'Accept:application/json' 'http://localhost:8080/approvals/{uuid}/tasks?user=admin&group=managers' +``` + +where `{uuid}` is the id of the given approval instance + +### Complete first line approval task + +```sh +curl -X POST -d '{"approved" : true}' -H 'Content-Type:application/json' -H 'Accept:application/json' 'http://localhost:8080/approvals/{uuid}/firstLineApproval/{tuuid}?user=admin&group=managers' +``` + +where `{uuid}` is the id of the given approval instance and `{tuuid}` is the id of the task instance + +### Show tasks + +```sh +curl -H 'Content-Type:application/json' -H 'Accept:application/json' 'http://localhost:8080/approvals/{uuid}/tasks?user=admin&group=managers' +``` + +where `{uuid}` is the id of the given approval instance + +This should return empty response as the admin user was the first approver and by that can't be assigned to another one. + +Repeating the request with another user will return task + +```sh +curl -H 'Content-Type:application/json' -H 'Accept:application/json' 'http://localhost:8080/approvals/{uuid}/tasks?user=john&group=managers' +``` + +### Complete second line approval task + +```sh +curl -X POST -d '{"approved" : true}' -H 'Content-Type:application/json' -H 'Accept:application/json' 'http://localhost:8080/approvals/{uuid}/secondLineApproval/{tuuid}?user=john&group=managers' +``` + +where `{uuid}` is the id of the given approval instance and `{tuuid}` is the id of the task instance + +This completes the approval and returns approvals model where both approvals of first and second line can be found, +plus the approver who made the first one. + +```json +{ + "approver": "admin", + "firstLineApproval": true, + "id": "2eeafa82-d631-4554-8d8e-46614cbe3bdf", + "secondLineApproval": true, + "traveller": { + "address": { + "city": "Boston", + "country": "US", + "street": "main street", + "zipCode": "10005" + }, + "email": "jon.doe@example.com", + "firstName": "John", + "lastName": "Doe", + "nationality": "American" + } +} +``` + +You should see a similar message after performing the second line approval after the curl command + +```json +{ + "id": "f498de73-e02d-4829-905e-2f768479a4f1", + "approver": "admin", + "firstLineApproval": true, + "secondLineApproval": true, + "traveller": { + "firstName": "John", + "lastName": "Doe", + "email": "jon.doe@example.com", + "nationality": "American", + "address": { "street": "main street", "city": "Boston", "zipCode": "10005", "country": "US" } + } +} +``` diff --git a/examples/drools-process-usertasks-quarkus-example/docs/images/diagramProperties.png b/examples/drools-process-usertasks-quarkus-example/docs/images/diagramProperties.png new file mode 100644 index 00000000000..585c58f583b Binary files /dev/null and b/examples/drools-process-usertasks-quarkus-example/docs/images/diagramProperties.png differ diff --git a/examples/drools-process-usertasks-quarkus-example/docs/images/diagramProperties3.png b/examples/drools-process-usertasks-quarkus-example/docs/images/diagramProperties3.png new file mode 100644 index 00000000000..df43a371afa Binary files /dev/null and b/examples/drools-process-usertasks-quarkus-example/docs/images/diagramProperties3.png differ diff --git a/examples/drools-process-usertasks-quarkus-example/docs/images/firstLineApprovalUserTask.png b/examples/drools-process-usertasks-quarkus-example/docs/images/firstLineApprovalUserTask.png new file mode 100644 index 00000000000..b705a63b367 Binary files /dev/null and b/examples/drools-process-usertasks-quarkus-example/docs/images/firstLineApprovalUserTask.png differ diff --git a/examples/drools-process-usertasks-quarkus-example/docs/images/firstLineApprovalUserTask2.png b/examples/drools-process-usertasks-quarkus-example/docs/images/firstLineApprovalUserTask2.png new file mode 100644 index 00000000000..65c7dc08469 Binary files /dev/null and b/examples/drools-process-usertasks-quarkus-example/docs/images/firstLineApprovalUserTask2.png differ diff --git a/examples/drools-process-usertasks-quarkus-example/docs/images/firstLineApprovalUserTaskAssignments.png b/examples/drools-process-usertasks-quarkus-example/docs/images/firstLineApprovalUserTaskAssignments.png new file mode 100644 index 00000000000..0bbadf0ac59 Binary files /dev/null and b/examples/drools-process-usertasks-quarkus-example/docs/images/firstLineApprovalUserTaskAssignments.png differ diff --git a/examples/drools-process-usertasks-quarkus-example/docs/images/process.png b/examples/drools-process-usertasks-quarkus-example/docs/images/process.png new file mode 100644 index 00000000000..78eadedc8c0 Binary files /dev/null and b/examples/drools-process-usertasks-quarkus-example/docs/images/process.png differ diff --git a/examples/drools-process-usertasks-quarkus-example/docs/images/secondLineApprovalUserTask.png b/examples/drools-process-usertasks-quarkus-example/docs/images/secondLineApprovalUserTask.png new file mode 100644 index 00000000000..bd3ce5bcce5 Binary files /dev/null and b/examples/drools-process-usertasks-quarkus-example/docs/images/secondLineApprovalUserTask.png differ diff --git a/examples/drools-process-usertasks-quarkus-example/docs/images/secondLineApprovalUserTaskAssignments.png b/examples/drools-process-usertasks-quarkus-example/docs/images/secondLineApprovalUserTaskAssignments.png new file mode 100644 index 00000000000..9ac27a7af04 Binary files /dev/null and b/examples/drools-process-usertasks-quarkus-example/docs/images/secondLineApprovalUserTaskAssignments.png differ diff --git a/examples/drools-process-usertasks-quarkus-example/env/index.js b/examples/drools-process-usertasks-quarkus-example/env/index.js new file mode 100644 index 00000000000..3dd70a342fc --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/env/index.js @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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"); + +module.exports = composeEnv([require("@kie-tools/root-env/env")], { + vars: varsWithName({}), + get env() { + return { + droolsProcessUsertasksQuarkusExample: { + version: require("../package.json").version, + }, + }; + }, +}); diff --git a/examples/drools-process-usertasks-quarkus-example/install.js b/examples/drools-process-usertasks-quarkus-example/install.js new file mode 100644 index 00000000000..9102bb3b499 --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/install.js @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 buildEnv = require("./env"); +const { setup } = require("@kie-tools/maven-config-setup-helper"); + +setup(` + -Drevision=${buildEnv.env.droolsProcessUsertasksQuarkusExample.version} +`); diff --git a/examples/drools-process-usertasks-quarkus-example/package.json b/examples/drools-process-usertasks-quarkus-example/package.json new file mode 100644 index 00000000000..74b65a00968 --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/package.json @@ -0,0 +1,45 @@ +{ + "private": true, + "name": "@kie-tools-examples/drools-process-usertasks-quarkus-example", + "version": "0.0.0", + "description": "", + "license": "Apache-2.0", + "homepage": "https://github.com/apache/incubator-kie-tools", + "repository": { + "type": "git", + "url": "https://github.com/apache/incubator-kie-tools.git" + }, + "bugs": { + "url": "https://github.com/apache/incubator-kie-tools/issues" + }, + "scripts": { + "build:dev": "run-script-if --bool \"$(build-env examples.build)\" --then run-script-os", + "build:dev:darwin:linux": "mvn clean compile -DskipTests", + "build:dev:win32": "pnpm powershell \"mvn clean compile -DskipTests \"", + "build:prod": "pnpm lint && run-script-if --bool \"$(build-env examples.build)\" --then run-script-os", + "build:prod:darwin:linux": "mvn clean compile -DskipTests=$(build-env tests.run --not) -Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)", + "build:prod:win32": "pnpm powershell \"mvn clean compile `-DskipTests `-Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)\"", + "install": "node install.js", + "lint": "echo 'Linting'", + "powershell": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command", + "quarkus:dev": "run-script-os", + "quarkus:dev:darwin:linux": "mvn clean compile quarkus:dev -DskipTests", + "quarkus:dev:win32": "mvn clean compile quarkus:dev -DskipTests", + "start": "pnpm quarkus:dev" + }, + "dependencies": { + "@kie-tools/jbpm-quarkus-devui": "workspace:*", + "@kie-tools/maven-base": "workspace:*" + }, + "devDependencies": { + "@kie-tools/maven-config-setup-helper": "workspace:*", + "@kie-tools/root-env": "workspace:*", + "run-script-os": "^1.1.6" + }, + "kieTools": { + "requiredPreinstalledCliCommands": [ + "java", + "mvn" + ] + } +} \ No newline at end of file diff --git a/examples/drools-process-usertasks-quarkus-example/pom.xml b/examples/drools-process-usertasks-quarkus-example/pom.xml new file mode 100644 index 00000000000..2e4e30a09b3 --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/pom.xml @@ -0,0 +1,99 @@ + + + + 4.0.0 + + org.kie + kie-tools-maven-base + ${revision} + ./node_modules/@kie-tools/maven-base/pom.xml + + drools-process-usertasks-quarkus-example + Kie-Tools Example :: Process with Usertasks Quarkus + Kogito user tasks orchestration - Quarkus + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-resteasy-jackson + + + org.jbpm + jbpm-with-drools-quarkus + + + org.jbpm + jbpm-quarkus-devui + ${project.version} + + + io.quarkus + quarkus-smallrye-openapi + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + io.quarkus + quarkus-smallrye-health + + + org.kie + kie-addons-quarkus-persistence-rocksdb + + + org.kie + kie-addons-quarkus-process-svg + + + + ${project.artifactId} + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus-plugin.version} + + + + build + + + + + + + diff --git a/examples/drools-process-usertasks-quarkus-example/src/main/docker/Dockerfile.jvm b/examples/drools-process-usertasks-quarkus-example/src/main/docker/Dockerfile.jvm new file mode 100644 index 00000000000..ec46ab84c71 --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/src/main/docker/Dockerfile.jvm @@ -0,0 +1,26 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode +# +# Before building the docker image run: +# +# mvn package +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/process-usertasks-quarkus-jvm . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/process-usertasks-quarkus-jvm +# +### +FROM fabric8/java-alpine-openjdk11-jre +ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +ENV AB_ENABLED=jmx_exporter + +COPY target/quarkus-app/lib/ /deployments/lib/ +COPY target/quarkus-app/*.jar /deployments/ +COPY target/quarkus-app/app/ /deployments/app/ +COPY target/quarkus-app/quarkus/ /deployments/quarkus/ + +ENTRYPOINT [ "/deployments/run-java.sh" ] \ No newline at end of file diff --git a/examples/drools-process-usertasks-quarkus-example/src/main/docker/Dockerfile.native b/examples/drools-process-usertasks-quarkus-example/src/main/docker/Dockerfile.native new file mode 100644 index 00000000000..b508cbb1d38 --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/src/main/docker/Dockerfile.native @@ -0,0 +1,22 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode +# +# Before building the docker image run: +# +# mvn package -Pnative -Dnative-image.docker-build=true +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.native -t quarkus/kogito-infinispan-persistence-quarkus . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/kogito-infinispan-persistence-quarkus +# +### +FROM registry.access.redhat.com/ubi8/ubi-minimal +WORKDIR /work/ +COPY target/*-runner /work/application +RUN chmod 775 /work +EXPOSE 8080 +CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] \ No newline at end of file diff --git a/examples/drools-process-usertasks-quarkus-example/src/main/java/org/acme/travels/Address.java b/examples/drools-process-usertasks-quarkus-example/src/main/java/org/acme/travels/Address.java new file mode 100644 index 00000000000..662dfa9b9f7 --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/src/main/java/org/acme/travels/Address.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.acme.travels; + +public class Address { + + private String street; + private String city; + private String zipCode; + private String country; + + public Address() { + + } + + public Address(String street, String city, String zipCode, String country) { + super(); + this.street = street; + this.city = city; + this.zipCode = zipCode; + this.country = country; + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + @Override + public String toString() { + return "Address [street=" + street + ", city=" + city + ", zipCode=" + zipCode + ", country=" + country + "]"; + } +} diff --git a/examples/drools-process-usertasks-quarkus-example/src/main/java/org/acme/travels/Traveller.java b/examples/drools-process-usertasks-quarkus-example/src/main/java/org/acme/travels/Traveller.java new file mode 100644 index 00000000000..c24685803d2 --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/src/main/java/org/acme/travels/Traveller.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.acme.travels; + +public class Traveller { + + private String firstName; + private String lastName; + private String email; + private String nationality; + private Address address; + + public Traveller() { + + } + + public Traveller(String firstName, String lastName, String email, String nationality, Address address) { + super(); + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + this.nationality = nationality; + this.address = address; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getNationality() { + return nationality; + } + + public void setNationality(String nationality) { + this.nationality = nationality; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + @Override + public String toString() { + return "Traveller [firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + ", nationality=" + + nationality + ", address=" + address + "]"; + } + +} diff --git a/examples/drools-process-usertasks-quarkus-example/src/main/resources/META-INF/processSVG/approvals.svg b/examples/drools-process-usertasks-quarkus-example/src/main/resources/META-INF/processSVG/approvals.svg new file mode 100644 index 00000000000..b5ce19ebbca --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/src/main/resources/META-INF/processSVG/approvals.svg @@ -0,0 +1 @@ +EndStartProcessSecond Line Approval First Line Approval \ No newline at end of file diff --git a/examples/drools-process-usertasks-quarkus-example/src/main/resources/META-INF/resources/index.html b/examples/drools-process-usertasks-quarkus-example/src/main/resources/META-INF/resources/index.html new file mode 100644 index 00000000000..8e3a2e791f8 --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/src/main/resources/META-INF/resources/index.html @@ -0,0 +1,174 @@ + + + + + + kogito-infinispan-persistence-quarkus - 1.0-SNAPSHOT + + + + + +
+
+

Congratulations, you have created a new Quarkus application.

+ +

Why do you see this?

+ +

+ This page is served by Quarkus. The source is in + src/main/resources/META-INF/resources/index.html. +

+ +

What can I do from here?

+ +

+ If not already done, run the application in dev mode using: mvn compile quarkus:dev. +

+ + +

How do I get rid of this page?

+

Just delete the src/main/resources/META-INF/resources/index.html file.

+
+
+
+

Application

+
    +
  • GroupId: org.acme
  • +
  • ArtifactId: kogito-infinispan-persistence-quarkus
  • +
  • Version: 1.0-SNAPSHOT
  • +
  • Quarkus Version: 0.19.1
  • +
+
+ +
+
+ + diff --git a/examples/drools-process-usertasks-quarkus-example/src/main/resources/application.properties b/examples/drools-process-usertasks-quarkus-example/src/main/resources/application.properties new file mode 100644 index 00000000000..64a5d9c9500 --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/src/main/resources/application.properties @@ -0,0 +1,28 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# Packaging +# quarkus.package.type=fast-jar + +quarkus.smallrye-openapi.path=/docs/openapi.json +quarkus.swagger-ui.always-include=true + +jbpm.devui.users.admin.groups=managers +jbpm.devui.users.manager.groups=managers +jbpm.devui.users.john.groups=managers \ No newline at end of file diff --git a/examples/drools-process-usertasks-quarkus-example/src/main/resources/org/acme/travels/approval.bpmn b/examples/drools-process-usertasks-quarkus-example/src/main/resources/org/acme/travels/approval.bpmn new file mode 100644 index 00000000000..275d148f7ac --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/src/main/resources/org/acme/travels/approval.bpmn @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _9EAFE6C1-69B4-4908-B764-EF3C4A55BEE3 + _C13522F1-230A-4C26-B5A9-533A5D9FEE9D + + + + + + + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_TaskNameInputX + _8B62D3CA-5D03-4B2B-832B-126469288BB4_travellerInputX + _8B62D3CA-5D03-4B2B-832B-126469288BB4_SkippableInputX + _8B62D3CA-5D03-4B2B-832B-126469288BB4_GroupIdInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_ActorIdOutputX + _8B62D3CA-5D03-4B2B-832B-126469288BB4_approvedOutputX + + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_TaskNameInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_TaskNameInputX + + + + traveller + _8B62D3CA-5D03-4B2B-832B-126469288BB4_travellerInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_SkippableInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_SkippableInputX + + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_GroupIdInputX + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_GroupIdInputX + + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_ActorIdOutputX + approver + + + _8B62D3CA-5D03-4B2B-832B-126469288BB4_approvedOutputX + firstLineApproval + + + + manager + + + + + + + + + + _C13522F1-230A-4C26-B5A9-533A5D9FEE9D + _078F46FB-B7A1-4DBB-BE9A-75C7CB0CCD03 + + + + + + + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_TaskNameInputX + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_ExcludedOwnerIdInputX + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_travellerInputX + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_SkippableInputX + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_GroupIdInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_approvedOutputX + + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_TaskNameInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_TaskNameInputX + + + + approver + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_ExcludedOwnerIdInputX + + + traveller + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_travellerInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_SkippableInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_SkippableInputX + + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_GroupIdInputX + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_GroupIdInputX + + + + _0DBFABE8-92B0-46E6-B52E-A9593AFA4371_approvedOutputX + secondLineApproval + + + + + + + + + _9EAFE6C1-69B4-4908-B764-EF3C4A55BEE3 + + + + + + + + _078F46FB-B7A1-4DBB-BE9A-75C7CB0CCD03 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + _F0jB8En5EeqlfsIhq1UCRQ + _F0jB8En5EeqlfsIhq1UCRQ + + diff --git a/examples/drools-process-usertasks-quarkus-example/src/test/java/org/acme/travels/quarkus/ApprovalsProcessTest.java b/examples/drools-process-usertasks-quarkus-example/src/test/java/org/acme/travels/quarkus/ApprovalsProcessTest.java new file mode 100644 index 00000000000..a5a41285c3d --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/src/test/java/org/acme/travels/quarkus/ApprovalsProcessTest.java @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.acme.travels.quarkus; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.acme.travels.Address; +import org.acme.travels.Traveller; +import org.jbpm.process.instance.impl.humantask.HumanTaskTransition; +import org.jbpm.process.instance.impl.humantask.phases.Claim; +import org.jbpm.process.instance.impl.workitem.Complete; +import org.junit.jupiter.api.Test; +import org.kie.kogito.Model; +import org.kie.kogito.auth.IdentityProviders; +import org.kie.kogito.auth.SecurityPolicy; +import org.kie.kogito.process.Process; +import org.kie.kogito.process.ProcessInstance; +import org.kie.kogito.process.WorkItem; + +import io.quarkus.test.junit.QuarkusTest; + +import jakarta.inject.Inject; +import jakarta.inject.Named; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@QuarkusTest +public class ApprovalsProcessTest { + + @Named("approvals") + @Inject + Process approvalsProcess; + + @Test + public void testApprovalProcess() { + + assertNotNull(approvalsProcess); + + Model m = approvalsProcess.createModel(); + Map parameters = new HashMap<>(); + parameters.put("traveller", new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US"))); + m.fromMap(parameters); + + ProcessInstance processInstance = approvalsProcess.createInstance(m); + processInstance.start(); + assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_ACTIVE, processInstance.status()); + + SecurityPolicy policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("managers"))); + + processInstance.workItems(policy); + + List workItems = processInstance.workItems(policy); + assertEquals(1, workItems.size()); + Map results = new HashMap<>(); + results.put("approved", true); + processInstance.completeWorkItem(workItems.get(0).getId(), results, policy); + + workItems = processInstance.workItems(policy); + assertEquals(0, workItems.size()); + + policy = SecurityPolicy.of(IdentityProviders.of("john", Collections.singletonList("managers"))); + + processInstance.workItems(policy); + + workItems = processInstance.workItems(policy); + assertEquals(1, workItems.size()); + + results.put("approved", false); + processInstance.completeWorkItem(workItems.get(0).getId(), results, policy); + assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status()); + + Model result = (Model) processInstance.variables(); + assertEquals(4, result.toMap().size()); + assertEquals(result.toMap().get("approver"), "admin"); + assertEquals(result.toMap().get("firstLineApproval"), true); + assertEquals(result.toMap().get("secondLineApproval"), false); + } + + @Test + public void testApprovalProcessViaPhases() { + + assertNotNull(approvalsProcess); + + Model m = approvalsProcess.createModel(); + Map parameters = new HashMap<>(); + parameters.put("traveller", new Traveller("John", "Doe", "john.doe@example.com", "American", new Address("main street", "Boston", "10005", "US"))); + m.fromMap(parameters); + + ProcessInstance processInstance = approvalsProcess.createInstance(m); + processInstance.start(); + assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_ACTIVE, processInstance.status()); + + SecurityPolicy policy = SecurityPolicy.of(IdentityProviders.of("admin", Collections.singletonList("managers"))); + + processInstance.workItems(policy); + + List workItems = processInstance.workItems(policy); + assertEquals(1, workItems.size()); + + processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); + processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", true), policy)); + + workItems = processInstance.workItems(policy); + assertEquals(0, workItems.size()); + + policy = SecurityPolicy.of(IdentityProviders.of("john", Collections.singletonList("managers"))); + + processInstance.workItems(policy); + + workItems = processInstance.workItems(policy); + assertEquals(1, workItems.size()); + + processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Claim.ID, null, policy)); + processInstance.transitionWorkItem(workItems.get(0).getId(), new HumanTaskTransition(Complete.ID, Collections.singletonMap("approved", false), policy)); + + assertEquals(org.kie.api.runtime.process.ProcessInstance.STATE_COMPLETED, processInstance.status()); + + Model result = (Model) processInstance.variables(); + assertEquals(4, result.toMap().size()); + assertEquals(result.toMap().get("approver"), "admin"); + assertEquals(result.toMap().get("firstLineApproval"), true); + assertEquals(result.toMap().get("secondLineApproval"), false); + } +} diff --git a/examples/drools-process-usertasks-quarkus-example/src/test/resources/application.properties b/examples/drools-process-usertasks-quarkus-example/src/test/resources/application.properties new file mode 100644 index 00000000000..e764de0f97d --- /dev/null +++ b/examples/drools-process-usertasks-quarkus-example/src/test/resources/application.properties @@ -0,0 +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. +# + +# Quarkus +quarkus.http.test-port=0 +kogito.persistence.rocksdb.clean=true +kogito.persistence.rocksdb.data.dir=pepe \ No newline at end of file diff --git a/examples/sonataflow-greeting-quarkus-example/README.md b/examples/sonataflow-greeting-quarkus-example/README.md new file mode 100644 index 00000000000..987ca4eab22 --- /dev/null +++ b/examples/sonataflow-greeting-quarkus-example/README.md @@ -0,0 +1,152 @@ +# KIE-Tools SonataFlow - Greeting Example + +## Description + +This example contains two simple greeting workflow services. +The services are described using both JSON and YAML formats as defined in the +[CNCF Serverless Workflow specification](https://github.com/cncf/wg-serverless/tree/main/workflow/spec). + +The workflow expects as JSON input containing the name of the person to greet, and the language in +which to greet them in +(see details in the [Submit a request](#Submit-a-request) section). + +The workflow starts with a SWITCH state, which is like a gateway. The switch state +decides which language to greet the person in based on the workflow input "language" parameter. +Depending on the language the workflow then injects the language-based greeting via RELAY states. +Relay states are just "pass" states which do not execute any functions and only have the ability +to inject data into the workflow. +The inject states then transition to the OPERATION state which call a "sysout" function passing it +input parameter containing the greeting and the name of the person to greet: "$.greeting $.name". +The function then prints out the greeting to the console. + +## Installing and Running + +### Prerequisites + +You will need: + +- Java 11+ installed +- Environment variable JAVA_HOME set accordingly +- Maven 3.8.6+ installed + +When using native image compilation, you will also need: + +- [GraalVm](https://www.graalvm.org/downloads/) 19.3.1+ installed +- Environment variable GRAALVM_HOME set accordingly +- Note that GraalVM native image compilation typically requires other packages (glibc-devel, zlib-devel and gcc) to be installed too. You also need 'native-image' installed in GraalVM (using 'gu install native-image'). Please refer to [GraalVM installation documentation](https://www.graalvm.org/docs/reference-manual/aot-compilation/#prerequisites) for more details. + +### Compile and Run in Local Dev Mode + +```sh +mvn clean package quarkus:dev +``` + +### Compile and Run in JVM mode + +```sh +mvn clean package +java -jar target/quarkus-app/quarkus-run.jar +``` + +or on windows + +```sh +mvn clean package +java -jar target\quarkus-app\quarkus-run.jar +``` + +### Compile and Run using Local Native Image + +Note that this requires GRAALVM_HOME to point to a valid GraalVM installation + +```sh +mvn clean package -Pnative +``` + +To run the generated native executable, generated in `target/`, execute + +```sh +./target/sw-quarkus-greeting-{version}-runner +``` + +### Submit a request + +The service based on the JSON workflow definition can be access by sending a request to http://localhost:8080/jsongreet' +with following content + +```json +{ + "name": "John", + "language": "English" +} +``` + +Complete curl command can be found below: + +```sh +curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{"name": "John", "language": "English"}' http://localhost:8080/jsongreet +``` + +Log after curl executed: + +```json +{ + "id": "541a5363-1667-4f6d-a8b4-1299eba81eac", + "workflowdata": { "name": "John", "language": "English", "greeting": "Hello from JSON Workflow, " } +} +``` + +In Quarkus you should see the log message printed: + +```text +Hello from JSON Workflow, John +``` + +If you would like to greet the person in Spanish, we need to pass the following data on workflow start: + +```json +{ + "name": "John", + "language": "Spanish" +} +``` + +Complete curl command can be found below: + +```sh +curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{"name": "John", "language": "Spanish"}' http://localhost:8080/jsongreet +``` + +In Quarkus you should now see the log message printed: + +```text +Saludos desde JSON Workflow, John +``` + +Similarly, the service based on the YAML workflow definition can be access by sending a request to http://localhost:8080/yamlgreet' +using the same content: + +```json +{ + "name": "John", + "language": "English" +} +``` + +Complete curl command can be found below: + +```sh +curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{"name": "John", "language": "English"}' http://localhost:8080/yamlgreet +``` + +In Quarkus you should see the log message: + +```text +Hello from YAML Workflow, John +``` + +You can also change the language parameter value to "Spanish" to get the greeting in Spanish. + +## Deploying with Kogito Operator + +In the [`operator`](operator) directory you'll find the custom resources needed to deploy this example on OpenShift with the [Kogito Operator](https://docs.jboss.org/kogito/release/latest/html_single/#chap_kogito-deploying-on-openshift). diff --git a/examples/sonataflow-greeting-quarkus-example/env/index.js b/examples/sonataflow-greeting-quarkus-example/env/index.js new file mode 100644 index 00000000000..7767297ccd4 --- /dev/null +++ b/examples/sonataflow-greeting-quarkus-example/env/index.js @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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"); + +module.exports = composeEnv([require("@kie-tools/root-env/env")], { + vars: varsWithName({}), + get env() { + return { + sonataflowGreetingQuarkus: { + version: require("../package.json").version, + }, + }; + }, +}); diff --git a/examples/sonataflow-greeting-quarkus-example/install.js b/examples/sonataflow-greeting-quarkus-example/install.js new file mode 100644 index 00000000000..7230ea08fa9 --- /dev/null +++ b/examples/sonataflow-greeting-quarkus-example/install.js @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 buildEnv = require("./env"); +const { setup } = require("@kie-tools/maven-config-setup-helper"); + +setup(` + -Drevision=${buildEnv.env.sonataflowGreetingQuarkus.version} +`); diff --git a/examples/sonataflow-greeting-quarkus-example/package.json b/examples/sonataflow-greeting-quarkus-example/package.json new file mode 100644 index 00000000000..91d6b0e68aa --- /dev/null +++ b/examples/sonataflow-greeting-quarkus-example/package.json @@ -0,0 +1,45 @@ +{ + "private": true, + "name": "@kie-tools-examples/sonataflow-greeting-quarkus-example", + "version": "0.0.0", + "description": "", + "license": "Apache-2.0", + "homepage": "https://github.com/apache/incubator-kie-tools", + "repository": { + "type": "git", + "url": "https://github.com/apache/incubator-kie-tools.git" + }, + "bugs": { + "url": "https://github.com/apache/incubator-kie-tools/issues" + }, + "scripts": { + "build:dev": "run-script-if --bool \"$(build-env examples.build)\" --then run-script-os", + "build:dev:darwin:linux": "mvn clean package -DskipTests", + "build:dev:win32": "pnpm powershell \"mvn clean package -DskipTests \"", + "build:prod": "pnpm lint && run-script-if --bool \"$(build-env examples.build)\" --then run-script-os", + "build:prod:darwin:linux": "mvn clean package -DskipTests=$(build-env tests.run --not) -Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)", + "build:prod:win32": "pnpm powershell \"mvn clean package `-DskipTests `-Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)\"", + "install": "node install.js", + "lint": "echo 'Linting'", + "powershell": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command", + "quarkus:dev": "run-script-os", + "quarkus:dev:darwin:linux": "mvn clean package quarkus:dev -DskipTests", + "quarkus:dev:win32": "mvn clean package quarkus:dev -DskipTests", + "start": "pnpm quarkus:dev" + }, + "dependencies": { + "@kie-tools/maven-base": "workspace:*", + "@kie-tools/sonataflow-quarkus-devui": "workspace:*" + }, + "devDependencies": { + "@kie-tools/maven-config-setup-helper": "workspace:*", + "@kie-tools/root-env": "workspace:*", + "run-script-os": "^1.1.6" + }, + "kieTools": { + "requiredPreinstalledCliCommands": [ + "java", + "mvn" + ] + } +} \ No newline at end of file diff --git a/examples/sonataflow-greeting-quarkus-example/pom.xml b/examples/sonataflow-greeting-quarkus-example/pom.xml new file mode 100644 index 00000000000..0d083e6e395 --- /dev/null +++ b/examples/sonataflow-greeting-quarkus-example/pom.xml @@ -0,0 +1,156 @@ + + + + 4.0.0 + + + org.kie + kie-tools-maven-base + ${revision} + ./node_modules/@kie-tools/maven-base/pom.xml + + + org.apache.kie.sonataflow.examples + sonataflow-greeting-quarkus-example + ${revision} + + KIE Tools Example :: SonataFlow Greeting :: Quarkus + SonataFlow Example - Quarkus + + + + org.apache.kie.sonataflow + sonataflow-quarkus + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-resteasy-jackson + + + io.quarkus + quarkus-jsonp + + + org.apache.kie.sonataflow + sonataflow-quarkus-devui + ${project.version} + + + org.kie + kie-addons-quarkus-source-files + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + io.quarkus + quarkus-smallrye-health + + + + ${project.artifactId} + + + maven-compiler-plugin + ${compiler-plugin.version} + + ${maven.compiler.release} + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus-plugin.version} + + + + build + + + + + + maven-failsafe-plugin + ${version.failsafe.plugin} + + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + integration-test + verify + + + + + + + + + container + + + container + + + + container + + + + io.quarkus + quarkus-container-image-jib + + + + + native + + + native + + + + native + + + + diff --git a/examples/sonataflow-greeting-quarkus-example/src/main/resources/application.properties b/examples/sonataflow-greeting-quarkus-example/src/main/resources/application.properties new file mode 100644 index 00000000000..bb5e12d81ec --- /dev/null +++ b/examples/sonataflow-greeting-quarkus-example/src/main/resources/application.properties @@ -0,0 +1,32 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# Packaging +# quarkus.package.type=fast-jar +quarkus.native.native-image-xmx=8g + +# profile to pack this example into a container, to use it execute activate the maven container profile, -Dcontainer +%container.quarkus.container-image.build=true +%container.quarkus.container-image.push=false +%container.quarkus.container-image.group=${USER} +%container.quarkus.container-image.registry=dev.local +%container.quarkus.container-image.tag=1.0-SNAPSHOT +%container.quarkus.jib.jvm-entrypoint=/home/kogito/kogito-app-launch.sh +%container.quarkus.jib.base-jvm-image=quay.io/kiegroup/kogito-runtime-jvm:latest +%container.quarkus.jib.working-directory=/home/kogito/bin diff --git a/examples/sonataflow-greeting-quarkus-example/src/main/resources/jsongreet.sw.json b/examples/sonataflow-greeting-quarkus-example/src/main/resources/jsongreet.sw.json new file mode 100644 index 00000000000..5998a47f30b --- /dev/null +++ b/examples/sonataflow-greeting-quarkus-example/src/main/resources/jsongreet.sw.json @@ -0,0 +1,65 @@ +{ + "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": true + } + ] +} diff --git a/examples/sonataflow-greeting-quarkus-example/src/main/resources/yamlgreet.sw.yml b/examples/sonataflow-greeting-quarkus-example/src/main/resources/yamlgreet.sw.yml new file mode 100644 index 00000000000..3eb1f715fed --- /dev/null +++ b/examples/sonataflow-greeting-quarkus-example/src/main/resources/yamlgreet.sw.yml @@ -0,0 +1,40 @@ +id: yamlgreet +version: "1.0" +name: Greeting workflow +description: YAML based greeting workflow +expressionLang: jsonpath +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 YAML Workflow, " + transition: GreetPerson + - name: GreetInSpanish + type: inject + data: + greeting: "Saludos desde YAML Workflow, " + transition: GreetPerson + - name: GreetPerson + type: operation + actions: + - name: greetAction + functionRef: + refName: greetFunction + arguments: + message: "$.greeting $.name" + end: + terminate: true diff --git a/examples/sonataflow-greeting-quarkus-example/src/test/java/org/kie/kogito/examples/GreetRestIT.java b/examples/sonataflow-greeting-quarkus-example/src/test/java/org/kie/kogito/examples/GreetRestIT.java new file mode 100644 index 00000000000..8c1bd391914 --- /dev/null +++ b/examples/sonataflow-greeting-quarkus-example/src/test/java/org/kie/kogito/examples/GreetRestIT.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.kie.kogito.examples; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.containsString; + +@QuarkusIntegrationTest +class GreetRestIT { + + @Test + void testEnglish() { + given() + .contentType(ContentType.JSON) + .accept(ContentType.JSON) + .body("{\"name\" : \"John\", \"language\":\"English\"}").when() + .post("/jsongreet") + .then() + .statusCode(201) + .body("workflowdata.greeting", containsString("Hello")); + } + + @Test + void testSpanish() { + given() + .contentType(ContentType.JSON) + .accept(ContentType.JSON) + .body("{\"name\" : \"Javierito\", \"language\":\"Spanish\"}").when() + .post("/jsongreet") + .then() + .statusCode(201) + .body("workflowdata.greeting", containsString("Saludos")); + } + + @Test + void testDefaultLanguage() { + given() + .contentType(ContentType.JSON) + .accept(ContentType.JSON) + .body("{\"name\" : \"John\"}").when() + .post("/jsongreet") + .then() + .statusCode(201) + .body("workflowdata.greeting", containsString("Hello")); + } + + @Test + void testUnsupportedLanguage() { + given() + .contentType(ContentType.JSON) + .accept(ContentType.JSON) + .body("{\"name\" : \"Jan\", \"language\":\"Czech\"}").when() + .post("/jsongreet") + .then() + .statusCode(201) + .body("workflowdata.greeting", containsString("Hello")); + } +} diff --git a/packages/boxed-expression-component/.storybook/main.ts b/packages/boxed-expression-component/.storybook/main.ts index c2c55e046da..07e68064701 100644 --- a/packages/boxed-expression-component/.storybook/main.ts +++ b/packages/boxed-expression-component/.storybook/main.ts @@ -18,6 +18,7 @@ */ import { baseConfig } from "@kie-tools/storybook-base/dist/config/baseConfig"; +import common from "@kie-tools-core/webpack-base/webpack.common.config"; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore @@ -25,7 +26,7 @@ import { env } from "../env"; const buildEnv: any = env; // build-env is not typed const config = { - ...baseConfig(buildEnv.webpack.dev), + ...baseConfig(buildEnv.webpack.dev, common(buildEnv.webpack)), staticDirs: ["../stories/__assets__"], }; diff --git a/packages/boxed-expression-component/.storybook/manager.ts b/packages/boxed-expression-component/.storybook/manager.ts index 8c06121c273..fb2eb76fe5f 100644 --- a/packages/boxed-expression-component/.storybook/manager.ts +++ b/packages/boxed-expression-component/.storybook/manager.ts @@ -22,4 +22,7 @@ import { KieToolsTheme } from "@kie-tools/storybook-base/dist/config/theme"; addons.setConfig({ theme: KieToolsTheme, + // Disable Storybook keyboard shortcuts. + // The shortcuts conflicts with the Monaco editor, impacting its behavior + enableShortcuts: false, }); diff --git a/packages/boxed-expression-component/src/expressions/ContextExpression/ContextEntryExpressionCell.tsx b/packages/boxed-expression-component/src/expressions/ContextExpression/ContextEntryExpressionCell.tsx index ea9abc4c15e..62faae7d859 100644 --- a/packages/boxed-expression-component/src/expressions/ContextExpression/ContextEntryExpressionCell.tsx +++ b/packages/boxed-expression-component/src/expressions/ContextExpression/ContextEntryExpressionCell.tsx @@ -18,16 +18,18 @@ */ import * as React from "react"; -import { useCallback } from "react"; -import { BeeTableCellProps, BoxedContext } from "../../api"; +import { useCallback, useEffect } from "react"; +import { BeeTableCellProps, BoxedContext, BoxedExpression } from "../../api"; import { NestedExpressionDispatchContextProvider, OnSetExpression, + useBoxedExpressionEditor, useBoxedExpressionEditorDispatch, } from "../../BoxedExpressionEditorContext"; import { ExpressionContainer } from "../ExpressionDefinitionRoot/ExpressionContainer"; import { ROWTYPE } from "./ContextExpression"; import "./ContextEntryExpressionCell.css"; +import { useBeeTableSelectableCellRef } from "../../selection/BeeTableSelectionContext"; export const ContextEntryExpressionCell: React.FunctionComponent> = ({ data, @@ -35,8 +37,15 @@ export const ContextEntryExpressionCell: React.FunctionComponent { const { setExpression } = useBoxedExpressionEditorDispatch(); - const { variable, expression, index } = data[rowIndex]; + const { isActive } = useBeeTableSelectableCellRef(rowIndex, columnIndex, undefined); + const { beeGwtService } = useBoxedExpressionEditor(); + + useEffect(() => { + if (isActive) { + beeGwtService?.selectObject((expression as BoxedExpression)?.["@_id"]); + } + }, [beeGwtService, columnIndex, expression, isActive]); const onSetExpression = useCallback( ({ getNewExpression }) => { @@ -47,6 +56,7 @@ export const ContextEntryExpressionCell: React.FunctionComponent { return [ - , + , , ]; - }, [contextExpression]); + }, [contextExpression, parentElementId]); const getDefaultContextEntry = useCallback( (name?: string): DMN15__tContextEntry => { @@ -284,6 +284,7 @@ export function ContextExpression({ "@_id": generateUuid(), expression: undefined!, // SPEC DISCREPANCY: Starting without an expression gives users the ability to select the expression type. variable: { + "@_id": generateUuid(), "@_name": variableName, "@_typeRef": DmnBuiltInDataType.Undefined, description: { __$$text: "" }, @@ -509,7 +510,7 @@ export function solveResultAndEntriesIndex({ return { isResultOperation, hasResultEntry, resultIndex, entryIndex }; } -export function ContextResultInfoCell() { +export function ContextResultInfoCell(props: { parentElementId: string }) { const { containerCellCoordinates } = useBeeTableCoordinates(); const value = useMemo(() => { @@ -529,11 +530,12 @@ export function ContextResultInfoCell() { const { beeGwtService } = useBoxedExpressionEditor(); + // Selecting the context result cell should be the parent data type useEffect(() => { if (isActive) { - beeGwtService?.selectObject(""); + beeGwtService?.selectObject(props.parentElementId); } - }, [beeGwtService, isActive]); + }, [beeGwtService, isActive, props.parentElementId]); return
{value}
; } diff --git a/packages/boxed-expression-component/src/expressions/DecisionTableExpression/DecisionTableExpression.tsx b/packages/boxed-expression-component/src/expressions/DecisionTableExpression/DecisionTableExpression.tsx index 9b78b091e1a..c9af257bcc4 100644 --- a/packages/boxed-expression-component/src/expressions/DecisionTableExpression/DecisionTableExpression.tsx +++ b/packages/boxed-expression-component/src/expressions/DecisionTableExpression/DecisionTableExpression.tsx @@ -60,9 +60,11 @@ import { DMN15__tDecisionRule, DMN15__tHitPolicy, DMN15__tInputClause, + DMN15__tLiteralExpression, DMN15__tOutputClause, DMN15__tRuleAnnotation, DMN15__tRuleAnnotationClause, + DMN15__tUnaryTests, } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; import "./DecisionTableExpression.css"; import { Unpacked } from "../../tsExt/tsExt"; @@ -420,7 +422,10 @@ export function DecisionTableExpression({ return getColumnsAtLastLevel(beeTableColumns).reduce( (tableRow: ROWTYPE, column, columnIndex) => { - tableRow[column.accessor] = ruleRow[columnIndex]?.text?.__$$text ?? ""; + tableRow[column.accessor] = { + id: (ruleRow[columnIndex] as DMN15__tUnaryTests & DMN15__tLiteralExpression)?.["@_id"] ?? "", + content: ruleRow[columnIndex]?.text?.__$$text ?? "", + }; return tableRow; }, { id: rule["@_id"] } diff --git a/packages/boxed-expression-component/src/expressions/ExpressionDefinitionRoot/ExpressionContainer.tsx b/packages/boxed-expression-component/src/expressions/ExpressionDefinitionRoot/ExpressionContainer.tsx index 884d9c10b4d..e5108118450 100644 --- a/packages/boxed-expression-component/src/expressions/ExpressionDefinitionRoot/ExpressionContainer.tsx +++ b/packages/boxed-expression-component/src/expressions/ExpressionDefinitionRoot/ExpressionContainer.tsx @@ -53,11 +53,12 @@ export const ExpressionContainer: React.FunctionComponent { if (isActive) { - beeGwtService?.selectObject(""); + beeGwtService?.selectObject(expression?.["@_id"]); } - }, [beeGwtService, isActive]); + }, [beeGwtService, isActive, expression]); const expressionTypeRef = expression?.["@_typeRef"]; diff --git a/packages/boxed-expression-component/src/expressions/ExpressionDefinitionRoot/ExpressionDefinitionLogicTypeSelector.tsx b/packages/boxed-expression-component/src/expressions/ExpressionDefinitionRoot/ExpressionDefinitionLogicTypeSelector.tsx index c997c59b639..cd097f15429 100644 --- a/packages/boxed-expression-component/src/expressions/ExpressionDefinitionRoot/ExpressionDefinitionLogicTypeSelector.tsx +++ b/packages/boxed-expression-component/src/expressions/ExpressionDefinitionRoot/ExpressionDefinitionLogicTypeSelector.tsx @@ -58,6 +58,8 @@ import "./ExpressionDefinitionLogicTypeSelector.css"; import { NavigationKeysUtils } from "../../keysUtils/keyUtils"; import { ConditionalExpression } from "../ConditionalExpression/ConditionalExpression"; import { IteratorExpressionComponent } from "../IteratorExpression/IteratorExpressionComponent"; +import { FilterExpressionComponent } from "../FilterExpression/FilterExpressionComponent"; +import FilterIcon from "@patternfly/react-icons/dist/esm/icons/filter-icon"; export interface ExpressionDefinitionLogicTypeSelectorProps { /** Expression properties */ @@ -102,7 +104,7 @@ export function ExpressionDefinitionLogicTypeSelector({ "for", "every", "some", - // "filter", + "filter", ], [hideDmn14BoxedExpressions, isNested] ); @@ -142,7 +144,9 @@ export function ExpressionDefinitionLogicTypeSelector({ ); case "filter": - return <>; + return ( + + ); default: assertUnreachable(logicType); } @@ -248,7 +252,7 @@ export function ExpressionDefinitionLogicTypeSelector({ case "some": return ; case "filter": - return <>; + return ; default: assertUnreachable(logicType); } @@ -343,7 +347,7 @@ export function ExpressionDefinitionLogicTypeSelector({ case "for": return ( "A boxed iterator offers a visual representation of an iterator statement. " + - 'For the for loop, the right part of the "for" displays the iterator variable name. The second row holds an expression representing the collection that will be iterated over. The expression in the "in" row MUST resolve to a collection.' + + 'For the "for" loop, the right part of the "for" displays the iterator variable name. The second row holds an expression representing the collection that will be iterated over. The expression in the "in" row MUST resolve to a collection.' + " The last row contains the expression that will process each element of the collection." ); @@ -351,14 +355,20 @@ export function ExpressionDefinitionLogicTypeSelector({ return ( "A boxed iterator offers a visual representation of an iterator statement. " + 'For the "every" loop, the right part of the "every" displays the iterator variable name. The second row holds an expression representing the collection that will be iterated over. The expression in the "in" row MUST resolve to a collection.' + - "The last line is an expression that will be evaluated on each item. The expression defined in the satisfies MUST resolve to a boolean." + 'The last line is an expression that will be evaluated on each item. The expression defined in the "satisfies" MUST resolve to a boolean.' ); case "some": return ( "A boxed iterator offers a visual representation of an iterator statement. " + 'For the "some" loop, the right part of the "some" displays the iterator variable name. The second row holds an expression representing the collection that will be iterated over. The expression in the "in" row MUST resolve to a collection. ' + - "The last line is an expression that will be evaluated on each item. The expression defined in the satisfies MUST resolve to a boolean." + 'The last line is an expression that will be evaluated on each item. The expression defined in the "satisfies" MUST resolve to a boolean.' + ); + case "filter": + return ( + "A boxed filter offers a visual representation of collection filtering. The top part is an expression that is the collection " + + "to be filtered. The bottom part, between the square brackets, holds the filter expression." ); + default: return ""; } diff --git a/packages/boxed-expression-component/src/expressions/FilterExpression/FilterExpression.css b/packages/boxed-expression-component/src/expressions/FilterExpression/FilterExpression.css new file mode 100644 index 00000000000..44d66b203e8 --- /dev/null +++ b/packages/boxed-expression-component/src/expressions/FilterExpression/FilterExpression.css @@ -0,0 +1,22 @@ +.filter-expression-cell { + display: flex; + align-content: center; +} + +.filter-expression-cell .bracket-sign-container { + background-color: var(--pf-global--palette--black-200); + width: 20px; + min-width: 20px; + max-width: 20px; + color: var(--pf-global--palette--black-600); + font-family: Menlo, monospace; + display: flex; + align-content: center; + align-items: center; +} + +.bracket-sign { + width: 20px; + min-width: 20px; + max-width: 20px; +} diff --git a/packages/boxed-expression-component/src/expressions/FilterExpression/FilterExpressionCollectionCell.tsx b/packages/boxed-expression-component/src/expressions/FilterExpression/FilterExpressionCollectionCell.tsx new file mode 100644 index 00000000000..833357dce75 --- /dev/null +++ b/packages/boxed-expression-component/src/expressions/FilterExpression/FilterExpressionCollectionCell.tsx @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useCallback } from "react"; +import { BeeTableCellProps, BoxedFilter } from "../../api"; +import { + NestedExpressionDispatchContextProvider, + useBoxedExpressionEditorDispatch, +} from "../../BoxedExpressionEditorContext"; +import { ExpressionContainer } from "../ExpressionDefinitionRoot/ExpressionContainer"; +import { ROWTYPE } from "./FilterExpressionComponent"; +import "./FilterExpression.css"; + +export function FilterExpressionCollectionCell({ + rowIndex, + data: items, + columnIndex, + parentElementId, +}: BeeTableCellProps & { parentElementId: string }) { + const { setExpression } = useBoxedExpressionEditorDispatch(); + + const onSetExpression = useCallback( + ({ getNewExpression }) => { + setExpression((prev: BoxedFilter) => { + return { + ...prev, + in: { + ...prev.in, + expression: getNewExpression(prev.in.expression), + }, + }; + }); + }, + [setExpression] + ); + + return ( +
+ + + +
+ ); +} diff --git a/packages/boxed-expression-component/src/expressions/FilterExpression/FilterExpressionComponent.tsx b/packages/boxed-expression-component/src/expressions/FilterExpression/FilterExpressionComponent.tsx new file mode 100644 index 00000000000..e9b4cfe60db --- /dev/null +++ b/packages/boxed-expression-component/src/expressions/FilterExpression/FilterExpressionComponent.tsx @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + BeeTableContextMenuAllowedOperationsConditions, + BeeTableHeaderVisibility, + BeeTableOperation, + BeeTableOperationConfig, + BeeTableProps, + BoxedFilter, + DmnBuiltInDataType, +} from "../../api"; +import { BeeTable, BeeTableColumnUpdate } from "../../table/BeeTable"; +import { ResizerStopBehavior } from "../../resizing/ResizingWidthsContext"; +import React, { useCallback, useMemo } from "react"; +import { DMN15__tChildExpression } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import * as ReactTable from "react-table"; +import { useBoxedExpressionEditorI18n } from "../../i18n"; +import { DEFAULT_EXPRESSION_VARIABLE_NAME } from "../../expressionVariable/ExpressionVariableMenu"; +import { useBoxedExpressionEditor, useBoxedExpressionEditorDispatch } from "../../BoxedExpressionEditorContext"; +import { NestedExpressionContainerContext } from "../../resizing/NestedExpressionContainerContext"; +import { useNestedExpressionContainerWithNestedExpressions } from "../../resizing/Hooks"; +import { + FILTER_EXPRESSION_EXTRA_WIDTH, + FILTER_EXPRESSION_MATCH_ROW_EXTRA_WIDTH, + FILTER_EXPRESSION_MIN_WIDTH, +} from "../../resizing/WidthConstants"; +import { FilterExpressionCollectionCell } from "./FilterExpressionCollectionCell"; +import { FilterExpressionMatchCell } from "./FilterExpressionMatchCell"; +import "./FilterExpression.css"; + +export type ROWTYPE = DMN15__tChildExpression; + +export function FilterExpressionComponent({ + isNested, + parentElementId, + expression: filterExpression, +}: { + expression: BoxedFilter; + isNested: boolean; + parentElementId: string; +}) { + const { i18n } = useBoxedExpressionEditorI18n(); + const { expressionHolderId, widthsById } = useBoxedExpressionEditor(); + const { setExpression } = useBoxedExpressionEditorDispatch(); + + const beeTableColumns = useMemo[]>(() => { + return [ + { + accessor: expressionHolderId as any, // FIXME: https://github.com/kiegroup/kie-issues/issues/169 + label: filterExpression["@_label"] ?? DEFAULT_EXPRESSION_VARIABLE_NAME, + dataType: filterExpression["@_typeRef"] ?? DmnBuiltInDataType.Undefined, + isRowIndexColumn: false, + minWidth: FILTER_EXPRESSION_MIN_WIDTH, + width: undefined, + }, + ]; + }, [filterExpression, expressionHolderId]); + + const headerVisibility = useMemo(() => { + return isNested ? BeeTableHeaderVisibility.None : BeeTableHeaderVisibility.AllLevels; + }, [isNested]); + + const beeTableOperationConfig = useMemo(() => { + return [ + { + group: i18n.terms.selection.toUpperCase(), + items: [{ name: i18n.terms.copy, type: BeeTableOperation.SelectionCopy }], + }, + { + group: i18n.function.toUpperCase(), + items: [{ name: i18n.rowOperations.reset, type: BeeTableOperation.RowReset }], + }, + ]; + }, [i18n]); + + const tableRows = useMemo(() => { + return [filterExpression.in]; + }, [filterExpression.in]); + + const allowedOperations = useCallback((conditions: BeeTableContextMenuAllowedOperationsConditions) => { + if (!conditions.selection.selectionStart || !conditions.selection.selectionEnd) { + return []; + } + + return [ + BeeTableOperation.SelectionCopy, + ...(conditions.selection.selectionStart.columnIndex > 1 + ? [BeeTableOperation.SelectionCut, BeeTableOperation.SelectionPaste, BeeTableOperation.SelectionReset] + : []), + ]; + }, []); + + const { nestedExpressionContainerValue, onColumnResizingWidthChange } = + useNestedExpressionContainerWithNestedExpressions( + useMemo(() => { + return { + nestedExpressions: [filterExpression.in.expression, filterExpression.match.expression], + fixedColumnActualWidth: 0, + fixedColumnResizingWidth: { value: 0, isPivoting: false }, + fixedColumnMinWidth: 0, + nestedExpressionMinWidth: FILTER_EXPRESSION_MIN_WIDTH, + extraWidth: FILTER_EXPRESSION_EXTRA_WIDTH, + expression: filterExpression, + flexibleColumnIndex: 1, + widthsById: widthsById, + nestedExpressionsExtraWidths: new Map([ + [filterExpression.match.expression?.["@_id"] ?? "", FILTER_EXPRESSION_MATCH_ROW_EXTRA_WIDTH], + ]), + }; + }, [filterExpression, widthsById]) + ); + + const cellComponentByColumnAccessor: BeeTableProps["cellComponentByColumnAccessor"] = useMemo( + () => ({ + [expressionHolderId]: (props) => , + }), + [expressionHolderId, parentElementId] + ); + + const beeTableAdditionalRow = useMemo(() => { + return [ + , + ]; + }, [filterExpression.match, parentElementId]); + + const onColumnUpdates = useCallback( + ([{ name, typeRef }]: BeeTableColumnUpdate[]) => { + setExpression((prev: BoxedFilter) => { + // Do not inline this variable for type safety. See https://github.com/microsoft/TypeScript/issues/241 + const ret: BoxedFilter = { + ...prev, + "@_label": name, + "@_typeRef": typeRef, + }; + + return ret; + }); + }, + [setExpression] + ); + + return ( + + + onColumnResizingWidthChange={onColumnResizingWidthChange} + resizerStopBehavior={ResizerStopBehavior.SET_WIDTH_WHEN_SMALLER} + tableId={filterExpression["@_id"]} + headerVisibility={headerVisibility} + cellComponentByColumnAccessor={cellComponentByColumnAccessor} + columns={beeTableColumns} + rows={tableRows} + operationConfig={beeTableOperationConfig} + allowedOperations={allowedOperations} + onColumnUpdates={onColumnUpdates} + shouldRenderRowIndexColumn={false} + shouldShowRowsInlineControls={false} + shouldShowColumnsInlineControls={false} + additionalRow={beeTableAdditionalRow} + /> + + ); +} diff --git a/packages/boxed-expression-component/src/expressions/FilterExpression/FilterExpressionMatchCell.tsx b/packages/boxed-expression-component/src/expressions/FilterExpression/FilterExpressionMatchCell.tsx new file mode 100644 index 00000000000..5ed1c6865ad --- /dev/null +++ b/packages/boxed-expression-component/src/expressions/FilterExpression/FilterExpressionMatchCell.tsx @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { BeeTableCellProps, BoxedFilter } from "../../api"; +import { + NestedExpressionDispatchContextProvider, + OnSetExpression, + useBoxedExpressionEditor, + useBoxedExpressionEditorDispatch, +} from "../../BoxedExpressionEditorContext"; +import React, { useCallback, useEffect, useMemo } from "react"; +import { ExpressionContainer } from "../ExpressionDefinitionRoot/ExpressionContainer"; +import { ROWTYPE } from "./FilterExpressionComponent"; +import "./FilterExpression.css"; +import { + NestedExpressionContainerContext, + NestedExpressionContainerContextType, + useNestedExpressionContainer, +} from "../../resizing/NestedExpressionContainerContext"; +import { FILTER_EXPRESSION_MATCH_ROW_EXTRA_WIDTH } from "../../resizing/WidthConstants"; +import { useBeeTableSelectableCellRef } from "../../selection/BeeTableSelectionContext"; + +export function FilterExpressionMatchCell({ + rowIndex, + data: items, + columnIndex, + parentElementId, +}: BeeTableCellProps & { + parentElementId: string; +}) { + const { setExpression } = useBoxedExpressionEditorDispatch(); + const { expression } = items[0]; + const { isActive } = useBeeTableSelectableCellRef(rowIndex, columnIndex, undefined); + const { beeGwtService } = useBoxedExpressionEditor(); + + useEffect(() => { + if (isActive) { + beeGwtService?.selectObject(expression?.["@_id"]); + } + }, [beeGwtService, expression, isActive]); + + const onSetExpression = useCallback( + ({ getNewExpression }) => { + setExpression((prev: BoxedFilter) => { + const newExpression = getNewExpression(prev.match.expression); + + // Do not inline this variable for type safety. See https://github.com/microsoft/TypeScript/issues/241 + const ret: BoxedFilter = { + ...prev, + match: { + ...prev.match, + expression: newExpression!, // SPEC DISCREPANCY + }, + }; + + return ret; + }); + }, + [setExpression] + ); + + const nestedExpressionContainer = useNestedExpressionContainer(); + + const nestedExpressionContainerValue = useMemo(() => { + return { + minWidth: nestedExpressionContainer.minWidth - FILTER_EXPRESSION_MATCH_ROW_EXTRA_WIDTH, + actualWidth: nestedExpressionContainer.actualWidth - FILTER_EXPRESSION_MATCH_ROW_EXTRA_WIDTH, + resizingWidth: { + value: nestedExpressionContainer.resizingWidth.value - FILTER_EXPRESSION_MATCH_ROW_EXTRA_WIDTH, + isPivoting: nestedExpressionContainer.resizingWidth.isPivoting, + }, + }; + }, [ + nestedExpressionContainer.actualWidth, + nestedExpressionContainer.minWidth, + nestedExpressionContainer.resizingWidth.isPivoting, + nestedExpressionContainer.resizingWidth.value, + ]); + + return ( +
+
+
[
+
+
+ + + + + +
+
+
]
+
+
+ ); +} diff --git a/packages/boxed-expression-component/src/expressions/FunctionExpression/FeelFunctionExpression.tsx b/packages/boxed-expression-component/src/expressions/FunctionExpression/FeelFunctionExpression.tsx index 4f1e4954e96..91be6514c94 100644 --- a/packages/boxed-expression-component/src/expressions/FunctionExpression/FeelFunctionExpression.tsx +++ b/packages/boxed-expression-component/src/expressions/FunctionExpression/FeelFunctionExpression.tsx @@ -74,6 +74,10 @@ export function FeelFunctionExpression({ const { setExpression, setWidthsById } = useBoxedExpressionEditorDispatch(); const parametersColumnHeader = useFunctionExpressionParametersColumnHeader(functionExpression.formalParameter); + const parametersId = useMemo( + () => (functionExpression["@_id"] ? `${functionExpression["@_id"]}-parameters` : "parameters"), + [functionExpression] + ); const beeTableColumns = useMemo[]>(() => { return [ @@ -86,7 +90,7 @@ export function FeelFunctionExpression({ columns: [ { headerCellElement: parametersColumnHeader, - accessor: "parameters" as any, + accessor: parametersId as any, label: "parameters", isRowIndexColumn: false, dataType: undefined as any, @@ -95,7 +99,7 @@ export function FeelFunctionExpression({ ], }, ]; - }, [expressionHolderId, functionExpression, parametersColumnHeader]); + }, [expressionHolderId, functionExpression, parametersColumnHeader, parametersId]); const headerVisibility = useMemo(() => { return isNested ? BeeTableHeaderVisibility.LastLevel : BeeTableHeaderVisibility.AllLevels; @@ -138,9 +142,9 @@ export function FeelFunctionExpression({ const cellComponentByColumnAccessor: BeeTableProps["cellComponentByColumnAccessor"] = useMemo(() => { return { - parameters: (props) => , + [`${parametersId}`]: (props) => , }; - }, [parentElementId]); + }, [parentElementId, parametersId]); const getRowKey = useCallback((r: ReactTable.Row) => { return r.id; diff --git a/packages/boxed-expression-component/src/expressions/FunctionExpression/FunctionKindSelector.tsx b/packages/boxed-expression-component/src/expressions/FunctionExpression/FunctionKindSelector.tsx index 1cec90881e6..585020e7b5e 100644 --- a/packages/boxed-expression-component/src/expressions/FunctionExpression/FunctionKindSelector.tsx +++ b/packages/boxed-expression-component/src/expressions/FunctionExpression/FunctionKindSelector.tsx @@ -48,9 +48,6 @@ export const FunctionKindSelector: React.FunctionComponent { - onFunctionKindSelect(itemId as DMN15__tFunctionKind); - }, 0); }, [onFunctionKindSelect] ); diff --git a/packages/boxed-expression-component/src/expressions/FunctionExpression/JavaFunctionExpression.tsx b/packages/boxed-expression-component/src/expressions/FunctionExpression/JavaFunctionExpression.tsx index 0d7006e6744..ddf0285725d 100644 --- a/packages/boxed-expression-component/src/expressions/FunctionExpression/JavaFunctionExpression.tsx +++ b/packages/boxed-expression-component/src/expressions/FunctionExpression/JavaFunctionExpression.tsx @@ -44,7 +44,6 @@ import { JAVA_FUNCTION_EXPRESSION_VALUES_COLUMN_WIDTH_INDEX, JAVA_FUNCTION_EXPRESSION_VALUES_MIN_WIDTH, } from "../../resizing/WidthConstants"; -import { useBeeTableSelectableCellRef } from "../../selection/BeeTableSelectionContext"; import { BeeTable, BeeTableCellUpdate, BeeTableColumnUpdate, BeeTableRef } from "../../table/BeeTable"; import { useBoxedExpressionEditor, useBoxedExpressionEditorDispatch } from "../../BoxedExpressionEditorContext"; import { DEFAULT_EXPRESSION_VARIABLE_NAME } from "../../expressionVariable/ExpressionVariableMenu"; @@ -55,6 +54,7 @@ import { DMN15__tLiteralExpression, } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; import "./JavaFunctionExpression.css"; +import { useBeeTableSelectableCellRef } from "../../selection/BeeTableSelectionContext"; export type JAVA_ROWTYPE = { value: string; @@ -120,6 +120,10 @@ export function JavaFunctionExpression({ ); const parametersColumnHeader = useFunctionExpressionParametersColumnHeader(functionExpression.formalParameter); + const parametersId = useMemo( + () => (functionExpression["@_id"] ? `${functionExpression["@_id"]}-parameters` : "parameters"), + [functionExpression] + ); const beeTableColumns = useMemo[]>(() => { return [ @@ -132,7 +136,7 @@ export function JavaFunctionExpression({ columns: [ { headerCellElement: parametersColumnHeader, - accessor: "parameters" as any, + accessor: parametersId as any, label: "parameters", isRowIndexColumn: false, dataType: undefined as any, @@ -168,6 +172,7 @@ export function JavaFunctionExpression({ classAndMethodNamesWidth, parametersColumnHeader, setClassAndMethodNamesWidth, + parametersId, ]); const headerVisibility = useMemo(() => { diff --git a/packages/boxed-expression-component/src/expressions/FunctionExpression/PmmlFunctionExpression.tsx b/packages/boxed-expression-component/src/expressions/FunctionExpression/PmmlFunctionExpression.tsx index 42aa4d87b8d..ab5414b500b 100644 --- a/packages/boxed-expression-component/src/expressions/FunctionExpression/PmmlFunctionExpression.tsx +++ b/packages/boxed-expression-component/src/expressions/FunctionExpression/PmmlFunctionExpression.tsx @@ -75,10 +75,14 @@ export function PmmlFunctionExpression({ parentElementId: string; }) { const { i18n } = useBoxedExpressionEditorI18n(); - const { expressionHolderId, widthsById } = useBoxedExpressionEditor(); + const { expressionHolderId } = useBoxedExpressionEditor(); const { setExpression } = useBoxedExpressionEditorDispatch(); const parametersColumnHeader = useFunctionExpressionParametersColumnHeader(functionExpression.formalParameter); + const parametersId = useMemo( + () => (functionExpression["@_id"] ? `${functionExpression["@_id"]}-parameters` : "parameters"), + [functionExpression] + ); const beeTableColumns = useMemo[]>(() => { return [ @@ -91,7 +95,7 @@ export function PmmlFunctionExpression({ columns: [ { headerCellElement: parametersColumnHeader, - accessor: "parameters" as any, + accessor: parametersId as any, label: "parameters", isRowIndexColumn: false, dataType: undefined as any, @@ -121,7 +125,7 @@ export function PmmlFunctionExpression({ ], }, ]; - }, [expressionHolderId, functionExpression, parametersColumnHeader]); + }, [expressionHolderId, functionExpression, parametersColumnHeader, parametersId]); const headerVisibility = useMemo(() => { return isNested ? BeeTableHeaderVisibility.SecondToLastLevel : BeeTableHeaderVisibility.AllLevels; diff --git a/packages/boxed-expression-component/src/expressions/InvocationExpression/ArgumentEntryExpressionCell.tsx b/packages/boxed-expression-component/src/expressions/InvocationExpression/ArgumentEntryExpressionCell.tsx index 433d75da5e8..6ccbf09e960 100644 --- a/packages/boxed-expression-component/src/expressions/InvocationExpression/ArgumentEntryExpressionCell.tsx +++ b/packages/boxed-expression-component/src/expressions/InvocationExpression/ArgumentEntryExpressionCell.tsx @@ -18,23 +18,32 @@ */ import * as React from "react"; +import { useCallback, useEffect } from "react"; import { BoxedInvocation, BeeTableCellProps } from "../../api"; +import { ExpressionContainer } from "../ExpressionDefinitionRoot/ExpressionContainer"; import { NestedExpressionDispatchContextProvider, OnSetExpression, + useBoxedExpressionEditor, useBoxedExpressionEditorDispatch, } from "../../BoxedExpressionEditorContext"; -import { useCallback } from "react"; -import { ExpressionContainer } from "../ExpressionDefinitionRoot/ExpressionContainer"; import { ROWTYPE } from "./InvocationExpression"; import "../ContextExpression/ContextEntryExpressionCell.css"; +import { useBeeTableSelectableCellRef } from "../../selection/BeeTableSelectionContext"; export const ArgumentEntryExpressionCell: React.FunctionComponent< BeeTableCellProps & { parentElementId: string } > = ({ data, rowIndex, columnIndex, parentElementId }) => { const { setExpression } = useBoxedExpressionEditorDispatch(); - const { expression, variable, index } = data[rowIndex]; + const { isActive } = useBeeTableSelectableCellRef(rowIndex, columnIndex, undefined); + const { beeGwtService } = useBoxedExpressionEditor(); + + useEffect(() => { + if (isActive) { + expression ? beeGwtService?.selectObject(expression["@_id"]) : ""; + } + }, [beeGwtService, columnIndex, expression, isActive]); const onSetExpression = useCallback( ({ getNewExpression }) => { diff --git a/packages/boxed-expression-component/src/expressions/InvocationExpression/InvocationExpression.tsx b/packages/boxed-expression-component/src/expressions/InvocationExpression/InvocationExpression.tsx index 215b2a5fb9f..bb8d4274f92 100644 --- a/packages/boxed-expression-component/src/expressions/InvocationExpression/InvocationExpression.tsx +++ b/packages/boxed-expression-component/src/expressions/InvocationExpression/InvocationExpression.tsx @@ -18,7 +18,7 @@ */ import * as React from "react"; -import { useCallback, useMemo } from "react"; +import { useCallback, useMemo, useEffect } from "react"; import * as ReactTable from "react-table"; import { BeeTableContextMenuAllowedOperationsConditions, @@ -49,6 +49,7 @@ import { ArgumentEntryExpressionCell } from "./ArgumentEntryExpressionCell"; import { ExpressionVariableCell, ExpressionWithVariable } from "../../expressionVariable/ExpressionVariableCell"; import { DEFAULT_EXPRESSION_VARIABLE_NAME } from "../../expressionVariable/ExpressionVariableMenu"; import { getExpressionTotalMinWidth } from "../../resizing/WidthMaths"; +import { useBeeTableCoordinates, useBeeTableSelectableCellRef } from "../../selection/BeeTableSelectionContext"; import { DMN15__tBinding } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; import { findAllIdsDeep } from "../../ids/ids"; import "./InvocationExpression.css"; @@ -112,6 +113,20 @@ export function InvocationExpression({ } }, []); + const { containerCellCoordinates } = useBeeTableCoordinates(); + const { isActive } = useBeeTableSelectableCellRef( + containerCellCoordinates?.rowIndex ?? 0, + containerCellCoordinates?.columnIndex ?? 0, + undefined + ); + + const { beeGwtService } = useBoxedExpressionEditor(); + useEffect(() => { + if (isActive) { + beeGwtService?.selectObject(); + } + }, [beeGwtService, isActive]); + /// ////////////////////////////////////////////////////// /// ///////////// RESIZING WIDTHS //////////////////////// /// ////////////////////////////////////////////////////// @@ -158,6 +173,11 @@ export function InvocationExpression({ })); }, [invocationExpression.binding]); + const invocationId = useMemo( + () => invocationExpression.expression?.["@_id"] ?? "functionName", + [invocationExpression.expression] + ); + const beeTableColumns = useMemo[]>( () => [ { @@ -168,7 +188,7 @@ export function InvocationExpression({ width: undefined, columns: [ { - accessor: "functionName" as keyof ROWTYPE, + accessor: invocationId as keyof ROWTYPE, label: invocationExpression.expression?.__$$element === "literalExpression" ? invocationExpression.expression.text?.__$$text ?? "Function name" @@ -202,18 +222,25 @@ export function InvocationExpression({ ], }, ], - [expressionHolderId, invocationExpression, parametersWidth, setParametersWidth] + [expressionHolderId, invocationExpression, parametersWidth, invocationId, setParametersWidth] ); const onColumnUpdates = useCallback( (columnUpdates: BeeTableColumnUpdate[]) => { for (const u of columnUpdates) { - if (u.column.originalId === "functionName") { + if (u.column.originalId === id) { + setExpression((prev: BoxedInvocation) => ({ + ...prev, + "@_id": prev["@_id"], + name: u.name, + })); + } else if (u.column.originalId === invocationId) { setExpression((prev: BoxedInvocation) => { // Do not inline this variable for type safety. See https://github.com/microsoft/TypeScript/issues/241 const ret: BoxedInvocation = { ...prev, expression: { + ...prev.expression, __$$element: "literalExpression", text: { __$$text: u.name, @@ -237,7 +264,7 @@ export function InvocationExpression({ } } }, - [setExpression] + [setExpression, id, invocationId] ); const headerVisibility = useMemo( diff --git a/packages/boxed-expression-component/src/expressions/IteratorExpression/IteratorExpressionCell.tsx b/packages/boxed-expression-component/src/expressions/IteratorExpression/IteratorExpressionCell.tsx index 99c0c7e5ab6..5ad0e80a77a 100644 --- a/packages/boxed-expression-component/src/expressions/IteratorExpression/IteratorExpressionCell.tsx +++ b/packages/boxed-expression-component/src/expressions/IteratorExpression/IteratorExpressionCell.tsx @@ -1,11 +1,29 @@ -import { BoxedIterator } from "../../api"; +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import * as React from "react"; +import { useCallback, useMemo } from "react"; +import { BoxedIterator } from "../../api"; import { NestedExpressionDispatchContextProvider, useBoxedExpressionEditorDispatch, } from "../../BoxedExpressionEditorContext"; -import * as React from "react"; -import { useCallback, useMemo } from "react"; import { ExpressionContainer } from "../ExpressionDefinitionRoot/ExpressionContainer"; import { IteratorClause } from "./IteratorExpressionComponent"; diff --git a/packages/boxed-expression-component/src/expressions/IteratorExpression/IteratorExpressionComponent.tsx b/packages/boxed-expression-component/src/expressions/IteratorExpression/IteratorExpressionComponent.tsx index d56b1d51780..de817288fbd 100644 --- a/packages/boxed-expression-component/src/expressions/IteratorExpression/IteratorExpressionComponent.tsx +++ b/packages/boxed-expression-component/src/expressions/IteratorExpression/IteratorExpressionComponent.tsx @@ -28,7 +28,7 @@ import { } from "../../api"; import { BeeTable, BeeTableColumnUpdate, BeeTableRef } from "../../table/BeeTable"; import { ResizerStopBehavior } from "../../resizing/ResizingWidthsContext"; -import React, { useCallback, useMemo, useRef } from "react"; +import React, { useCallback, useEffect, useMemo, useRef } from "react"; import { DMN15__tChildExpression, DMN15__tTypedChildExpression, @@ -47,7 +47,8 @@ import { ITERATOR_EXPRESSION_LABEL_COLUMN_WIDTH, } from "../../resizing/WidthConstants"; import { DEFAULT_EXPRESSION_VARIABLE_NAME } from "../../expressionVariable/ExpressionVariableMenu"; -import { InlineEditableTextInput } from "../../table/BeeTable/InlineEditableTextInput"; +import { useBeeTableCoordinates, useBeeTableSelectableCellRef } from "../../selection/BeeTableSelectionContext"; +import { IteratorExpressionVariableCell } from "./IteratorExpressionVariableCell"; type ROWTYPE = IteratorClause; @@ -192,32 +193,13 @@ export function IteratorExpressionComponent({ child: (props) => { if (props.rowIndex === 0) { return ( -
- { - setExpression((prev: BoxedIterator) => { - // Do not inline this variable for type safety. See https://github.com/microsoft/TypeScript/issues/241 - const ret: BoxedIterator = { - ...prev, - "@_iteratorVariable": updatedValue, - }; - return ret; - }); - }} - setActiveCellEditing={(value) => { - beeTableRef.current?.setActiveCellEditing(value); - }} - /> -
+ ); } else if (props.rowIndex === 1 || props.rowIndex === 2) { return ( @@ -232,7 +214,7 @@ export function IteratorExpressionComponent({ } }, }; - }, [parentElementId, setExpression]); + }, [id, parentElementId]); const { nestedExpressionContainerValue, onColumnResizingWidthChange } = useNestedExpressionContainerWithNestedExpressions( diff --git a/packages/boxed-expression-component/src/expressions/IteratorExpression/IteratorExpressionVariableCell.tsx b/packages/boxed-expression-component/src/expressions/IteratorExpression/IteratorExpressionVariableCell.tsx new file mode 100644 index 00000000000..2b0e0d6bb2d --- /dev/null +++ b/packages/boxed-expression-component/src/expressions/IteratorExpression/IteratorExpressionVariableCell.tsx @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useEffect } from "react"; +import { BoxedIterator } from "../../api"; +import { useBoxedExpressionEditor, useBoxedExpressionEditorDispatch } from "../../BoxedExpressionEditorContext"; +import { IteratorClause } from "./IteratorExpressionComponent"; +import { InlineEditableTextInput } from "../../table/BeeTable/InlineEditableTextInput"; +import { BeeTableRef } from "../../table/BeeTable"; +import { useBeeTableSelectableCellRef } from "../../selection/BeeTableSelectionContext"; + +export interface IteratorExpressionVariableCellProps { + rowIndex: number; + columnIndex: number; + currentElementId: string; + data: readonly IteratorClause[]; + beeTableRef: React.RefObject; +} + +export function IteratorExpressionVariableCell({ + rowIndex, + columnIndex, + currentElementId, + data, + beeTableRef, +}: IteratorExpressionVariableCellProps) { + const { setExpression } = useBoxedExpressionEditorDispatch(); + const { isActive } = useBeeTableSelectableCellRef(rowIndex ?? 0, columnIndex ?? 0, undefined); + const { beeGwtService } = useBoxedExpressionEditor(); + + // Selecting the context result cell should be the parent data type + useEffect(() => { + if (isActive) { + beeGwtService?.selectObject(`${currentElementId}-iteratorVariable`); + } + }, [beeGwtService, isActive, currentElementId]); + + return ( +
+ { + setExpression((prev: BoxedIterator) => { + // Do not inline this variable for type safety. See https://github.com/microsoft/TypeScript/issues/241 + const ret: BoxedIterator = { + ...prev, + "@_iteratorVariable": updatedValue, + }; + return ret; + }); + }} + rowIndex={rowIndex} + columnIndex={columnIndex} + setActiveCellEditing={(value) => { + beeTableRef.current?.setActiveCellEditing(value); + }} + /> +
+ ); +} diff --git a/packages/boxed-expression-component/src/expressions/RelationExpression/RelationExpression.tsx b/packages/boxed-expression-component/src/expressions/RelationExpression/RelationExpression.tsx index 1fadabf054b..4300dffb587 100644 --- a/packages/boxed-expression-component/src/expressions/RelationExpression/RelationExpression.tsx +++ b/packages/boxed-expression-component/src/expressions/RelationExpression/RelationExpression.tsx @@ -189,7 +189,10 @@ export function RelationExpression({ (tableRow: ROWTYPE, column, columnIndex) => { const cellExpression = row.expression?.[columnIndex]; if (cellExpression?.__$$element === "literalExpression") { - tableRow[column["@_id"]!] = cellExpression.text?.__$$text ?? ""; + tableRow[column["@_id"]!] = { + id: cellExpression["@_id"] ?? generateUuid(), + content: cellExpression.text?.__$$text ?? "", + }; } return tableRow; }, diff --git a/packages/boxed-expression-component/src/ids/ids.ts b/packages/boxed-expression-component/src/ids/ids.ts index 13e10e320e2..d9aad77449b 100644 --- a/packages/boxed-expression-component/src/ids/ids.ts +++ b/packages/boxed-expression-component/src/ids/ids.ts @@ -37,7 +37,7 @@ export function mutateExpressionRandomizingIds(expression: BoxedExpression | und return new Map(); } - return getIdRandomizerForExpression(expression).randomize(); + return getIdRandomizerForExpression(expression).randomize({ skipAlreadyAttributedIds: false }).getRandomized(); } function getNewBeeIdRandomizer() { diff --git a/packages/boxed-expression-component/src/resizing/Hooks.tsx b/packages/boxed-expression-component/src/resizing/Hooks.tsx index 1c91fd96670..106b09020fa 100644 --- a/packages/boxed-expression-component/src/resizing/Hooks.tsx +++ b/packages/boxed-expression-component/src/resizing/Hooks.tsx @@ -37,7 +37,8 @@ export function useNestedExpressionResizingWidthValue( fixedColumnMinWidth: number, nestedExpressionMinWidth: number, extraWidth: number, - widthsById: Map + widthsById: Map, + nestedExpressionsExtraWidths?: Map ) { const { resizingWidths } = useResizingWidths(); const nestedExpressionContainer = useNestedExpressionContainer(); @@ -54,7 +55,8 @@ export function useNestedExpressionResizingWidthValue( if (nestedPivotingExpression) { return Math.max( - getExpressionResizingWidth(nestedPivotingExpression, resizingWidths, widthsById), + getExpressionResizingWidth(nestedPivotingExpression, resizingWidths, widthsById) + + (nestedExpressionsExtraWidths?.get(nestedPivotingExpression["@_id"]!) ?? 0), fixedColumnMinWidth ); } @@ -83,6 +85,7 @@ export function useNestedExpressionResizingWidthValue( resizingWidths, widthsById, fixedColumnMinWidth, + nestedExpressionsExtraWidths, ]); } @@ -144,6 +147,7 @@ export function useNestedExpressionContainerWithNestedExpressions({ expression, flexibleColumnIndex, widthsById, + nestedExpressionsExtraWidths, }: { nestedExpressions: BoxedExpression[]; fixedColumnActualWidth: number; @@ -154,6 +158,7 @@ export function useNestedExpressionContainerWithNestedExpressions({ expression: BoxedExpression; flexibleColumnIndex: number; widthsById: Map; + nestedExpressionsExtraWidths?: Map; }) { const nestedExpressionContainer = useNestedExpressionContainer(); @@ -189,7 +194,8 @@ export function useNestedExpressionContainerWithNestedExpressions({ fixedColumnMinWidth, nestedExpressionMinWidth, extraWidth, - widthsById + widthsById, + nestedExpressionsExtraWidths ); const maxNestedExpressionMinWidth = useNestedExpressionMinWidth( diff --git a/packages/boxed-expression-component/src/resizing/WidthConstants.ts b/packages/boxed-expression-component/src/resizing/WidthConstants.ts index 06d98a78d26..0713ba22a3f 100644 --- a/packages/boxed-expression-component/src/resizing/WidthConstants.ts +++ b/packages/boxed-expression-component/src/resizing/WidthConstants.ts @@ -75,3 +75,7 @@ export const CONDITIONAL_EXPRESSION_EXTRA_WIDTH = 2; // 2px for borders of conte export const ITERATOR_EXPRESSION_LABEL_COLUMN_WIDTH = 80; export const ITERATOR_EXPRESSION_CLAUSE_COLUMN_MIN_WIDTH = 210; export const ITERATOR_EXPRESSION_EXTRA_WIDTH = 2; // 2px for borders of context entry expression // It's a mistery why to this cell is counting the borders. + +export const FILTER_EXPRESSION_MIN_WIDTH = 250; +export const FILTER_EXPRESSION_MATCH_ROW_EXTRA_WIDTH = 2 * 20; // 20px is the size of the 'bracket-sign-container' CSS class in the FilterExpression.css file +export const FILTER_EXPRESSION_EXTRA_WIDTH = 2; // 2px for borders of context entry expression // It's a mistery why to this cell is counting the borders. diff --git a/packages/boxed-expression-component/src/resizing/WidthMaths.ts b/packages/boxed-expression-component/src/resizing/WidthMaths.ts index 3b3f3e5003f..6b516671066 100644 --- a/packages/boxed-expression-component/src/resizing/WidthMaths.ts +++ b/packages/boxed-expression-component/src/resizing/WidthMaths.ts @@ -54,6 +54,9 @@ import { ITERATOR_EXPRESSION_LABEL_COLUMN_WIDTH, ITERATOR_EXPRESSION_CLAUSE_COLUMN_MIN_WIDTH, ITERATOR_EXPRESSION_EXTRA_WIDTH, + FILTER_EXPRESSION_MIN_WIDTH, + FILTER_EXPRESSION_MATCH_ROW_EXTRA_WIDTH, + FILTER_EXPRESSION_EXTRA_WIDTH, } from "./WidthConstants"; export function getExpressionMinWidth(expression?: BoxedExpression): number { @@ -167,6 +170,17 @@ export function getExpressionMinWidth(expression?: BoxedExpression): number { ITERATOR_EXPRESSION_EXTRA_WIDTH ); } + + // Filter + else if (expression.__$$element === "filter") { + const inExpressionWidth = getExpressionMinWidth(expression.in.expression); + const matchExpressionWidth = + getExpressionMinWidth(expression.match.expression) + FILTER_EXPRESSION_MATCH_ROW_EXTRA_WIDTH; + return ( + Math.max(FILTER_EXPRESSION_MIN_WIDTH, inExpressionWidth, matchExpressionWidth) + FILTER_EXPRESSION_EXTRA_WIDTH + ); + } + // Others else { throw new Error("Shouldn't ever reach this point"); @@ -378,9 +392,23 @@ export function getExpressionResizingWidth( ); } + // Filter + else if (expression.__$$element === "filter") { + const inExpressionWidth = getExpressionResizingWidth(expression.in.expression, resizingWidths, widthsById); + const matchExpressionWidth = + getExpressionResizingWidth(expression.match.expression, resizingWidths, widthsById) + + FILTER_EXPRESSION_MATCH_ROW_EXTRA_WIDTH; + return ( + resizingWidth ?? + Math.max(FILTER_EXPRESSION_MIN_WIDTH, inExpressionWidth, matchExpressionWidth) + FILTER_EXPRESSION_EXTRA_WIDTH + ); + } + // Others else { - throw new Error(`Can't determine resizing width for expression of unknown type '${expression.__$$element}'`); + throw new Error( + `Can't determine resizing width for expression of unknown type '${(expression as any).__$$element}'` + ); } } diff --git a/packages/boxed-expression-component/src/table/BeeTable/BeeTableDefaultCell.tsx b/packages/boxed-expression-component/src/table/BeeTable/BeeTableDefaultCell.tsx index 3789e071111..c282f259844 100644 --- a/packages/boxed-expression-component/src/table/BeeTable/BeeTableDefaultCell.tsx +++ b/packages/boxed-expression-component/src/table/BeeTable/BeeTableDefaultCell.tsx @@ -18,11 +18,12 @@ */ import * as React from "react"; -import { useCallback } from "react"; +import { useCallback, useEffect } from "react"; import { BeeTableCellUpdate } from "."; import { BeeTableEditableCellContent } from "./BeeTableEditableCellContent"; import { useBeeTableSelectableCellRef } from "../../selection/BeeTableSelectionContext"; import * as ReactTable from "react-table"; +import { useBoxedExpressionEditor } from "../../BoxedExpressionEditorContext"; export function BeeTableDefaultCell({ cellProps, @@ -67,6 +68,17 @@ export function BeeTableDefaultCell({ getValue ); + // FIXME: The BeeTable shouldn't know about DMN or GWT + // The following useEffect shouldn't be placed here. + const { beeGwtService } = useBoxedExpressionEditor(); + useEffect(() => { + if (isActive) { + const column = cellProps.column.id; + const cell = cellProps.row.values[column] as { id: string; content: string }; + beeGwtService?.selectObject(cell ? cell.id : ""); + } + }, [beeGwtService, cellProps.column.id, cellProps.columns, cellProps.row.values, isActive]); + return ( { if (isActive) { beeGwtService?.selectObject(""); diff --git a/packages/boxed-expression-component/src/table/BeeTable/BeeTableTd.tsx b/packages/boxed-expression-component/src/table/BeeTable/BeeTableTd.tsx index 8031797526d..66c031ad583 100644 --- a/packages/boxed-expression-component/src/table/BeeTable/BeeTableTd.tsx +++ b/packages/boxed-expression-component/src/table/BeeTable/BeeTableTd.tsx @@ -107,14 +107,13 @@ export function BeeTableTd({ const { isActive } = useBeeTableSelectableCellRef(rowIndex, columnIndex, undefined); + // FIXME: The BeeTable shouldn't know about DMN or GWT + // The following useEffect shouldn't be placed here. const { beeGwtService, editorRef } = useBoxedExpressionEditor(); - useEffect(() => { if (isActive) { if (column.isRowIndexColumn) { beeGwtService?.selectObject(""); - } else { - beeGwtService?.selectObject(typeof cell.value === "string" ? "" : cell.value?.id ?? ""); } } }, [beeGwtService, isActive, column.isRowIndexColumn, cell.value]); diff --git a/packages/boxed-expression-component/src/table/BeeTable/BeeTableTh.tsx b/packages/boxed-expression-component/src/table/BeeTable/BeeTableTh.tsx index 4f6e844ee28..b5ed5724afb 100644 --- a/packages/boxed-expression-component/src/table/BeeTable/BeeTableTh.tsx +++ b/packages/boxed-expression-component/src/table/BeeTable/BeeTableTh.tsx @@ -108,17 +108,18 @@ export function BeeTableTh({ const { isActive } = useBeeTableSelectableCellRef(rowIndex, columnIndex, undefined); + // FIXME: The BeeTable shouldn't know about DMN or GWT + // The following useEffect shouldn't be placed here. const { beeGwtService } = useBoxedExpressionEditor(); - useEffect(() => { if (isActive) { - if (column.isRowIndexColumn) { + if (column.isRowIndexColumn || groupType === "annotation") { beeGwtService?.selectObject(""); } else { beeGwtService?.selectObject(columnKey); } } - }, [beeGwtService, column.isRowIndexColumn, columnKey, isActive]); + }, [beeGwtService, column.isRowIndexColumn, columnKey, groupType, isActive]); const _thRef = useRef(null); const thRef = forwardRef ?? _thRef; diff --git a/packages/boxed-expression-component/stories/boxedExpressionStoriesWrapper.tsx b/packages/boxed-expression-component/stories/boxedExpressionStoriesWrapper.tsx index 75484b023d9..080a7bea231 100644 --- a/packages/boxed-expression-component/stories/boxedExpressionStoriesWrapper.tsx +++ b/packages/boxed-expression-component/stories/boxedExpressionStoriesWrapper.tsx @@ -187,10 +187,10 @@ export function BoxedExpressionEditorStory(props?: Partial): StorybookArgWidhtsById { - return Array.from((map ?? new Map()).entries()).reduce((acc, [key, value]) => { + return Array.from((map ?? new Map()).entries()).reduce((acc, [key, value]) => { acc[`${key}`] = value; return acc; - }, {}); + }, {} as Record); } function toMap(object?: StorybookArgWidhtsById): Map { diff --git a/packages/boxed-expression-component/stories/dev/WebApp.stories.tsx b/packages/boxed-expression-component/stories/dev/WebApp.stories.tsx index d765fff82fa..8975cf44e27 100644 --- a/packages/boxed-expression-component/stories/dev/WebApp.stories.tsx +++ b/packages/boxed-expression-component/stories/dev/WebApp.stories.tsx @@ -93,21 +93,11 @@ const pmmlDocuments = [ const INITIAL_EXPRESSION: BoxedExpression | undefined = undefined; const INITIAL_WIDTHS_BY_ID: Record = {}; -const beeGwtService: BeeGwtService = { - getDefaultExpressionDefinition(logicType, typeRef) { - return { - expression: getDefaultBoxedExpressionForDevWebapp(logicType, typeRef), - widthsById: new Map(), - }; - }, - openDataTypePage(): void {}, - selectObject(): void {}, -}; - function App() { const [version, setVersion] = useState(-1); const [boxedExpression, setBoxedExpression] = useState(INITIAL_EXPRESSION); const [widthsById, setWidthsById] = useState>(INITIAL_WIDTHS_BY_ID); + const [selectedObjectId, setSelectedObjectId] = useState(); useEffect(() => { setVersion((prev) => prev + 1); @@ -118,6 +108,19 @@ function App() { setWidthsById(widthsById); }, []); + const beeGwtService: BeeGwtService = { + getDefaultExpressionDefinition(logicType, typeRef) { + return { + expression: getDefaultBoxedExpressionForDevWebapp(logicType, typeRef), + widthsById: new Map(), + }; + }, + openDataTypePage(): void {}, + selectObject(uuid) { + setSelectedObjectId(uuid); + }, + }; + return (
@@ -139,25 +142,38 @@ function App() { Affordability - - - Updates count: {version} - - - -
- {BoxedExpressionEditorStory({ - expressionHolderId: "_00000000-0000-0000-0000-000000000000", - expression: boxedExpression, - onExpressionChange: setBoxedExpression, - widthsById: widthsById, - onWidthsChange: setWidthsById, - isResetSupportedOnRootExpression: true, - })} -
-
+ + + +
+ {BoxedExpressionEditorStory({ + expressionHolderId: "_00000000-0000-0000-0000-000000000000", + expression: boxedExpression, + onExpressionChange: setBoxedExpression, + widthsById: widthsById, + onWidthsChange: setWidthsById, + isResetSupportedOnRootExpression: true, + beeGwtService: beeGwtService, + })} +
+
+ + +
+ Updates count +

{version}

+
+
+ +
+ Selected cell ID +

{selectedObjectId}

+
+
+
+
); @@ -182,7 +198,6 @@ export const WebApp: Story = { expression: undefined, // Needs to be here to be displayed. widthsById: {}, // Needs to be here to be displayed. dataTypes: dataTypes, - beeGwtService: beeGwtService, pmmlDocuments: pmmlDocuments, }, }; diff --git a/packages/bpmn-vscode-extension/package.json b/packages/bpmn-vscode-extension/package.json index 3794af34371..74fe0e9430d 100644 --- a/packages/bpmn-vscode-extension/package.json +++ b/packages/bpmn-vscode-extension/package.json @@ -30,8 +30,7 @@ "@kie-tools-core/i18n": "workspace:*", "@kie-tools-core/patternfly-base": "workspace:*", "@kie-tools-core/vscode-extension": "workspace:*", - "@kie-tools/kie-bc-editors": "workspace:*", - "@kie-tools/vscode-java-code-completion-extension-plugin": "workspace:*" + "@kie-tools/kie-bc-editors": "workspace:*" }, "devDependencies": { "@kie-tools-core/webpack-base": "workspace:*", @@ -39,6 +38,7 @@ "@kie-tools/root-env": "workspace:*", "@kie-tools/stunner-editors": "workspace:*", "@kie-tools/tsconfig": "workspace:*", + "@kie-tools/vscode-java-code-completion-extension-plugin": "workspace:*", "@types/vscode": "1.67.0", "@vscode/test-web": "^0.0.30", "@vscode/vsce": "^2.22.0", diff --git a/packages/cors-proxy-image/Containerfile b/packages/cors-proxy-image/Containerfile index 622f31f3221..582a4f9c16b 100644 --- a/packages/cors-proxy-image/Containerfile +++ b/packages/cors-proxy-image/Containerfile @@ -5,15 +5,15 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations -# under the License. +# under the License. FROM --platform=linux/amd64 registry.access.redhat.com/ubi9/ubi-minimal:9.3 @@ -29,13 +29,14 @@ RUN mkdir $HOME \ && chgrp -R 0 $HOME \ && chmod -R g=u $HOME \ && chown -R 1000:0 $HOME \ - && microdnf install -y tar-2:1.34-6.el9_1.x86_64 gzip-1.12-1.el9.x86_64 \ + && microdnf --disableplugin=subscription-manager install -y tar gzip \ + && microdnf --disableplugin=subscription-manager clean all \ && curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash \ && /bin/bash -c "source $NVM_DIR/nvm.sh && nvm install $NODE_VERSION" \ && export CORS_PROXY_HTTP_PORT=$CORS_PROXY_DEFAULT_PORT \ && export CORS_PROXY_ORIGIN=CORS_PROXY_DEFAULT_ORIGIN \ && export CORS_PROXY_VERBOSE=CORS_PROXY_DEFAULT_VERBOSE - + ENV NODE_PATH $NVM_DIR/versions/node/$NODE_VERSION/bin ENV PATH $NODE_PATH:$PATH diff --git a/packages/cors-proxy/package.json b/packages/cors-proxy/package.json index 3c714f7f67d..a264349562b 100644 --- a/packages/cors-proxy/package.json +++ b/packages/cors-proxy/package.json @@ -21,8 +21,8 @@ "build:prod": "pnpm lint && pnpm test && rimraf dist && webpack", "lint": "run-script-if --bool \"$(build-env linters.run)\" --then \"kie-tools--eslint ./src\"", "start": "run-script-os", - "start:darwin:linux": "pnpm build:dev && cross-env CORS_PROXY_HTTP_PORT=$(build-env corsProxy.dev.port) CORS_PROXY_ORIGIN=$(build-env corsProxy.dev.oring) CORS_PROXY_VERBOSE=$(build-env corsProxy.dev.verbose) node dist/index.js", - "start:win32": "pnpm build:dev && pnpm powershell \"cross-env CORS_PROXY_HTTP_PORT=$(build-env corsProxy.dev.port) CORS_PROXY_ORIGIN=$(build-env corsProxy.dev.oring) CORS_PROXY_VERBOSE=$(build-env corsProxy.dev.verbose) node dist/index.js\"", + "start:darwin:linux": "pnpm build:dev && cross-env CORS_PROXY_HTTP_PORT=$(build-env corsProxy.dev.port) CORS_PROXY_ORIGIN=$(build-env corsProxy.dev.origin) CORS_PROXY_VERBOSE=$(build-env corsProxy.dev.verbose) node dist/index.js", + "start:win32": "pnpm build:dev && pnpm powershell \"cross-env CORS_PROXY_HTTP_PORT=$(build-env corsProxy.dev.port) CORS_PROXY_ORIGIN=$(build-env corsProxy.dev.origin) CORS_PROXY_VERBOSE=$(build-env corsProxy.dev.verbose) node dist/index.js\"", "test": "run-script-if --ignore-errors \"$(build-env tests.ignoreFailures)\" --bool \"$(build-env tests.run)\" --then \"jest --silent --verbose --passWithNoTests\"" }, "dependencies": { diff --git a/packages/dashbuilder-viewer-image/Containerfile b/packages/dashbuilder-viewer-image/Containerfile index e57389dfbc9..55678da2613 100644 --- a/packages/dashbuilder-viewer-image/Containerfile +++ b/packages/dashbuilder-viewer-image/Containerfile @@ -5,19 +5,19 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations -# under the License. +# under the License. FROM --platform=linux/amd64 registry.access.redhat.com/ubi9/ubi-minimal:9.3 -RUN microdnf --disableplugin=subscription-manager -y install httpd-2.4.57-5.el9.x86_64 \ +RUN microdnf --disableplugin=subscription-manager -y install httpd \ && microdnf --disableplugin=subscription-manager clean all \ && sed -i -e 's/Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf \ && sed -i -e 's/#ServerName www.example.com:80/ServerName 127.0.0.1:8080/' /etc/httpd/conf/httpd.conf \ diff --git a/packages/dashbuilder-viewer-image/package.json b/packages/dashbuilder-viewer-image/package.json index 7c8fffda55c..620a4f8c113 100644 --- a/packages/dashbuilder-viewer-image/package.json +++ b/packages/dashbuilder-viewer-image/package.json @@ -19,7 +19,7 @@ "build:prod:linux": "pnpm copy:assets && run-script-if --bool \"$(build-env containerImages.build)\" --then \"pnpm image:podman:build\"", "build:prod:win32": "echo \"Build not supported on Windows\"", "cleanup": "rimraf dist-dev && mkdir dist-dev", - "copy:assets": "cp -R ../dashbuilder-viewer-deployment-webapp/dist ./dist-dev/dashbuilder-viewer-deployment-webapp", + "copy:assets": "cp -R ./node_modules/@kie-tools/dashbuilder-viewer-deployment-webapp/dist/ ./dist-dev/dashbuilder-viewer-deployment-webapp", "image:docker:build": "run-script-if --bool $([ $(command -v docker) ] && echo true || echo false) --then \"docker build $(echo $(build-env dashbuilderViewerImage.buildTags) | xargs printf -- \"-t $(build-env dashbuilderViewerImageEnv.registry)/$(build-env dashbuilderViewerImageEnv.account)/$(build-env dashbuilderViewerImageEnv.name):%s\n\" | xargs echo) .\" --else \"echo Docker not found, skipping image build.\"", "image:podman:build": "run-script-if --bool $([ $(command -v podman) ] && echo true || echo false) --then \"podman build $(echo $(build-env dashbuilderViewerImage.buildTags) | xargs printf -- \"-t $(build-env dashbuilderViewerImageEnv.registry)/$(build-env dashbuilderViewerImageEnv.account)/$(build-env dashbuilderViewerImageEnv.name):%s\n\" | xargs echo) -f Containerfile\" --else \"echo Podman not found, skipping image build.\"" }, diff --git a/packages/dashbuilder/appformer/pom.xml b/packages/dashbuilder/appformer/pom.xml index acbda19e628..64c91c4fd47 100644 --- a/packages/dashbuilder/appformer/pom.xml +++ b/packages/dashbuilder/appformer/pom.xml @@ -136,29 +136,6 @@ - - - jboss-public-repository-group - JBoss Public Repository Group - https://repository.jboss.org/nexus/content/groups/public/ - - true - - - true - - - - - - scm:git:git@github.com:apache/incubator-kie-tools.git - scm:git:git@github.com:apache/incubator-kie-tools.git - scm:git:git@github.com:apache/incubator-kie-tools.git - - - github-issues - https://github.com/apache/incubator-kie-issues/issues - diff --git a/packages/dashbuilder/dashbuilder-bom/pom.xml b/packages/dashbuilder/dashbuilder-bom/pom.xml index 4f80eccec3b..d37c711bc34 100644 --- a/packages/dashbuilder/dashbuilder-bom/pom.xml +++ b/packages/dashbuilder/dashbuilder-bom/pom.xml @@ -52,24 +52,6 @@ - - - - - jboss-public-repository-group - JBoss Public Repository Group - https://repository.jboss.org/nexus/content/groups/public/ - - true - never - - - true - daily - - - - - central - Central Repository - https://repo.maven.apache.org/maven2 - default - - false - - - - apache-public-repository-group - Apache Public Repository Group - https://repository.apache.org/content/groups/public/ - - true - never - - - true - daily - - - - - 3.12.1 - true - 17 - 17 - UTF-8 - UTF-8 - 3.2.5 - 4.13.2 - diff --git a/packages/dev-deployment-dmn-form-webapp-image/Containerfile b/packages/dev-deployment-dmn-form-webapp-image/Containerfile index cd04aea2986..ceab50f22e7 100644 --- a/packages/dev-deployment-dmn-form-webapp-image/Containerfile +++ b/packages/dev-deployment-dmn-form-webapp-image/Containerfile @@ -5,19 +5,19 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations -# under the License. +# under the License. FROM --platform=linux/amd64 registry.access.redhat.com/ubi9/ubi-minimal:9.3 -RUN microdnf --disableplugin=subscription-manager -y install httpd-2.4.57-5.el9.x86_64 \ +RUN microdnf --disableplugin=subscription-manager -y install httpd \ && microdnf --disableplugin=subscription-manager clean all \ && echo "Mutex posixsem" >> /etc/httpd/conf/httpd.conf \ && sed -i -e 's/Listen 80/Listen 8081/' /etc/httpd/conf/httpd.conf \ diff --git a/packages/dev-deployment-dmn-form-webapp-image/package.json b/packages/dev-deployment-dmn-form-webapp-image/package.json index 8a778c13d37..5bc50f56546 100644 --- a/packages/dev-deployment-dmn-form-webapp-image/package.json +++ b/packages/dev-deployment-dmn-form-webapp-image/package.json @@ -16,8 +16,8 @@ "build:dev": "pnpm build:prod", "build:prod": "run-script-if --bool \"$(build-env containerImages.build)\" --then \"pnpm copy-assets\" \"pnpm image:docker:build\"", "copy-assets": "run-script-os", - "copy-assets:linux:darwin": "rimraf dist-dev && cp -R ../dev-deployment-dmn-form-webapp/dist dist-dev", - "copy-assets:win32": "rimraf dist-dev && pnpm powershell \"Copy-Item -R ../dev-deployment-dmn-form-webapp/dist dist-dev\"", + "copy-assets:linux:darwin": "rimraf dist-dev && cp -R ./node_modules/@kie-tools/dev-deployment-dmn-form-webapp/dist/ dist-dev", + "copy-assets:win32": "rimraf dist-dev && pnpm powershell \"Copy-Item -R ./node_modules/@kie-tools/dev-deployment-dmn-form-webapp/dist/ dist-dev\"", "create-test-image:build-only": "kie-tools--image-builder build -r \"$(pnpm build-env devDeploymentDmnFormWebappImage.registry)\" -a \"$(pnpm build-env devDeploymentDmnFormWebappImage.account)\" -n \"$(pnpm build-env devDeploymentDmnFormWebappImage.name)\" -t \"$(pnpm build-env devDeploymentDmnFormWebappImage.tags)\"", "create-test-image:kind": "kie-tools--image-builder kind -r \"$(pnpm build-env devDeploymentDmnFormWebappImage.registry)\" -a \"$(pnpm build-env devDeploymentDmnFormWebappImage.account)\" -n \"$(pnpm build-env devDeploymentDmnFormWebappImage.name)\" -t \"$(pnpm build-env devDeploymentDmnFormWebappImage.tags)\" --kind-cluster-name kie-sandbox-dev-cluster", "create-test-image:minikube": "kie-tools--image-builder minikube -r \"$(pnpm build-env devDeploymentDmnFormWebappImage.registry)\" -a \"$(pnpm build-env devDeploymentDmnFormWebappImage.account)\" -n \"$(pnpm build-env devDeploymentDmnFormWebappImage.name)\" -t \"$(pnpm build-env devDeploymentDmnFormWebappImage.tags)\"", diff --git a/packages/dev-deployment-kogito-quarkus-blank-app-image/Containerfile b/packages/dev-deployment-kogito-quarkus-blank-app-image/Containerfile index 182f85b38cd..41933fe213f 100644 --- a/packages/dev-deployment-kogito-quarkus-blank-app-image/Containerfile +++ b/packages/dev-deployment-kogito-quarkus-blank-app-image/Containerfile @@ -27,6 +27,7 @@ ENV DEV_DEPLOYMENT__UPLOAD_SERVICE_EXTRACT_TO_DIR=$HOME_PATH/app/src/main/resour ENV DEV_DEPLOYMENT__UPLOAD_SERVICE_PORT=8080 COPY --chown=$USER_ID:$USER_ID dist-dev/quarkus-app $HOME_PATH/app/ +COPY --chown=$USER_ID:$USER_ID dist-dev/quarkus-app-m2 /tmp/kogito/.m2/repository RUN ./mvnw clean package -B -ntp -Dmaven.test.skip -Dmaven.repo.local=/tmp/kogito/.m2/repository -Dquarkus.http.non-application-root-path=${ROOT_PATH}/q -Dquarkus.http.root-path=${ROOT_PATH} \ && chgrp -R 0 $HOME_PATH/app && chmod -R g=u $HOME_PATH/app && chgrp -R 0 /tmp/kogito && chmod -R g=u /tmp/kogito && chgrp -R 0 /.m2 && chmod -R g=u /.m2 diff --git a/packages/dev-deployment-kogito-quarkus-blank-app-image/install.js b/packages/dev-deployment-kogito-quarkus-blank-app-image/install.js new file mode 100644 index 00000000000..ef3dc831446 --- /dev/null +++ b/packages/dev-deployment-kogito-quarkus-blank-app-image/install.js @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 buildEnv = require("./env"); +const { setup } = require("@kie-tools/maven-config-setup-helper"); + +setup(` + -Drevision=${buildEnv.env.devDeploymentKogitoQuarkusBlankAppImage.version} +`); diff --git a/packages/dev-deployment-kogito-quarkus-blank-app-image/package.json b/packages/dev-deployment-kogito-quarkus-blank-app-image/package.json index d3b9852e89c..2a90303600d 100644 --- a/packages/dev-deployment-kogito-quarkus-blank-app-image/package.json +++ b/packages/dev-deployment-kogito-quarkus-blank-app-image/package.json @@ -13,18 +13,20 @@ "url": "https://github.com/apache/incubator-kie-tools/issues" }, "scripts": { - "build:dev": "run-script-if --bool \"$(build-env containerImages.build)\" --then \"pnpm copy-assets\" \"pnpm image:docker:build\"", - "build:prod": "run-script-if --bool \"$(build-env containerImages.build)\" --then \"pnpm copy-assets\" \"pnpm image:docker:build\"", - "copy-assets": "rimraf dist-dev && pnpm copy-quarkus-app-assets", - "copy-quarkus-app-assets": "run-script-os", - "copy-quarkus-app-assets:linux:darwin": "mkdir -p ./dist-dev && cp -R ../dev-deployment-kogito-quarkus-blank-app ./dist-dev/quarkus-app", - "copy-quarkus-app-assets:win32": "pnpm powershell \"New-Item -ItemType Directory -Force -Path ./dist-dev/quarkus-app; Copy-Item -R ../dev-deployment-kogito-quarkus-blank-app/* ./dist-dev/quarkus-app -Exclude @('node_modules')\"", + "build:dev": "run-script-if --bool \"$(build-env containerImages.build)\" --then \"pnpm copy:assets\" \"pnpm image:docker:build\"", + "build:prod": "run-script-if --bool \"$(build-env containerImages.build)\" --then \"pnpm copy:assets\" \"pnpm image:docker:build\"", + "copy:assets": "rimraf dist-dev && mkdir -p ./dist-dev && pnpm copy:m2-for-jbpm-quarkus-devui && pnpm copy:quarkus-app", + "copy:m2-for-jbpm-quarkus-devui": "mvn dependency:copy-dependencies -Dmdep.useRepositoryLayout=true -Dmdep.copyPom=true -DexcludeTransitive=true -DoutputDirectory=./dist-dev/quarkus-app-m2", + "copy:quarkus-app": "run-script-os", + "copy:quarkus-app:linux:darwin": " cp -R ./node_modules/@kie-tools/dev-deployment-kogito-quarkus-blank-app/ ./dist-dev/quarkus-app && rm -rf ./dist-dev/quarkus-app/node_modules ./dist-dev/quarkus-app/install.js ./dist-dev/quarkus-app/env ./dist-dev/quarkus-app/package.json", + "copy:quarkus-app:win32": "pnpm powershell \"New-Item -ItemType Directory -Force -Path ./dist-dev/quarkus-app; Copy-Item -R ./node_modules/@kie-tools/dev-deployment-kogito-quarkus-blank-app/* ./dist-dev/quarkus-app -Exclude @('node_modules')\"", "create-test-image:build-only": "kie-tools--image-builder build -r \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.registry)\" -a \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.account)\" -n \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.name)\" -t \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.tags)\" --build-arg BUILDER_IMAGE_ARG=\"$(build-env devDeploymentKogitoQuarkusBlankAppImage.builderImage)\" --build-arg ROOT_PATH=/", "create-test-image:kind": "kie-tools--image-builder kind -r \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.registry)\" -a \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.account)\" -n \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.name)\" -t \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.tags)\" --build-arg BUILDER_IMAGE_ARG=\"$(build-env devDeploymentKogitoQuarkusBlankAppImage.builderImage)\" --build-arg ROOT_PATH=/ --kind-cluster-name kie-sandbox-dev-cluster", "create-test-image:minikube": "kie-tools--image-builder minikube -r \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.registry)\" -a \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.account)\" -n \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.name)\" -t \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.tags)\" --build-arg BUILDER_IMAGE_ARG=\"$(build-env devDeploymentKogitoQuarkusBlankAppImage.builderImage)\" --build-arg ROOT_PATH=/", "create-test-image:openshift": "kie-tools--image-builder openshift -r \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.registry)\" -a \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.account)\" -n \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.name)\" -t \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.tags)\" --build-arg BUILDER_IMAGE_ARG=\"$(build-env devDeploymentKogitoQuarkusBlankAppImage.builderImage)\" --build-arg ROOT_PATH=/", "image:docker:build": "kie-tools--image-builder build -r \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.registry)\" -a \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.account)\" -n \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.name)\" -t \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.tags)\" --build-arg BUILDER_IMAGE_ARG=\"$(build-env devDeploymentKogitoQuarkusBlankAppImage.builderImage)\" --build-arg ROOT_PATH=/", "image:podman:build": "kie-tools--image-builder build -r \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.registry)\" -a \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.account)\" -n \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.name)\" -t \"$(build-env devDeploymentKogitoQuarkusBlankAppImage.tags)\" --build-arg BUILDER_IMAGE_ARG=\"$(build-env devDeploymentKogitoQuarkusBlankAppImage.builderImage)\" --build-arg ROOT_PATH=/ -e podman", + "install": "node install.js", "powershell": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command" }, "dependencies": { diff --git a/packages/dev-deployment-kogito-quarkus-blank-app-image/pom.xml b/packages/dev-deployment-kogito-quarkus-blank-app-image/pom.xml new file mode 100644 index 00000000000..1ac91d54290 --- /dev/null +++ b/packages/dev-deployment-kogito-quarkus-blank-app-image/pom.xml @@ -0,0 +1,54 @@ + + + + 4.0.0 + org.kie.kogito + dev-deployment-kogito-quarkus-blank-app-image + ${revision} + + + + org.jbpm + jbpm-quarkus-devui-deployment + ${project.version} + + + org.jbpm + jbpm-quarkus-devui + ${project.version} + + + org.jbpm + jbpm-quarkus-devui-parent + ${project.version} + pom + + + org.kie + kie-tools-maven-base + ${project.version} + pom + + + diff --git a/packages/dev-deployment-kogito-quarkus-blank-app/package.json b/packages/dev-deployment-kogito-quarkus-blank-app/package.json index 58f2c1f1aab..bac09dbecbb 100644 --- a/packages/dev-deployment-kogito-quarkus-blank-app/package.json +++ b/packages/dev-deployment-kogito-quarkus-blank-app/package.json @@ -14,21 +14,24 @@ }, "scripts": { "build:dev": "run-script-os", - "build:dev:darwin:linux": "pnpm install:mvnw && mvn clean install -DskipTests", - "build:dev:win32": "pnpm install:mvnw && pnpm powershell \"mvn clean install `-DskipTests\"", + "build:dev:darwin:linux": "mvn clean install -DskipTests", + "build:dev:win32": "pnpm powershell \"mvn clean install `-DskipTests\"", "build:prod": "pnpm lint && run-script-os", - "build:prod:darwin:linux": "pnpm install:mvnw && mvn clean install -DskipTests=$(build-env tests.run --not) -Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)", - "build:prod:win32": "pnpm install:mvnw && pnpm powershell \"mvn clean install `-DskipTests=$(build-env tests.run --not) `-Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)\"", - "install": "node install.js", + "build:prod:darwin:linux": "mvn clean install -DskipTests=$(build-env tests.run --not) -Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)", + "build:prod:win32": "pnpm powershell \"mvn clean install `-DskipTests=$(build-env tests.run --not) `-Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)\"", + "install": "node install.js && pnpm install:mvnw", "install:mvnw": "run-script-os", - "install:mvnw:darwin:linux": "mvn wrapper:wrapper", - "install:mvnw:win32": "pnpm powershell \"mvn wrapper:wrapper\"", + "install:mvnw:darwin:linux": "mvn -e org.apache.maven.plugins:maven-wrapper-plugin:3.3.0:wrapper", + "install:mvnw:win32": "pnpm powershell \"mvn -e org.apache.maven.plugins:maven-wrapper-plugin:3.3.0:wrapper\"", "lint": "echo 'Linting'", "powershell": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command", "quarkus:dev": "run-script-os", "quarkus:dev:darwin:linux": "mvn clean package quarkus:dev -DskipTests", "quarkus:dev:win32": "mvn clean package quarkus:dev `-DskipTests" }, + "dependencies": { + "@kie-tools/jbpm-quarkus-devui": "workspace:*" + }, "devDependencies": { "@kie-tools/maven-config-setup-helper": "workspace:*", "@kie-tools/root-env": "workspace:*", diff --git a/packages/dev-deployment-kogito-quarkus-blank-app/pom.xml b/packages/dev-deployment-kogito-quarkus-blank-app/pom.xml index 67a6258cd19..e31665fca9e 100644 --- a/packages/dev-deployment-kogito-quarkus-blank-app/pom.xml +++ b/packages/dev-deployment-kogito-quarkus-blank-app/pom.xml @@ -22,41 +22,20 @@ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > + + + + + org.apache + apache + 32 + + 4.0.0 org.kie.kogito dev-deployment-kogito-quarkus-blank-app ${revision} - - - - central - Central Repository - https://repo.maven.apache.org/maven2 - default - - false - - - - apache-public-repository-group - Apache Public Repository Group - https://repository.apache.org/content/groups/public/ - - true - never - - - true - daily - - - - 3.12.1 true @@ -128,6 +107,12 @@ + + io.quarkus quarkus-junit5 diff --git a/packages/dev-deployment-upload-service/dev/Containerfile.ddus-buildtime-install b/packages/dev-deployment-upload-service/dev/Containerfile.ddus-buildtime-install index 8597df5f4b8..ed2177a801b 100644 --- a/packages/dev-deployment-upload-service/dev/Containerfile.ddus-buildtime-install +++ b/packages/dev-deployment-upload-service/dev/Containerfile.ddus-buildtime-install @@ -28,7 +28,7 @@ ENV DEV_DEPLOYMENT__UPLOAD_SERVICE_PORT=8091 ENV DEV_DEPLOYMENT__UPLOAD_SERVICE_API_KEY=dev ENV DEV_DEPLOYMENT__UPLOAD_SERVICE_ROOT_PATH="/" -RUN microdnf install -y tar gzip findutils +RUN microdnf --disableplugin=subscription-manager install -y tar gzip findutils RUN curl ${DDUS_FILESERVER_IP}:${DDUS_FILESERVER_PORT}/apache/incubator-kie-tools/releases/download/${DDUS_VERSION}/getDevDeploymentUploadService.sh | sed 's/localhost:${DDUS_FILESERVER_PORT}/${DDUS_FILESERVER_IP}:${DDUS_FILESERVER_PORT}/; s/https:\/\/github.com/http:\/\/${DDUS_FILESERVER_IP}:${DDUS_FILESERVER_PORT}/' | bash diff --git a/packages/dev-deployment-upload-service/dev/Containerfile.ddus-fileserver b/packages/dev-deployment-upload-service/dev/Containerfile.ddus-fileserver index 01a3a529581..736e93baf2d 100644 --- a/packages/dev-deployment-upload-service/dev/Containerfile.ddus-fileserver +++ b/packages/dev-deployment-upload-service/dev/Containerfile.ddus-fileserver @@ -19,7 +19,7 @@ FROM --platform=linux/amd64 registry.access.redhat.com/ubi9/ubi-minimal:9.3 ARG DDUS_VERSION="0.0.0" -RUN microdnf -y install httpd \ +RUN microdnf --disableplugin=subscription-manager install -y httpd \ && echo "Mutex posixsem" >> /etc/httpd/conf/httpd.conf \ && sed -i -e 's/Listen 80/Listen 8090/' /etc/httpd/conf/httpd.conf \ && sed -i -e 's/#ServerName www.example.com:80/ServerName 127.0.0.1:8090/' /etc/httpd/conf/httpd.conf \ diff --git a/packages/dev-deployment-upload-service/dev/Containerfile.ddus-runtime-install b/packages/dev-deployment-upload-service/dev/Containerfile.ddus-runtime-install index 7731d1a359a..f8cecbdf638 100644 --- a/packages/dev-deployment-upload-service/dev/Containerfile.ddus-runtime-install +++ b/packages/dev-deployment-upload-service/dev/Containerfile.ddus-runtime-install @@ -28,7 +28,7 @@ ENV DEV_DEPLOYMENT__UPLOAD_SERVICE_PORT=8092 ENV DEV_DEPLOYMENT__UPLOAD_SERVICE_API_KEY=dev ENV DEV_DEPLOYMENT__UPLOAD_SERVICE_ROOT_PATH="/" -RUN microdnf install -y tar gzip findutils +RUN microdnf --disableplugin=subscription-manager install -y tar gzip findutils CMD curl $DDUS_FILESERVER_IP:${DDUS_FILESERVER_PORT}/apache/incubator-kie-tools/releases/download/$DDUS_VERSION/getDevDeploymentUploadService.sh | sed 's/localhost:${DDUS_FILESERVER_PORT}/$DDUS_FILESERVER_IP:${DDUS_FILESERVER_PORT}/; s/https:\/\/github.com/http:\/\/$DDUS_FILESERVER_IP:${DDUS_FILESERVER_PORT}/' | bash \ && dev-deployment-upload-service \ diff --git a/packages/dmn-editor-envelope/package.json b/packages/dmn-editor-envelope/package.json index 026f7e09739..44963a5078a 100644 --- a/packages/dmn-editor-envelope/package.json +++ b/packages/dmn-editor-envelope/package.json @@ -27,6 +27,7 @@ "@kie-tools-core/editor": "workspace:*", "@kie-tools-core/envelope": "workspace:*", "@kie-tools-core/envelope-bus": "workspace:*", + "@kie-tools-core/keyboard-shortcuts": "workspace:*", "@kie-tools-core/notifications": "workspace:*", "@kie-tools-core/react-hooks": "workspace:*", "@kie-tools-core/workspace": "workspace:*", diff --git a/packages/dmn-editor-envelope/src/DmnEditorFactory.tsx b/packages/dmn-editor-envelope/src/DmnEditorFactory.tsx index b5012e4cb2f..411287583be 100644 --- a/packages/dmn-editor-envelope/src/DmnEditorFactory.tsx +++ b/packages/dmn-editor-envelope/src/DmnEditorFactory.tsx @@ -150,6 +150,7 @@ function DmnEditorRootWrapper({ onOpenFileFromNormalizedPosixPathRelativeToTheWorkspaceRoot } workspaceRootAbsolutePosixPath={workspaceRootAbsolutePosixPath} + keyboardShortcutsService={envelopeContext?.services.keyboardShortcuts} /> ); } diff --git a/packages/dmn-editor-envelope/src/DmnEditorRoot.tsx b/packages/dmn-editor-envelope/src/DmnEditorRoot.tsx index 50907d890a0..3b06bd42875 100644 --- a/packages/dmn-editor-envelope/src/DmnEditorRoot.tsx +++ b/packages/dmn-editor-envelope/src/DmnEditorRoot.tsx @@ -41,6 +41,7 @@ import { imperativePromiseHandle, PromiseImperativeHandle, } from "@kie-tools-core/react-hooks/dist/useImperativePromiseHandler"; +import { KeyboardShortcutsService } from "@kie-tools-core/keyboard-shortcuts/dist/envelope/KeyboardShortcutsService"; export const EXTERNAL_MODELS_SEARCH_GLOB_PATTERN = "**/*.{dmn,pmml}"; @@ -60,6 +61,7 @@ export type DmnEditorRootProps = { onRequestWorkspaceFileContent: WorkspaceChannelApi["kogitoWorkspace_resourceContentRequest"]; onOpenFileFromNormalizedPosixPathRelativeToTheWorkspaceRoot: WorkspaceChannelApi["kogitoWorkspace_openFile"]; workspaceRootAbsolutePosixPath: string; + keyboardShortcutsService: KeyboardShortcutsService | undefined; }; export type DmnEditorRootState = { @@ -70,6 +72,8 @@ export type DmnEditorRootState = { externalModelsByNamespace: DmnEditor.ExternalModelsIndex; readonly: boolean; externalModelsManagerDoneBootstraping: boolean; + keyboardShortcutsRegisterIds: number[]; + keyboardShortcutsRegistred: boolean; }; export class DmnEditorRoot extends React.Component { @@ -89,6 +93,8 @@ export class DmnEditorRoot extends React.Component, + prevState: Readonly, + snapshot?: any + ): void { + if (this.props.keyboardShortcutsService === undefined || this.state.keyboardShortcutsRegistred === true) { + return; + } + + const commands = this.dmnEditorRef.current?.getCommands(); + if (commands === undefined) { + return; + } + const cancelAction = this.props.keyboardShortcutsService.registerKeyPress("Escape", "Edit | Unselect", async () => + commands.cancelAction() + ); + const deleteSelectionBackspace = this.props.keyboardShortcutsService.registerKeyPress( + "Backspace", + "Edit | Delete selection", + async () => {} + ); + const deleteSelectionDelete = this.props.keyboardShortcutsService.registerKeyPress( + "Delete", + "Edit | Delete selection", + async () => {} + ); + const selectAll = this.props.keyboardShortcutsService?.registerKeyPress( + "A", + "Edit | Select/Deselect all", + async () => commands.selectAll() + ); + const createGroup = this.props.keyboardShortcutsService?.registerKeyPress( + "G", + "Edit | Create group wrapping selection", + async () => { + console.log(" KEY GROUP PRESSED, ", commands); + return commands.createGroup(); + } + ); + const hideFromDrd = this.props.keyboardShortcutsService?.registerKeyPress("X", "Edit | Hide from DRD", async () => + commands.hideFromDrd() + ); + const copy = this.props.keyboardShortcutsService?.registerKeyPress("Ctrl+C", "Edit | Copy nodes", async () => + commands.copy() + ); + const cut = this.props.keyboardShortcutsService?.registerKeyPress("Ctrl+X", "Edit | Cut nodes", async () => + commands.cut() + ); + const paste = this.props.keyboardShortcutsService?.registerKeyPress("Ctrl+V", "Edit | Paste nodes", async () => + commands.paste() + ); + const togglePropertiesPanel = this.props.keyboardShortcutsService?.registerKeyPress( + "I", + "Misc | Open/Close properties panel", + async () => commands.togglePropertiesPanel() + ); + const toggleHierarchyHighlight = this.props.keyboardShortcutsService?.registerKeyPress( + "H", + "Misc | Toggle hierarchy highlights", + async () => commands.toggleHierarchyHighlight() + ); + const moveUp = this.props.keyboardShortcutsService.registerKeyPress( + "Up", + "Move | Move selection up", + async () => {} + ); + const moveDown = this.props.keyboardShortcutsService.registerKeyPress( + "Down", + "Move | Move selection down", + async () => {} + ); + const moveLeft = this.props.keyboardShortcutsService.registerKeyPress( + "Left", + "Move | Move selection left", + async () => {} + ); + const moveRight = this.props.keyboardShortcutsService.registerKeyPress( + "Right", + "Move | Move selection right", + async () => {} + ); + const bigMoveUp = this.props.keyboardShortcutsService.registerKeyPress( + "Shift + Up", + "Move | Move selection up a big distance", + async () => {} + ); + const bigMoveDown = this.props.keyboardShortcutsService.registerKeyPress( + "Shift + Down", + "Move | Move selection down a big distance", + async () => {} + ); + const bigMoveLeft = this.props.keyboardShortcutsService.registerKeyPress( + "Shift + Left", + "Move | Move selection left a big distance", + async () => {} + ); + const bigMoveRight = this.props.keyboardShortcutsService.registerKeyPress( + "Shift + Right", + "Move | Move selection right a big distance", + async () => {} + ); + const focusOnBounds = this.props.keyboardShortcutsService?.registerKeyPress( + "B", + "Navigate | Focus on selection", + async () => commands.focusOnSelection() + ); + const resetPosition = this.props.keyboardShortcutsService?.registerKeyPress( + "Space", + "Navigate | Reset position to origin", + async () => commands.resetPosition() + ); + const pan = this.props.keyboardShortcutsService?.registerKeyDownThenUp( + "Alt", + "Navigate | Hold and drag to Pan", + async () => commands.panDown(), + async () => commands.panUp() + ); + const zoom = this.props.keyboardShortcutsService?.registerKeyPress( + "Ctrl", + "Navigate | Hold and scroll to zoom in/out", + async () => {} + ); + const navigateHorizontally = this.props.keyboardShortcutsService?.registerKeyPress( + "Shift", + "Navigate | Hold and scroll to navigate horizontally", + async () => {} + ); + + this.setState((prev) => ({ + ...prev, + keyboardShortcutsRegistred: true, + keyboardShortcutsRegisterIds: [ + bigMoveDown, + bigMoveLeft, + bigMoveRight, + bigMoveUp, + cancelAction, + copy, + createGroup, + cut, + deleteSelectionBackspace, + deleteSelectionDelete, + focusOnBounds, + hideFromDrd, + moveDown, + moveLeft, + moveRight, + moveUp, + navigateHorizontally, + pan, + paste, + resetPosition, + selectAll, + toggleHierarchyHighlight, + togglePropertiesPanel, + zoom, + ], + })); + } + + public componentWillUnmount() { + const keyboardShortcuts = this.dmnEditorRef.current?.getCommands(); + if (keyboardShortcuts === undefined) { + return; + } + + this.state.keyboardShortcutsRegisterIds.forEach((id) => { + this.props.keyboardShortcutsService?.deregister(id); + }); + } + public render() { return ( <> diff --git a/packages/dmn-editor/.storybook/main.ts b/packages/dmn-editor/.storybook/main.ts index b8169c7262a..5b60b650813 100644 --- a/packages/dmn-editor/.storybook/main.ts +++ b/packages/dmn-editor/.storybook/main.ts @@ -18,6 +18,7 @@ */ import { baseConfig } from "@kie-tools/storybook-base/dist/config/baseConfig"; +import common from "@kie-tools-core/webpack-base/webpack.common.config"; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore @@ -25,7 +26,7 @@ import { env } from "../env"; const buildEnv: any = env; // build-env is not typed const config = { - ...baseConfig(buildEnv.webpack.dev), + ...baseConfig(buildEnv.webpack.dev, common(buildEnv.webpack)), }; export default config; diff --git a/packages/dmn-editor/.storybook/manager.ts b/packages/dmn-editor/.storybook/manager.ts index a806377b64c..7d64e5cf631 100644 --- a/packages/dmn-editor/.storybook/manager.ts +++ b/packages/dmn-editor/.storybook/manager.ts @@ -22,6 +22,7 @@ import { KieToolsTheme } from "@kie-tools/storybook-base/dist/config/theme"; addons.setConfig({ theme: KieToolsTheme, - // RF adds listeners to the document level + // Disable Storybook keyboard shortcuts. + // ReactFlow adds listeners to the document level enableShortcuts: false, }); diff --git a/packages/dmn-editor/package.json b/packages/dmn-editor/package.json index 841f7a7cafa..b3a425f7f5d 100644 --- a/packages/dmn-editor/package.json +++ b/packages/dmn-editor/package.json @@ -74,6 +74,7 @@ "@kie-tools/tsconfig": "workspace:*", "@playwright/test": "^1.38.1", "@storybook/addon-links": "^7.3.2", + "@storybook/addon-webpack5-compiler-babel": "^3.0.3", "@storybook/blocks": "^7.3.2", "@storybook/manager-api": "^7.3.2", "@storybook/preview-api": "^7.3.2", diff --git a/packages/dmn-editor/src/DmnEditor.css b/packages/dmn-editor/src/DmnEditor.css index 1011c465840..7187edd7719 100644 --- a/packages/dmn-editor/src/DmnEditor.css +++ b/packages/dmn-editor/src/DmnEditor.css @@ -71,6 +71,7 @@ z-index: 1; } .kie-dmn-editor--input-data-node { + outline: none; width: 100%; height: 100%; } diff --git a/packages/dmn-editor/src/DmnEditor.tsx b/packages/dmn-editor/src/DmnEditor.tsx index d667fd89829..571d18ec019 100644 --- a/packages/dmn-editor/src/DmnEditor.tsx +++ b/packages/dmn-editor/src/DmnEditor.tsx @@ -20,32 +20,33 @@ import "@patternfly/react-core/dist/styles/base.css"; import "reactflow/dist/style.css"; -import { AllDmnMarshallers, DmnLatestModel } from "@kie-tools/dmn-marshaller"; +import * as React from "react"; +import * as ReactDOM from "react-dom"; +import * as RF from "reactflow"; +import { ErrorBoundary, ErrorBoundaryPropsWithFallback } from "react-error-boundary"; +import { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react"; +import { original } from "immer"; import { PMML } from "@kie-tools/pmml-editor-marshaller"; -import { Drawer, DrawerContent, DrawerContentBody } from "@patternfly/react-core/dist/js/components/Drawer"; -import { Label } from "@patternfly/react-core/dist/js/components/Label"; -import { Tab, TabTitleIcon, TabTitleText, Tabs } from "@patternfly/react-core/dist/js/components/Tabs"; +import { DmnLatestModel, AllDmnMarshallers } from "@kie-tools/dmn-marshaller"; import { FileIcon } from "@patternfly/react-icons/dist/js/icons/file-icon"; import { InfrastructureIcon } from "@patternfly/react-icons/dist/js/icons/infrastructure-icon"; import { PficonTemplateIcon } from "@patternfly/react-icons/dist/js/icons/pficon-template-icon"; -import { original } from "immer"; -import * as React from "react"; -import { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react"; -import * as ReactDOM from "react-dom"; -import { ErrorBoundary, ErrorBoundaryPropsWithFallback } from "react-error-boundary"; -import * as RF from "reactflow"; -import { DmnEditorContextProvider, useDmnEditor } from "./DmnEditorContext"; -import { DmnEditorErrorFallback } from "./DmnEditorErrorFallback"; +import { Drawer, DrawerContent, DrawerContentBody } from "@patternfly/react-core/dist/js/components/Drawer"; +import { Label } from "@patternfly/react-core/dist/js/components/Label"; +import { Tab, TabTitleIcon, TabTitleText, Tabs } from "@patternfly/react-core/dist/js/components/Tabs"; import { BoxedExpressionScreen } from "./boxedExpressions/BoxedExpressionScreen"; import { DataTypes } from "./dataTypes/DataTypes"; import { Diagram, DiagramRef } from "./diagram/Diagram"; import { DmnVersionLabel } from "./diagram/DmnVersionLabel"; +import { normalize } from "./normalization/normalize"; +import { BoxedExpressionPropertiesPanel } from "./propertiesPanel/BoxedExpressionPropertiesPanel"; +import { DmnEditorContextProvider, useDmnEditor } from "./DmnEditorContext"; +import { DmnEditorErrorFallback } from "./DmnEditorErrorFallback"; import { DmnEditorExternalModelsContextProvider, useExternalModels, } from "./includedModels/DmnEditorDependenciesContext"; import { IncludedModels } from "./includedModels/IncludedModels"; -import { BeePropertiesPanel } from "./propertiesPanel/BeePropertiesPanel"; import { DiagramPropertiesPanel } from "./propertiesPanel/DiagramPropertiesPanel"; import { ComputedStateCache } from "./store/ComputedStateCache"; import { Computed, DmnEditorTab, createDmnEditorStore, defaultStaticState } from "./store/Store"; @@ -56,6 +57,7 @@ import { INITIAL_COMPUTED_CACHE } from "./store/computed/initial"; import "@kie-tools/dmn-marshaller/dist/kie-extensions"; // This is here because of the KIE Extension for DMN. import "./DmnEditor.css"; // Leave it for last, as this overrides some of the PF and RF styles. +import { Commands, CommandsContextProvider, useCommands } from "./commands/CommandsContextProvider"; const ON_MODEL_CHANGE_DEBOUNCE_TIME_IN_MS = 500; @@ -64,6 +66,7 @@ const SVG_PADDING = 20; export type DmnEditorRef = { reset: (mode: DmnLatestModel) => void; getDiagramSvg: () => Promise; + getCommands: () => Commands; }; export type EvaluationResults = Record; @@ -170,14 +173,13 @@ export const DmnEditorInternal = ({ const navigationTab = useDmnEditorStore((s) => s.navigation.tab); const dmn = useDmnEditorStore((s) => s.dmn); const isDiagramEditingInProgress = useDmnEditorStore((s) => s.computed(s).isDiagramEditingInProgress()); - const dmnEditorStoreApi = useDmnEditorStoreApi(); + const { commandsRef } = useCommands(); const { dmnModelBeforeEditingRef, dmnEditorRootElementRef } = useDmnEditor(); const { externalModelsByNamespace } = useExternalModels(); // Refs - const diagramRef = useRef(null); const diagramContainerRef = useRef(null); const beeContainerRef = useRef(null); @@ -232,8 +234,9 @@ export const DmnEditorInternal = ({ return new XMLSerializer().serializeToString(svg); }, + getCommands: () => commandsRef.current, }), - [dmnEditorStoreApi, externalModelsByNamespace] + [dmnEditorStoreApi, externalModelsByNamespace, commandsRef] ); // Make sure the DMN Editor reacts to props changing. @@ -243,8 +246,8 @@ export const DmnEditorInternal = ({ if (model === original(state.dmn.model)) { return; } - state.dmn.model = model; - dmnModelBeforeEditingRef.current = model; + state.dmn.model = normalize(model); + dmnModelBeforeEditingRef.current = state.dmn.model; }); }, [dmnEditorStoreApi, model]); @@ -328,7 +331,7 @@ export const DmnEditorInternal = ({ }, [dmn.model.definitions.import?.length, dmn.model.definitions.itemDefinition?.length]); const diagramPropertiesPanel = useMemo(() => , []); - const beePropertiesPanel = useMemo(() => , []); + const beePropertiesPanel = useMemo(() => , []); return (
@@ -406,7 +409,9 @@ export const DmnEditor = React.forwardRef((props: DmnEditorProps, ref: React.Ref - + + + diff --git a/packages/dmn-editor/src/boxedExpressions/BoxedExpressionScreen.tsx b/packages/dmn-editor/src/boxedExpressions/BoxedExpressionScreen.tsx index f46d021d462..dbc155484f7 100644 --- a/packages/dmn-editor/src/boxedExpressions/BoxedExpressionScreen.tsx +++ b/packages/dmn-editor/src/boxedExpressions/BoxedExpressionScreen.tsx @@ -286,8 +286,6 @@ export function BoxedExpressionScreen({ container }: { container: React.RefObjec }, }); - console.log(defaultWidthsById); - return { expression: defaultExpression, widthsById: defaultWidthsById, @@ -385,10 +383,10 @@ export function BoxedExpressionScreen({ container }: { container: React.RefObjec pmmlDocuments={pmmlDocuments} isResetSupportedOnRootExpression={isResetSupportedOnRootExpression} expressionHolderId={activeDrgElementId!} - expressionHolderName={drgElement?.variable?.["@_name"] || drgElement?.["@_name"] || ""} + expressionHolderName={drgElement?.variable?.["@_name"] ?? drgElement?.["@_name"] ?? ""} expressionHolderTypeRef={ - drgElement?.variable?.["@_typeRef"] || - expression?.boxedExpression?.["@_typeRef"] || + drgElement?.variable?.["@_typeRef"] ?? + expression?.boxedExpression?.["@_typeRef"] ?? DmnBuiltInDataType.Undefined } expression={expression?.boxedExpression} @@ -405,7 +403,7 @@ export function BoxedExpressionScreen({ container }: { container: React.RefObjec ); } -function drgElementToBoxedExpression( +export function drgElementToBoxedExpression( expressionHolder: | (DMN15__tDecision & { __$$element: "decision" }) | (DMN15__tBusinessKnowledgeModel & { __$$element: "businessKnowledgeModel" }) @@ -418,7 +416,7 @@ function drgElementToBoxedExpression( } : { __$$element: "functionDefinition", - "@_id": generateUuid(), + "@_id": expressionHolder.variable?.["@_id"] ?? generateUuid(), "@_kind": "FEEL", expression: undefined!, // SPEC DISCREPANCY: Starting without an expression gives users the ability to select the expression type. formalParameter: [], @@ -426,7 +424,16 @@ function drgElementToBoxedExpression( "@_typeRef": expressionHolder.variable?.["@_typeRef"], }; } else if (expressionHolder.__$$element === "decision") { - return expressionHolder.expression; + return expressionHolder.expression + ? { + ...expressionHolder.expression, + "@_label": + expressionHolder?.variable?.["@_name"] ?? + expressionHolder.expression["@_label"] ?? + expressionHolder?.["@_name"], + "@_typeRef": expressionHolder?.variable?.["@_typeRef"] ?? expressionHolder.expression["@_typeRef"], + } + : undefined; } else { throw new Error( `Unknown __$$element of expressionHolder that has an expression '${(expressionHolder as any).__$$element}'.` diff --git a/packages/dmn-editor/src/boxedExpressions/boxedExpressionIndex.ts b/packages/dmn-editor/src/boxedExpressions/boxedExpressionIndex.ts new file mode 100644 index 00000000000..ec3d46742d5 --- /dev/null +++ b/packages/dmn-editor/src/boxedExpressions/boxedExpressionIndex.ts @@ -0,0 +1,544 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + DMN15__tConditional, + DMN15__tContext, + DMN15__tDecisionTable, + DMN15__tFilter, + DMN15__tFor, + DMN15__tFunctionDefinition, + DMN15__tInvocation, + DMN15__tList, + DMN15__tLiteralExpression, + DMN15__tQuantified, + DMN15__tRelation, +} from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { AllExpressionTypes, AllExpressions, AllExpressionsWithoutTypes } from "../dataTypes/DataTypeSpec"; + +interface PathType { + type: AllExpressionTypes; + root: string; +} + +interface ConditionalExpressionPath extends PathType { + type: "conditional"; + row?: "if" | "else" | "then"; +} + +interface ContextExpressionPath extends PathType { + type: "context"; + row?: number; + column?: "variable" | "expression"; +} + +interface DecisionTablePath extends PathType { + type: "decisionTable"; + header?: "input" | "output"; + row?: number; + column?: number; +} + +interface EveryExpressionPath extends PathType { + type: "every"; + row?: "variable" | "in" | "statisfies"; +} + +interface FilterExpressionPath extends PathType { + type: "filter"; + row?: "in" | "match"; +} + +interface ForExpressionPath extends PathType { + type: "for"; + row?: "variable" | "in" | "return"; +} + +interface FunctionDefinitionExpressionPath extends PathType { + type: "functionDefinition"; + parameterIndex?: number; +} + +interface InvocationExpressionPath extends PathType { + type: "invocation"; + row?: number; + column?: "parameter" | "expression"; +} + +interface ListExpressionPath extends PathType { + type: "list"; + row?: number; +} + +interface LiteralExpressionPath extends PathType { + type: "literalExpression"; +} + +interface RelationExpressionPath extends PathType { + type: "relation"; + row?: number; + column?: number; +} + +interface SomeExpressionPath extends PathType { + type: "some"; + row?: "variable" | "in" | "statisfies"; +} + +export type ExpressionPath = + | ConditionalExpressionPath + | ContextExpressionPath + | DecisionTablePath + | EveryExpressionPath + | FilterExpressionPath + | ForExpressionPath + | FunctionDefinitionExpressionPath + | InvocationExpressionPath + | ListExpressionPath + | LiteralExpressionPath + | RelationExpressionPath + | SomeExpressionPath; + +/** + * A map of "@_id" to cell (expression) and its path in the expression hierarchy + */ +export type BoxedExpressionIndex = Map< + string, + { expressionPath: ExpressionPath[]; cell: AllExpressionsWithoutTypes | AllExpressionsWithoutTypes[] } +>; + +export function generateBoxedExpressionIndex( + expression: AllExpressions, + parentMap: BoxedExpressionIndex, + parentExpressionPath: ExpressionPath[] +): BoxedExpressionIndex { + const map: BoxedExpressionIndex = parentMap ? parentMap : new Map(); + switch (expression?.__$$element) { + case "conditional": + expression["@_id"] && + map.set(expression["@_id"], { + expressionPath: [...parentExpressionPath, { type: "conditional", root: expression["@_id"] }], + cell: expression, + }); + generateBoxedExpressionIndex(expression.if.expression, map, [ + ...parentExpressionPath, + { type: "conditional", row: "if", root: expression["@_id"]! }, + ]); + generateBoxedExpressionIndex(expression.else.expression, map, [ + ...parentExpressionPath, + { type: "conditional", row: "else", root: expression["@_id"]! }, + ]); + generateBoxedExpressionIndex(expression.then.expression, map, [ + ...parentExpressionPath, + { type: "conditional", row: "then", root: expression["@_id"]! }, + ]); + return map; + case "context": + expression["@_id"] && + map.set(expression["@_id"], { + expressionPath: [...parentExpressionPath, { type: "context", root: expression["@_id"] }], + cell: expression, + }); + expression.contextEntry?.forEach((ce, row) => { + const id = ce.variable?.["@_id"] ?? ce?.["@_id"]; + id && + ce.variable && + map.set(id, { + expressionPath: [ + ...parentExpressionPath, + { type: "context", row, column: "variable", root: expression["@_id"]! }, + ], + cell: ce.variable, + }); + generateBoxedExpressionIndex(ce.expression, map, [ + ...parentExpressionPath, + { type: "context", row, column: "expression", root: expression["@_id"]! }, + ]); + }); + return map; + case "decisionTable": + expression["@_id"] && + map.set(expression["@_id"], { + expressionPath: [...parentExpressionPath, { type: "decisionTable", root: expression["@_id"] }], + cell: expression, + }); + expression.output.forEach( + (o, column) => + o["@_id"] && + map.set(o["@_id"], { + expressionPath: [ + ...parentExpressionPath, + { type: "decisionTable", header: "output", row: -1, column, root: expression["@_id"]! }, + ], + cell: o, + }) + ); + expression.input?.forEach((i, column) => { + i["@_id"] && + map.set(i["@_id"], { + expressionPath: [ + ...parentExpressionPath, + { type: "decisionTable", header: "input", row: -1, column, root: expression["@_id"]! }, + ], + cell: i, + }); + }); + expression.rule?.forEach((r, row) => { + r.outputEntry?.forEach( + (ro, column) => + ro["@_id"] && + map.set(ro["@_id"], { + expressionPath: [ + ...parentExpressionPath, + { type: "decisionTable", header: "output", row, column, root: expression["@_id"]! }, + ], + cell: ro, + }) + ); + r.inputEntry?.forEach( + (ri, column) => + ri["@_id"] && + map.set(ri["@_id"], { + expressionPath: [ + ...parentExpressionPath, + { type: "decisionTable", header: "input", row, column, root: expression["@_id"]! }, + ], + cell: ri, + }) + ); + }); + return map; + case "every": + expression["@_id"] && + map.set(expression["@_id"], { + expressionPath: [...parentExpressionPath, { type: "every", root: expression["@_id"] }], + cell: expression, + }); + expression["@_id"] && + map.set(`${expression["@_id"]}-iteratorVariable`, { + expressionPath: [...parentExpressionPath, { type: "every", row: "variable", root: expression["@_id"] }], + cell: expression, + }); + generateBoxedExpressionIndex(expression.in.expression, map, [ + ...parentExpressionPath, + { type: "every", row: "in", root: expression["@_id"]! }, + ]); + generateBoxedExpressionIndex(expression.satisfies.expression, map, [ + ...parentExpressionPath, + { type: "every", row: "statisfies", root: expression["@_id"]! }, + ]); + return map; + case "filter": + expression["@_id"] && + map.set(expression["@_id"], { + expressionPath: [...parentExpressionPath, { type: "filter", root: expression["@_id"] }], + cell: expression, + }); + generateBoxedExpressionIndex(expression.in.expression, map, [ + ...parentExpressionPath, + { type: "filter", row: "in", root: expression["@_id"]! }, + ]); + generateBoxedExpressionIndex(expression.match.expression, map, [ + ...parentExpressionPath, + { type: "filter", row: "match", root: expression["@_id"]! }, + ]); + return map; + case "for": + expression["@_id"] && + map.set(expression["@_id"], { + expressionPath: [...parentExpressionPath, { type: "for", root: expression["@_id"] }], + cell: expression, + }); + expression["@_id"] && + map.set(`${expression["@_id"]}-iteratorVariable`, { + expressionPath: [...parentExpressionPath, { type: "for", row: "variable", root: expression["@_id"] }], + cell: expression, + }); + generateBoxedExpressionIndex(expression.in.expression, map, [ + ...parentExpressionPath, + { type: "for", row: "in", root: expression["@_id"]! }, + ]); + generateBoxedExpressionIndex(expression.return.expression, map, [ + ...parentExpressionPath, + { type: "for", row: "return", root: expression["@_id"]! }, + ]); + return map; + case "functionDefinition": + expression["@_id"] && + map.set(expression["@_id"], { + expressionPath: [...parentExpressionPath, { type: "functionDefinition", root: expression["@_id"] }], + cell: expression, + }); + + if (expression.expression?.["@_id"]) { + generateBoxedExpressionIndex(expression.expression, map, [ + ...parentExpressionPath, + { type: "functionDefinition", parameterIndex: -1, root: expression["@_id"]! }, + ]); + } + + map.set(`${expression["@_id"]}-parameters`, { + expressionPath: [ + ...parentExpressionPath, + { type: "functionDefinition", parameterIndex: 0, root: expression["@_id"]! }, + ], + cell: expression.formalParameter ?? [], + }); + return map; + case "invocation": + expression["@_id"] && + map.set(expression["@_id"], { + expressionPath: [...parentExpressionPath, { type: "invocation", root: expression["@_id"] }], + cell: expression, + }); + expression.binding?.forEach((b, row) => { + b.parameter["@_id"] && + map.set(b.parameter["@_id"], { + expressionPath: [ + ...parentExpressionPath, + { type: "invocation", row, column: "parameter", root: expression["@_id"]! }, + ], + cell: b.parameter, + }); + b.expression && + generateBoxedExpressionIndex(b.expression, map, [ + ...parentExpressionPath, + { type: "invocation", row, column: "expression", root: expression["@_id"]! }, + ]); + }); + // function call + expression.expression && + expression.expression["@_id"] && + map.set(expression.expression["@_id"], { + expressionPath: [ + ...parentExpressionPath, + { type: "invocation", row: -1, column: "expression", root: expression["@_id"]! }, + ], + cell: expression.expression, + }); + return map; + case "list": + expression["@_id"] && + map.set(expression["@_id"], { + expressionPath: [...parentExpressionPath, { type: "list", root: expression["@_id"] }], + cell: expression, + }); + expression.expression?.forEach((e, row) => + generateBoxedExpressionIndex(e, map, [ + ...parentExpressionPath, + { type: "list", row, root: expression["@_id"]! }, + ]) + ); + return map; + case "literalExpression": + expression["@_id"] && + map.set(expression["@_id"], { + expressionPath: [...parentExpressionPath, { type: "literalExpression", root: expression["@_id"] }], + cell: expression, + }); + return map; + case "relation": + expression["@_id"] && + map.set(expression["@_id"], { + expressionPath: [...parentExpressionPath, { type: "relation", root: expression["@_id"] }], + cell: expression, + }); + expression.column?.forEach( + (c, column) => + c["@_id"] && + map.set(c["@_id"], { + expressionPath: [...parentExpressionPath, { type: "relation", row: -1, column, root: expression["@_id"]! }], + cell: c, + }) + ); + expression.row?.forEach((r, row) => + r.expression?.forEach((re, column) => { + re["@_id"] && + map.set(re["@_id"], { + expressionPath: [...parentExpressionPath, { type: "relation", row, column, root: expression["@_id"]! }], + cell: re, + }); + }) + ); + return map; + case "some": + expression["@_id"] && + map.set(expression["@_id"], { + expressionPath: [...parentExpressionPath, { type: "some", root: expression["@_id"] }], + cell: expression, + }); + expression["@_id"] && + map.set(`${expression["@_id"]}-iteratorVariable`, { + expressionPath: [...parentExpressionPath, { type: "some", row: "variable", root: expression["@_id"] }], + cell: expression, + }); + generateBoxedExpressionIndex(expression.in.expression, map, [ + ...parentExpressionPath, + { type: "some", row: "in", root: expression["@_id"]! }, + ]); + generateBoxedExpressionIndex(expression.satisfies.expression, map, [ + ...parentExpressionPath, + { type: "some", row: "statisfies", root: expression["@_id"]! }, + ]); + return map; + } +} + +export function getDmnObjectByPath( + paths: ExpressionPath[], + expressionRoot?: AllExpressionsWithoutTypes +): AllExpressionsWithoutTypes | undefined { + if (!expressionRoot) { + return; + } + return paths.reduce((expressionToEdit: AllExpressionsWithoutTypes, path) => { + if (path.type === "conditional") { + // root + if (path.row === undefined) { + return expressionToEdit as DMN15__tConditional; + } + if (path.row === "if") { + return (expressionToEdit as DMN15__tConditional).if.expression; + } + if (path.row === "else") { + return (expressionToEdit as DMN15__tConditional).else.expression; + } + return (expressionToEdit as DMN15__tConditional).then.expression; + } + if (path.type === "context") { + // root + if (path.row === undefined || path.column === undefined) { + return expressionToEdit as DMN15__tContext; + } + if (path.column === "expression") { + return (expressionToEdit as DMN15__tContext).contextEntry?.[path.row].expression; + } + return (expressionToEdit as DMN15__tContext).contextEntry?.[path.row].variable; + } + if (path.type === "decisionTable") { + // root + if (path.row === undefined || path.column === undefined) { + return expressionToEdit as DMN15__tDecisionTable; + } + if (path.header === "input") { + if (path.row < 0) { + return (expressionToEdit as DMN15__tDecisionTable).input?.[path.column]; + } + return (expressionToEdit as DMN15__tDecisionTable).rule?.[path.row].inputEntry?.[path.column]; + } + if (path.row < 0) { + return (expressionToEdit as DMN15__tDecisionTable).output?.[path.column]; + } + return (expressionToEdit as DMN15__tDecisionTable).rule?.[path.row].outputEntry?.[path.column]; + } + if (path.type === "every") { + // root + if (path.row === undefined) { + return expressionToEdit as DMN15__tQuantified; + } + if (path.row === "variable") { + return expressionToEdit as DMN15__tQuantified; + } + if (path.row === "in") { + return (expressionToEdit as DMN15__tQuantified).in.expression; + } + return (expressionToEdit as DMN15__tQuantified).satisfies.expression; + } + if (path.type === "filter") { + // root + if (path.row === undefined) { + return expressionToEdit as DMN15__tFilter; + } + if (path.row === "in") { + return (expressionToEdit as DMN15__tFilter).in.expression; + } + return (expressionToEdit as DMN15__tFilter).match.expression; + } + if (path.type === "for") { + // root + if (path.row === undefined) { + return expressionToEdit as DMN15__tFor; + } + if (path.row === "variable") { + return expressionToEdit as DMN15__tFor; + } + if (path.row === "in") { + return (expressionToEdit as DMN15__tFor).in.expression; + } + return (expressionToEdit as DMN15__tFor).return.expression; + } + if (path.type === "functionDefinition") { + // root + if (!path.parameterIndex) { + return expressionToEdit as DMN15__tFunctionDefinition; + } + if (path.parameterIndex < 0) { + return (expressionToEdit as DMN15__tFunctionDefinition).expression; + } + return expressionToEdit as DMN15__tFunctionDefinition; + } + if (path.type === "invocation") { + // root + if (path.row === undefined || path.column === undefined) { + return expressionToEdit as DMN15__tInvocation; + } + if (path.column === "parameter") { + return (expressionToEdit as DMN15__tInvocation).binding?.[path.row].parameter; + } + if (path.column === "expression" && path.row >= 0) { + return (expressionToEdit as DMN15__tInvocation).binding?.[path.row].expression; + } + // function call + return (expressionToEdit as DMN15__tInvocation).expression; + } + if (path.type === "list") { + // root + if (path.row === undefined) { + return expressionToEdit as DMN15__tList; + } + return (expressionToEdit as DMN15__tList).expression?.[path.row]; + } + if (path.type === "literalExpression") { + return expressionToEdit as DMN15__tLiteralExpression; + } + if (path.type === "relation") { + // root + if (path.row === undefined || path.column === undefined) { + return expressionToEdit as DMN15__tRelation; + } + if (path.row < 0) { + return (expressionToEdit as DMN15__tRelation).column?.[path.column]; + } + return (expressionToEdit as DMN15__tRelation).row?.[path.row].expression?.[path.column]; + } + if (path.type === "some") { + // root + if (path.row === undefined) { + return expressionToEdit as DMN15__tQuantified; + } + if (path.row === "variable") { + return expressionToEdit as DMN15__tQuantified; + } + if (path.row === "in") { + return (expressionToEdit as DMN15__tQuantified).in.expression; + } + return (expressionToEdit as DMN15__tQuantified).satisfies.expression; + } + }, expressionRoot); +} diff --git a/packages/dmn-editor/src/commands/CommandsContextProvider.tsx b/packages/dmn-editor/src/commands/CommandsContextProvider.tsx new file mode 100644 index 00000000000..ab664a26388 --- /dev/null +++ b/packages/dmn-editor/src/commands/CommandsContextProvider.tsx @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useContext, useRef } from "react"; + +export interface Commands { + hideFromDrd: () => void; + toggleHierarchyHighlight: () => void; + togglePropertiesPanel: () => void; + createGroup: () => void; + selectAll: () => void; + panDown: () => void; + panUp: () => void; + paste: () => void; + copy: () => void; + cut: () => void; + cancelAction: () => void; + focusOnSelection: () => void; + resetPosition: () => void; +} + +const CommandsContext = React.createContext<{ + commandsRef: React.MutableRefObject; +}>({} as any); + +export function useCommands() { + return useContext(CommandsContext); +} + +export function CommandsContextProvider(props: React.PropsWithChildren<{}>) { + const commandsRef = useRef({ + hideFromDrd: () => { + throw new Error("DMN EDITOR: hideFromDrd command not implemented."); + }, + toggleHierarchyHighlight: () => { + throw new Error("DMN EDITOR: toggleHierarchyHighlight command not implemented."); + }, + togglePropertiesPanel: () => { + throw new Error("DMN EDITOR: togglePropertiesPanel command not implemented."); + }, + createGroup: () => { + throw new Error("DMN EDITOR: createGroup command not implemented."); + }, + selectAll: () => { + throw new Error("DMN EDITOR: selectAll command not implemented."); + }, + panDown: () => { + throw new Error("DMN EDITOR: panDown command not implemented."); + }, + panUp: () => { + throw new Error("DMN EDITOR: panUp command not implemented."); + }, + paste: () => { + throw new Error("DMN EDITOR: paste command not implemented."); + }, + copy: () => { + throw new Error("DMN EDITOR: copy command not implemented."); + }, + cut: () => { + throw new Error("DMN EDITOR: cut command not implemented."); + }, + cancelAction: () => { + throw new Error("DMN EDITOR: cancelAction command not implemented."); + }, + focusOnSelection: () => { + throw new Error("DMN EDITOR: focusOnSelection command not implemented."); + }, + resetPosition: () => { + throw new Error("DMN EDITOR: resetPosition command not implemented."); + }, + }); + + return {props.children}; +} diff --git a/packages/dmn-editor/src/dataTypes/Constraints.tsx b/packages/dmn-editor/src/dataTypes/Constraints.tsx index 8f3579b6d4f..9a2b93230af 100644 --- a/packages/dmn-editor/src/dataTypes/Constraints.tsx +++ b/packages/dmn-editor/src/dataTypes/Constraints.tsx @@ -18,7 +18,7 @@ */ import * as React from "react"; -import { useMemo, useCallback } from "react"; +import { useMemo, useCallback, useState, useEffect } from "react"; import { ConstraintsExpression } from "./ConstraintsExpression"; import { DMN15__tItemDefinition, @@ -28,9 +28,9 @@ import { DmnBuiltInDataType, generateUuid } from "@kie-tools/boxed-expression-co import { ConstraintsEnum, isEnum } from "./ConstraintsEnum"; import { ConstraintsRange, isRange } from "./ConstraintsRange"; import { KIE__tConstraintType } from "@kie-tools/dmn-marshaller/dist/schemas/kie-1_0/ts-gen/types"; -import { EditItemDefinition } from "./DataTypes"; +import { DataTypeIndex, EditItemDefinition } from "./DataTypes"; import { ToggleGroup, ToggleGroupItem } from "@patternfly/react-core/dist/js/components/ToggleGroup"; -import { constrainableBuiltInFeelTypes } from "./DataTypeSpec"; +import { constrainableBuiltInFeelTypes, isCollection, isStruct } from "./DataTypeSpec"; import moment from "moment"; import { TextInput } from "@patternfly/react-core/dist/js/components/TextInput"; import { ConstraintDate } from "./ConstraintComponents/ConstraintDate"; @@ -46,6 +46,10 @@ import { } from "./ConstraintComponents/ConstraintYearsMonthsDuration"; import { invalidInlineFeelNameStyle } from "../feel/InlineFeelNameInput"; import { ConstraintProps } from "./ConstraintComponents/Constraint"; +import { useDmnEditorStore } from "../store/StoreContext"; +import { useExternalModels } from "../includedModels/DmnEditorDependenciesContext"; +import { UniqueNameIndex } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/Dmn15Spec"; +import { builtInFeelTypeNames } from "./BuiltInFeelTypes"; export type TypeHelper = { check: (value: string) => boolean; @@ -56,6 +60,7 @@ export type TypeHelper = { }; export interface ConstraintComponentProps { + id: string; isReadonly: boolean; value?: string; expressionValue?: string; @@ -63,6 +68,7 @@ export interface ConstraintComponentProps { typeHelper: TypeHelper; onSave: (value?: string) => void; isDisabled: boolean; + renderOnPropertiesPanel?: boolean; } enum ConstraintsType { @@ -72,31 +78,71 @@ enum ConstraintsType { NONE = "None", } -export const constraintTypeHelper = (typeRef: DmnBuiltInDataType): TypeHelper => { - return { +// Recurse the `itemDefinition` until find `typeRef` attribute +// that is part of the built in FEEL types. +// If the found `itemDefinition` is a collection, it will have a early stop. +export function recursivelyGetRootItemDefinition( + itemDefinition: DMN15__tItemDefinition, + allDataTypesById: DataTypeIndex, + allTopLevelItemDefinitionUniqueNames: UniqueNameIndex +): DMN15__tItemDefinition { + const typeRef: DmnBuiltInDataType = + (itemDefinition.typeRef?.__$$text as DmnBuiltInDataType) ?? DmnBuiltInDataType.Undefined; + + if (builtInFeelTypeNames.has(typeRef) === false) { + const parentDataType = allDataTypesById.get(allTopLevelItemDefinitionUniqueNames.get(typeRef) ?? ""); + if (parentDataType !== undefined && isCollection(parentDataType.itemDefinition)) { + // Parent `itemDefinition` is a collection. Early stop. + return parentDataType.itemDefinition; + } else if (parentDataType !== undefined) { + return recursivelyGetRootItemDefinition( + parentDataType.itemDefinition, + allDataTypesById, + allTopLevelItemDefinitionUniqueNames + ); + } + // Something wrong. Caller `itemDefinition` isn't a built-in FEEL type and doesn't have parent. + return itemDefinition; + } + // Caller `itemDefinition` is a built-in FEEL type + return itemDefinition; +} + +export const constraintTypeHelper = ( + itemDefinition: DMN15__tItemDefinition, + allDataTypesById?: DataTypeIndex, + allTopLevelItemDefinitionUniqueNames?: UniqueNameIndex +): TypeHelper => { + const typeRef = + (allDataTypesById !== undefined && allTopLevelItemDefinitionUniqueNames !== undefined + ? recursivelyGetRootItemDefinition(itemDefinition, allDataTypesById, allTopLevelItemDefinitionUniqueNames).typeRef + ?.__$$text + : itemDefinition.typeRef?.__$$text) ?? DmnBuiltInDataType.Undefined; + + const typeHelper = { // check if the value has the correct type - check: (value: string) => { - const recoveredValue = constraintTypeHelper(typeRef).recover(value); - switch (typeRef) { + check: (value: string, type?: DmnBuiltInDataType) => { + const recoveredValue = typeHelper.recover(value); + switch (type ?? typeRef) { case DmnBuiltInDataType.Any: return true; case DmnBuiltInDataType.String: if (recoveredValue === "") { return true; } - if (constraintTypeHelper(DmnBuiltInDataType.Date).check(value)) { + if (typeHelper.check(value, DmnBuiltInDataType.Date)) { return false; } - if (constraintTypeHelper(DmnBuiltInDataType.DateTime).check(value)) { + if (typeHelper.check(value, DmnBuiltInDataType.DateTime)) { return false; } - if (constraintTypeHelper(DmnBuiltInDataType.DateTimeDuration).check(value)) { + if (typeHelper.check(value, DmnBuiltInDataType.DateTimeDuration)) { return false; } - if (constraintTypeHelper(DmnBuiltInDataType.Time).check(value)) { + if (typeHelper.check(value, DmnBuiltInDataType.Time)) { return false; } - if (constraintTypeHelper(DmnBuiltInDataType.YearsMonthsDuration).check(value)) { + if (typeHelper.check(value, DmnBuiltInDataType.YearsMonthsDuration)) { return false; } return typeof recoveredValue === "string"; @@ -124,7 +170,7 @@ export const constraintTypeHelper = (typeRef: DmnBuiltInDataType): TypeHelper => // parse the value to the type // useful for comparisons parse: (value: string) => { - const recoveredValue = constraintTypeHelper(typeRef).recover(value); + const recoveredValue = typeHelper.recover(value); switch (typeRef) { case DmnBuiltInDataType.Number: return parseFloat(recoveredValue ?? ""); @@ -162,7 +208,7 @@ export const constraintTypeHelper = (typeRef: DmnBuiltInDataType): TypeHelper => } }, // recover the value before use it - recover: (value?: string) => { + recover: (value: string | undefined) => { if (value === undefined) { return undefined; } @@ -247,41 +293,39 @@ export const constraintTypeHelper = (typeRef: DmnBuiltInDataType): TypeHelper => } }, }; + return typeHelper; }; export function useConstraint({ constraint, itemDefinition, - isCollectionConstraintEnable, + isCollectionConstraintEnabled, + constraintTypeHelper, + enabledConstraints, }: { constraint: DMN15__tUnaryTests | undefined; itemDefinition: DMN15__tItemDefinition; - isCollectionConstraintEnable: boolean; + isCollectionConstraintEnabled: boolean; + constraintTypeHelper: TypeHelper; + enabledConstraints: KIE__tConstraintType[] | undefined; }) { - const constraintValue = useMemo(() => constraint?.text.__$$text, [constraint?.text.__$$text]); - const kieConstraintType = useMemo(() => constraint?.["@_kie:constraintType"], [constraint]); - const isCollection = useMemo(() => itemDefinition["@_isCollection"] ?? false, [itemDefinition]); - const itemDefinitionId = useMemo(() => itemDefinition["@_id"], [itemDefinition]); - - const typeRef: DmnBuiltInDataType = useMemo( - () => (itemDefinition?.typeRef?.__$$text as DmnBuiltInDataType) ?? DmnBuiltInDataType.Undefined, - [itemDefinition?.typeRef?.__$$text] - ); + const constraintValue = constraint?.text.__$$text; + const kieConstraintType = constraint?.["@_kie:constraintType"]; const isConstraintEnum = useMemo( () => - isCollection === true && isCollectionConstraintEnable === true // collection doesn't support enumeration constraint + isCollection(itemDefinition) === true && isCollectionConstraintEnabled === true // collection doesn't support enumeration constraint ? undefined - : isEnum(constraintValue, constraintTypeHelper(typeRef).check), - [constraintValue, isCollectionConstraintEnable, isCollection, typeRef] + : isEnum(constraintValue, constraintTypeHelper.check), + [constraintTypeHelper.check, constraintValue, isCollectionConstraintEnabled, itemDefinition] ); const isConstraintRange = useMemo( () => - isCollection === true && isCollectionConstraintEnable === true // collection doesn't support range constraint + isCollection(itemDefinition) === true && isCollectionConstraintEnabled === true // collection doesn't support range constraint ? undefined - : isRange(constraintValue, constraintTypeHelper(typeRef).check), - [constraintValue, isCollectionConstraintEnable, isCollection, typeRef] + : isRange(constraintValue, constraintTypeHelper.check), + [constraintTypeHelper.check, constraintValue, isCollectionConstraintEnabled, itemDefinition] ); const enumToKieConstraintType: (selection: ConstraintsType) => KIE__tConstraintType | undefined = useCallback( @@ -302,21 +346,20 @@ export function useConstraint({ ); const isConstraintEnabled = useMemo(() => { - const enabledConstraints = constrainableBuiltInFeelTypes.get(typeRef); return { enumeration: - !(isCollection === true && isCollectionConstraintEnable === true) && + !(isCollection(itemDefinition) === true && isCollectionConstraintEnabled === true) && (enabledConstraints ?? []).includes(enumToKieConstraintType(ConstraintsType.ENUMERATION)!), range: - !(isCollection === true && isCollectionConstraintEnable === true) && + !(isCollection(itemDefinition) === true && isCollectionConstraintEnabled === true) && (enabledConstraints ?? []).includes(enumToKieConstraintType(ConstraintsType.RANGE)!), expression: - (isCollection === true && isCollectionConstraintEnable === true) || + (isCollection(itemDefinition) === true && isCollectionConstraintEnabled === true) || (enabledConstraints ?? []).includes(enumToKieConstraintType(ConstraintsType.EXPRESSION)!), }; - }, [typeRef, isCollection, isCollectionConstraintEnable, enumToKieConstraintType]); + }, [enabledConstraints, enumToKieConstraintType, isCollectionConstraintEnabled, itemDefinition]); - const selectedConstraint = useMemo(() => { + const selectedKieConstraintType = useMemo(() => { if (isConstraintEnabled.enumeration && kieConstraintType === "enumeration") { return ConstraintsType.ENUMERATION; } @@ -346,136 +389,153 @@ export function useConstraint({ kieConstraintType, ]); - return useMemo(() => { - return { - constraintValue, - typeRef, - isConstraintEnum, - isConstraintRange, - isConstraintEnabled, - itemDefinitionId, - selectedConstraint, - enumToKieConstraintType, - }; - }, [ + return { constraintValue, - isConstraintEnabled, isConstraintEnum, isConstraintRange, - itemDefinitionId, - selectedConstraint, - typeRef, + isConstraintEnabled, + selectedKieConstraintType, enumToKieConstraintType, - ]); + }; } export function ConstraintsFromAllowedValuesAttribute({ isReadonly, itemDefinition, editItemDefinition, + renderOnPropertiesPanel, }: { isReadonly: boolean; itemDefinition: DMN15__tItemDefinition; editItemDefinition: EditItemDefinition; + renderOnPropertiesPanel?: boolean; isEnumDisabled?: boolean; isRangeDisabled?: boolean; }) { + const { externalModelsByNamespace } = useExternalModels(); + const allDataTypesById = useDmnEditorStore( + (s) => s.computed(s).getDataTypes(externalModelsByNamespace).allDataTypesById + ); + const allTopLevelItemDefinitionUniqueNames = useDmnEditorStore( + (s) => s.computed(s).getDataTypes(externalModelsByNamespace).allTopLevelItemDefinitionUniqueNames + ); + const allowedValues = useMemo(() => itemDefinition?.allowedValues, [itemDefinition?.allowedValues]); + const itemDefinitionId = itemDefinition["@_id"]!; + const typeRef = (itemDefinition?.typeRef?.__$$text as DmnBuiltInDataType) ?? DmnBuiltInDataType.Undefined; + const typeRefConstraintTypeHelper = useMemo( + () => constraintTypeHelper(itemDefinition, allDataTypesById, allTopLevelItemDefinitionUniqueNames), + [allDataTypesById, allTopLevelItemDefinitionUniqueNames, itemDefinition] + ); + + const rootItemDefinition = useMemo( + () => recursivelyGetRootItemDefinition(itemDefinition, allDataTypesById, allTopLevelItemDefinitionUniqueNames), + [allDataTypesById, allTopLevelItemDefinitionUniqueNames, itemDefinition] + ); + + const enabledConstraints = useMemo( + () => + isStruct(rootItemDefinition) + ? (["expression"] as KIE__tConstraintType[]) + : constrainableBuiltInFeelTypes.get( + (rootItemDefinition.typeRef?.__$$text as DmnBuiltInDataType) ?? DmnBuiltInDataType.Undefined + ), + [rootItemDefinition] + ); + + // Collection constraint on the `allowedValues` must be enabled on cases where `rootItemDefinition` is a collection + const isCollectionConstraintEnable = useMemo(() => { + if (itemDefinitionId !== rootItemDefinition["@_id"]) { + return rootItemDefinition["@_isCollection"] ?? false; + } + return false; + }, [itemDefinitionId, rootItemDefinition]); const { constraintValue, - typeRef, isConstraintEnum, isConstraintRange, isConstraintEnabled, - itemDefinitionId, - selectedConstraint, + selectedKieConstraintType, enumToKieConstraintType, } = useConstraint({ constraint: allowedValues, itemDefinition, - isCollectionConstraintEnable: false, // allowedValues doesn't support constraint to the collection itself + isCollectionConstraintEnabled: isCollectionConstraintEnable, + constraintTypeHelper: typeRefConstraintTypeHelper, + enabledConstraints, }); const onConstraintChange = useCallback( - (value?: string) => { - editItemDefinition(itemDefinitionId!, (itemDefinition) => { - itemDefinition.allowedValues ??= { text: { __$$text: "" } }; - itemDefinition.allowedValues.text.__$$text = value ?? ""; - itemDefinition.allowedValues["@_id"] = itemDefinition.allowedValues?.["@_id"] ?? generateUuid(); - return; + (value: string | undefined, selectedConstraint: ConstraintsType) => { + editItemDefinition(itemDefinitionId, (itemDefinition) => { + if (value === "" || value === undefined) { + itemDefinition.allowedValues = undefined; + } else { + itemDefinition.allowedValues ??= { text: { __$$text: "" } }; + itemDefinition.allowedValues.text.__$$text = value; + itemDefinition.allowedValues["@_id"] = itemDefinition.allowedValues?.["@_id"] ?? generateUuid(); + itemDefinition.allowedValues["@_kie:constraintType"] = enumToKieConstraintType(selectedConstraint); + } }); }, - [editItemDefinition, itemDefinitionId] + [editItemDefinition, enumToKieConstraintType, itemDefinitionId] ); const onToggleGroupChange = useCallback( - (newSelection: boolean, event: React.KeyboardEvent | MouseEvent | React.MouseEvent) => { + (newSelection: boolean, selectedConstraint: ConstraintsType) => { if (!newSelection) { return; } - const selection = event.currentTarget.id as ConstraintsType; - if (selection === ConstraintsType.NONE) { - editItemDefinition(itemDefinitionId!, (itemDefinition) => { + + editItemDefinition(itemDefinitionId, (itemDefinition) => { + if (selectedConstraint === ConstraintsType.NONE) { itemDefinition.allowedValues = undefined; - }); - return; - } + return; + } - editItemDefinition(itemDefinitionId!, (itemDefinition) => { - itemDefinition.allowedValues ??= { text: { __$$text: "" } }; - const previousKieContraintType = itemDefinition.allowedValues["@_kie:constraintType"]; - itemDefinition.allowedValues["@_kie:constraintType"] = enumToKieConstraintType(selection); + if (itemDefinition.allowedValues) { + itemDefinition.allowedValues["@_kie:constraintType"] = enumToKieConstraintType(selectedConstraint); + } - if (selection === ConstraintsType.EXPRESSION) { + if (selectedConstraint === ConstraintsType.EXPRESSION) { return; } if ( - previousKieContraintType === "expression" && - selection === ConstraintsType.ENUMERATION && - isEnum( - itemDefinition.allowedValues.text.__$$text, - constraintTypeHelper( - (itemDefinition?.typeRef?.__$$text as DmnBuiltInDataType) ?? DmnBuiltInDataType.Undefined - ).check - ) + selectedConstraint === ConstraintsType.ENUMERATION && + isEnum(itemDefinition.allowedValues?.text.__$$text, typeRefConstraintTypeHelper.check) ) { return; } if ( - previousKieContraintType === "expression" && - selection === ConstraintsType.RANGE && - isRange( - itemDefinition.allowedValues.text.__$$text, - constraintTypeHelper( - (itemDefinition?.typeRef?.__$$text as DmnBuiltInDataType) ?? DmnBuiltInDataType.Undefined - ).check - ) + selectedConstraint === ConstraintsType.RANGE && + isRange(itemDefinition.allowedValues?.text.__$$text, typeRefConstraintTypeHelper.check) ) { return; } - itemDefinition.allowedValues.text.__$$text = ""; - return; + itemDefinition.allowedValues = undefined; }); }, - [editItemDefinition, enumToKieConstraintType, itemDefinitionId] + [editItemDefinition, itemDefinitionId, enumToKieConstraintType, typeRefConstraintTypeHelper.check] ); return ( ); } @@ -484,13 +544,23 @@ export function ConstraintsFromTypeConstraintAttribute({ isReadonly, itemDefinition, editItemDefinition, + renderOnPropertiesPanel, defaultsToAllowedValues, }: { isReadonly: boolean; itemDefinition: DMN15__tItemDefinition; editItemDefinition: EditItemDefinition; + renderOnPropertiesPanel?: boolean; defaultsToAllowedValues: boolean; }) { + const { externalModelsByNamespace } = useExternalModels(); + const allDataTypesById = useDmnEditorStore( + (s) => s.computed(s).getDataTypes(externalModelsByNamespace).allDataTypesById + ); + const allTopLevelItemDefinitionUniqueNames = useDmnEditorStore( + (s) => s.computed(s).getDataTypes(externalModelsByNamespace).allTopLevelItemDefinitionUniqueNames + ); + const itemDefinitionId = itemDefinition["@_id"]!; const typeConstraint = useMemo( () => defaultsToAllowedValues @@ -499,117 +569,136 @@ export function ConstraintsFromTypeConstraintAttribute({ [defaultsToAllowedValues, itemDefinition?.allowedValues, itemDefinition?.typeConstraint] ); + const typeRef = (itemDefinition?.typeRef?.__$$text as DmnBuiltInDataType) ?? DmnBuiltInDataType.Undefined; + const typeRefConstraintTypeHelper = useMemo( + () => constraintTypeHelper(itemDefinition, allDataTypesById, allTopLevelItemDefinitionUniqueNames), + [allDataTypesById, allTopLevelItemDefinitionUniqueNames, itemDefinition] + ); + + const rootItemDefinition = useMemo( + () => recursivelyGetRootItemDefinition(itemDefinition, allDataTypesById, allTopLevelItemDefinitionUniqueNames), + [allDataTypesById, allTopLevelItemDefinitionUniqueNames, itemDefinition] + ); + + const enabledConstraints = useMemo(() => { + if (isStruct(rootItemDefinition)) { + return ["expression"] as KIE__tConstraintType[]; + } + if (isCollection(rootItemDefinition)) { + return ["expression"] as KIE__tConstraintType[]; + } + return constrainableBuiltInFeelTypes.get( + (rootItemDefinition.typeRef?.__$$text as DmnBuiltInDataType) ?? DmnBuiltInDataType.Undefined + ); + }, [rootItemDefinition]); + const { constraintValue, - typeRef, isConstraintEnum, isConstraintRange, isConstraintEnabled, - itemDefinitionId, - selectedConstraint, + selectedKieConstraintType, enumToKieConstraintType, } = useConstraint({ constraint: typeConstraint, - itemDefinition, - isCollectionConstraintEnable: true, // typeConstraint enables to add a constraint to the collection itself + itemDefinition: itemDefinition, + isCollectionConstraintEnabled: true, // typeConstraint enables to add a constraint to the collection itself + constraintTypeHelper: typeRefConstraintTypeHelper, + enabledConstraints, }); const onConstraintChange = useCallback( - (value?: string) => { - editItemDefinition(itemDefinitionId!, (itemDefinition) => { - itemDefinition.typeConstraint ??= { text: { __$$text: "" } }; - itemDefinition.typeConstraint.text.__$$text = value ?? ""; - itemDefinition.typeConstraint["@_id"] = itemDefinition.typeConstraint?.["@_id"] ?? generateUuid(); + (value: string | undefined, selectedConstraint: ConstraintsType) => { + editItemDefinition(itemDefinitionId, (itemDefinition) => { + if (value === "" || value === undefined) { + itemDefinition.typeConstraint = undefined; + } else { + itemDefinition.typeConstraint ??= { text: { __$$text: "" } }; + itemDefinition.typeConstraint.text.__$$text = value; + itemDefinition.typeConstraint["@_id"] = itemDefinition.typeConstraint?.["@_id"] ?? generateUuid(); + itemDefinition.typeConstraint["@_kie:constraintType"] = enumToKieConstraintType(selectedConstraint); + } }); }, - [editItemDefinition, itemDefinitionId] + [editItemDefinition, enumToKieConstraintType, itemDefinitionId] ); const onToggleGroupChange = useCallback( - (newSelection: boolean, event: React.KeyboardEvent | MouseEvent | React.MouseEvent) => { + (newSelection: boolean, selectedConstraint: ConstraintsType) => { if (!newSelection) { return; } - const selection = event.currentTarget.id as ConstraintsType; - if (selection === ConstraintsType.NONE) { - editItemDefinition(itemDefinitionId!, (itemDefinition) => { + + editItemDefinition(itemDefinitionId, (itemDefinition) => { + if (selectedConstraint === ConstraintsType.NONE) { itemDefinition.typeConstraint = undefined; - }); - return; - } + return; + } - editItemDefinition(itemDefinitionId!, (itemDefinition) => { - itemDefinition.typeConstraint ??= { text: { __$$text: "" } }; - const previousKieContraintType = itemDefinition.typeConstraint["@_kie:constraintType"]; - itemDefinition.typeConstraint["@_kie:constraintType"] = enumToKieConstraintType(selection); + if (itemDefinition.typeConstraint) { + itemDefinition.typeConstraint["@_kie:constraintType"] = enumToKieConstraintType(selectedConstraint); + } - if (selection === ConstraintsType.EXPRESSION) { + if (selectedConstraint === ConstraintsType.EXPRESSION) { return; } if ( - previousKieContraintType === "expression" && - selection === ConstraintsType.ENUMERATION && - isEnum( - itemDefinition.typeConstraint.text.__$$text, - constraintTypeHelper( - (itemDefinition?.typeRef?.__$$text as DmnBuiltInDataType) ?? DmnBuiltInDataType.Undefined - ).check - ) + selectedConstraint === ConstraintsType.ENUMERATION && + isEnum(itemDefinition.typeConstraint?.text.__$$text, typeRefConstraintTypeHelper.check) ) { return; } if ( - previousKieContraintType === "expression" && - selection === ConstraintsType.RANGE && - isRange( - itemDefinition.typeConstraint.text.__$$text, - constraintTypeHelper( - (itemDefinition?.typeRef?.__$$text as DmnBuiltInDataType) ?? DmnBuiltInDataType.Undefined - ).check - ) + selectedConstraint === ConstraintsType.RANGE && + isRange(itemDefinition.typeConstraint?.text.__$$text, typeRefConstraintTypeHelper.check) ) { return; } - itemDefinition.typeConstraint.text.__$$text = ""; + itemDefinition.typeConstraint = undefined; }); }, - [editItemDefinition, enumToKieConstraintType, itemDefinitionId] + [editItemDefinition, itemDefinitionId, enumToKieConstraintType, typeRefConstraintTypeHelper.check] ); return ( ); } export function Constraints({ isReadonly, - itemDefinition, + itemDefinitionId, constraintValue, + typeHelper, typeRef, isConstraintEnum, isConstraintRange, isConstraintEnabled, - selectedConstraint, + selectedKieConstraintType, onToggleGroupChange, onConstraintChange, + renderOnPropertiesPanel, }: { isReadonly: boolean; - itemDefinition: DMN15__tItemDefinition; + itemDefinitionId: string; constraintValue: string | undefined; + typeHelper: TypeHelper; typeRef: DmnBuiltInDataType; isConstraintEnum: string[] | undefined; isConstraintRange: [string, string] | undefined; @@ -618,13 +707,37 @@ export function Constraints({ range: boolean; expression: boolean; }; - selectedConstraint: ConstraintsType; - onToggleGroupChange: ( - selected: boolean, - event: React.KeyboardEvent | MouseEvent | React.MouseEvent - ) => void; - onConstraintChange: (value?: string) => void; + selectedKieConstraintType: ConstraintsType; + renderOnPropertiesPanel?: boolean; + onToggleGroupChange: (selected: boolean, selectedConstraint: ConstraintsType) => void; + onConstraintChange: (value: string | undefined, selectedConstraint: ConstraintsType) => void; }) { + const [internalSelectedConstraint, setInternalSelectedConstraint] = + useState(selectedKieConstraintType); + + // Updates the `selectedConstraint` only after changing the active item definition + // Both `internalSelectedConstraint` and `selectedKieConstraintType` should not be coupled together + useEffect(() => { + setInternalSelectedConstraint(selectedKieConstraintType); + // eslint-disable-next-line + }, [itemDefinitionId]); + + const onToggleGroupChangeInternal = useCallback( + (selected: boolean, event: React.KeyboardEvent | MouseEvent | React.MouseEvent) => { + const selectedConstraint = event.currentTarget.id as ConstraintsType; + setInternalSelectedConstraint(selectedConstraint); + onToggleGroupChange(selected, selectedConstraint); + }, + [onToggleGroupChange] + ); + + const onConstraintChangeInternal = useCallback( + (value: string | undefined) => { + onConstraintChange(value, internalSelectedConstraint); + }, + [onConstraintChange, internalSelectedConstraint] + ); + return ( <> {isConstraintEnabled.expression === false && @@ -647,79 +760,105 @@ export function Constraints({
- {selectedConstraint === ConstraintsType.ENUMERATION && ( + {(selectedKieConstraintType === ConstraintsType.ENUMERATION || + internalSelectedConstraint === ConstraintsType.ENUMERATION) && ( )} - {selectedConstraint === ConstraintsType.RANGE && ( + {(selectedKieConstraintType === ConstraintsType.RANGE || + internalSelectedConstraint === ConstraintsType.RANGE) && ( )} - {selectedConstraint === ConstraintsType.EXPRESSION && ( + {(selectedKieConstraintType === ConstraintsType.EXPRESSION || + internalSelectedConstraint === ConstraintsType.EXPRESSION) && ( )} - {selectedConstraint === ConstraintsType.NONE && ( -

- {`All values are allowed`} -

- )} + {selectedKieConstraintType === ConstraintsType.NONE && + internalSelectedConstraint === ConstraintsType.NONE && ( +

+ {`All values are allowed`} +

+ )}
)} diff --git a/packages/dmn-editor/src/dataTypes/ConstraintsEnum.tsx b/packages/dmn-editor/src/dataTypes/ConstraintsEnum.tsx index da5d47baf35..d92758c9aa6 100644 --- a/packages/dmn-editor/src/dataTypes/ConstraintsEnum.tsx +++ b/packages/dmn-editor/src/dataTypes/ConstraintsEnum.tsx @@ -31,6 +31,7 @@ import { ConstraintComponentProps, TypeHelper } from "./Constraints"; export const ENUM_SEPARATOR = ","; export function ConstraintsEnum({ + id, isReadonly, value, expressionValue, @@ -38,6 +39,7 @@ export function ConstraintsEnum({ typeHelper, onSave, isDisabled, + renderOnPropertiesPanel, }: ConstraintComponentProps) { const enumValues = useMemo(() => isEnum(value, typeHelper.check) ?? [""], [typeHelper.check, value]); const [valuesUuid, setValuesUuid] = useState((enumValues ?? [""])?.map((_) => generateUuid())); @@ -112,6 +114,7 @@ export function ConstraintsEnum({ index={index} style={{ alignItems: "center" }} handlerStyle={{ margin: "0px 10px" }} + isDisabled={isReadonly || isDisabled} >
  • - -
    -
    - + {!(isDisabled || isReadonly) && ( + <> + + + )} + {!renderOnPropertiesPanel && ( + <> +
    +
    + + + )} ); } diff --git a/packages/dmn-editor/src/dataTypes/ConstraintsExpression.tsx b/packages/dmn-editor/src/dataTypes/ConstraintsExpression.tsx index ecd7e13727b..75d53af21b9 100644 --- a/packages/dmn-editor/src/dataTypes/ConstraintsExpression.tsx +++ b/packages/dmn-editor/src/dataTypes/ConstraintsExpression.tsx @@ -18,7 +18,7 @@ */ import * as React from "react"; -import { useMemo, useState, useCallback } from "react"; +import { useMemo, useState, useCallback, useRef, useEffect } from "react"; import { Title } from "@patternfly/react-core/dist/js/components/Title"; import { FeelInput } from "@kie-tools/feel-input-component/dist"; import "./ConstraintsExpression.css"; @@ -28,10 +28,12 @@ import { DmnBuiltInDataType } from "@kie-tools/boxed-expression-component/dist/a import { TypeHelper } from "./Constraints"; export function ConstraintsExpression({ + id, isReadonly, value, onSave, }: { + id: string; isReadonly: boolean; value?: string; savedValue?: string; @@ -41,15 +43,43 @@ export function ConstraintsExpression({ isDisabled?: boolean; }) { const [preview, setPreview] = useState(value ?? ""); - const [editingValue, setEditingValue] = useState(value); + const [isEditing, setEditing] = useState(false); + const valueCopy = useRef(value); + + const onFeelBlur = useCallback((valueOnBlur: string) => { + setEditing(false); + }, []); + const onFeelChange = useCallback( (_, content, preview) => { - onSave?.(content.trim()); setPreview(preview); + onSave?.(content.trim()); }, [onSave] ); + const onPreviewChanged = useCallback((newPreview: string) => setPreview(newPreview), []); + + useEffect(() => { + valueCopy.current = isEditing ? valueCopy.current : value; + }, [isEditing, value]); + + const onKeyDown = useCallback( + (e) => { + // When inside FEEL Input, all keyboard events should be kept inside it. + // Exceptions to this strategy are handled on `onFeelKeyDown`. + if (!isReadonly && isEditing) { + e.stopPropagation(); + } + + // This is used to start editing a cell without being in edit mode. + if (!isReadonly && !isEditing) { + setEditing(true); + } + }, + [isEditing, isReadonly] + ); + const monacoOptions = useMemo( () => ({ fixedOverflowWidgets: true, @@ -64,7 +94,9 @@ export function ConstraintsExpression({ ); return ( -
    + // FeelInput doens't react to `onFeelChange` updates + // making it necessary to add a key to force a re-render; +
    {isReadonly && ( Equivalent FEEL expression: @@ -85,9 +117,10 @@ export function ConstraintsExpression({ <p style={{ fontStyle: "italic" }}>{`<None>`}</p> ))} <FeelInput - value={isReadonly ? value : editingValue} + value={isEditing ? valueCopy.current : value} onChange={onFeelChange} - onPreviewChanged={setPreview} + onBlur={onFeelBlur} + onPreviewChanged={onPreviewChanged} enabled={!isReadonly} options={monacoOptions as any} /> diff --git a/packages/dmn-editor/src/dataTypes/ConstraintsRange.tsx b/packages/dmn-editor/src/dataTypes/ConstraintsRange.tsx index a72c121319b..b18aca1498e 100644 --- a/packages/dmn-editor/src/dataTypes/ConstraintsRange.tsx +++ b/packages/dmn-editor/src/dataTypes/ConstraintsRange.tsx @@ -31,6 +31,7 @@ const CONSTRAINT_START_ID = "start"; const CONSTRAINT_END_ID = "end"; export function ConstraintsRange({ + id, isReadonly, value, expressionValue, @@ -38,6 +39,7 @@ export function ConstraintsRange({ typeHelper, onSave, isDisabled, + renderOnPropertiesPanel, }: ConstraintComponentProps) { const start = useMemo( () => typeHelper.recover(isRange(value ?? "", typeHelper.check)?.[0]) ?? "", @@ -308,8 +310,12 @@ export function ConstraintsRange({ </HelperText> </div> </div> - <br /> - <ConstraintsExpression isReadonly={true} value={expressionValue ?? ""} type={type} /> + {!renderOnPropertiesPanel && ( + <> + <br /> + <ConstraintsExpression id={id} isReadonly={true} value={expressionValue ?? ""} type={type} /> + </> + )} </div> ); } diff --git a/packages/dmn-editor/src/dataTypes/DataTypePanel.tsx b/packages/dmn-editor/src/dataTypes/DataTypePanel.tsx index 9279932c753..080955d5791 100644 --- a/packages/dmn-editor/src/dataTypes/DataTypePanel.tsx +++ b/packages/dmn-editor/src/dataTypes/DataTypePanel.tsx @@ -357,6 +357,7 @@ export function DataTypePanel({ isDisabled={isReadonly} typeRef={resolvedTypeRef} onChange={changeTypeRef} + removeDataTypes={[dataType]} /> <br /> <br /> diff --git a/packages/dmn-editor/src/dataTypes/DataTypes.tsx b/packages/dmn-editor/src/dataTypes/DataTypes.tsx index 3daf48bb213..7d950a6ee67 100644 --- a/packages/dmn-editor/src/dataTypes/DataTypes.tsx +++ b/packages/dmn-editor/src/dataTypes/DataTypes.tsx @@ -87,7 +87,7 @@ export type EditItemDefinition = ( export function DataTypes() { const thisDmnsNamespace = useDmnEditorStore((s) => s.dmn.model.definitions["@_namespace"]); const dmnEditorStoreApi = useDmnEditorStoreApi(); - const { activeItemDefinitionId } = useDmnEditorStore((s) => s.dataTypesEditor); + const activeItemDefinitionId = useDmnEditorStore((s) => s.dataTypesEditor.activeItemDefinitionId); const [filter, setFilter] = useState(""); const { externalModelsByNamespace } = useExternalModels(); diff --git a/packages/dmn-editor/src/dataTypes/ItemComponentsTable.tsx b/packages/dmn-editor/src/dataTypes/ItemComponentsTable.tsx index 7778708f412..7769fd8c709 100644 --- a/packages/dmn-editor/src/dataTypes/ItemComponentsTable.tsx +++ b/packages/dmn-editor/src/dataTypes/ItemComponentsTable.tsx @@ -54,7 +54,7 @@ import { import { getNewDmnIdRandomizer } from "../idRandomizer/dmnIdRandomizer"; import { isEnum } from "./ConstraintsEnum"; import { isRange } from "./ConstraintsRange"; -import { constraintTypeHelper } from "./Constraints"; +import { constraintTypeHelper, recursivelyGetRootItemDefinition } from "./Constraints"; import { builtInFeelTypeNames } from "./BuiltInFeelTypes"; import { useDmnEditor } from "../DmnEditorContext"; import { DMN15__tItemDefinition } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; @@ -95,6 +95,9 @@ export function ItemComponentsTable({ const allTopLevelDataTypesByFeelName = useDmnEditorStore( (s) => s.computed(s).getDataTypes(externalModelsByNamespace).allTopLevelDataTypesByFeelName ); + const allTopLevelItemDefinitionUniqueNames = useDmnEditorStore( + (s) => s.computed(s).getDataTypes(externalModelsByNamespace).allTopLevelItemDefinitionUniqueNames + ); const importsByNamespace = useDmnEditorStore((s) => s.computed(s).importsByNamespace()); const thisDmnsNamespace = useDmnEditorStore((s) => s.dmn.model.definitions["@_namespace"]); @@ -288,21 +291,37 @@ export function ItemComponentsTable({ return <>Range</>; } - const constraintValue = dt.itemDefinition.allowedValues?.text.__$$text; - const typeRef = - (dt.itemDefinition.typeRef?.__$$text as DmnBuiltInDataType) ?? DmnBuiltInDataType.Undefined; + const constraintValue = + dt.itemDefinition.typeConstraint?.text.__$$text ?? dt.itemDefinition.allowedValues?.text.__$$text; + + const typeHelper = constraintTypeHelper( + dt.itemDefinition, + allDataTypesById, + allTopLevelItemDefinitionUniqueNames + ); + if (constraintValue === undefined) { return <>None</>; } - if (isEnum(constraintValue, constraintTypeHelper(typeRef).check)) { + if (isEnum(constraintValue, typeHelper.check)) { return <>Enumeration</>; } - if (isRange(constraintValue, constraintTypeHelper(typeRef).check)) { + if (isRange(constraintValue, typeHelper.check)) { return <>Range</>; } return <>Expression</>; }; + const rootItemDefinition = recursivelyGetRootItemDefinition( + dt.itemDefinition, + allDataTypesById, + allTopLevelItemDefinitionUniqueNames + ); + + const isItemComponent = !!parent.itemDefinition?.itemComponent?.find( + (ic) => ic["@_id"] === rootItemDefinition["@_id"] + ); + return ( <React.Fragment key={dt.itemDefinition["@_id"]}> {shouldShowRow && ( @@ -439,7 +458,8 @@ export function ItemComponentsTable({ /> </td> <td> - {canHaveConstraints(dt.itemDefinition) ? ( + {canHaveConstraints(rootItemDefinition) || + (isStruct(rootItemDefinition) && !isItemComponent) ? ( <Button variant={ButtonVariant.link} onClick={() => { diff --git a/packages/dmn-editor/src/dataTypes/TypeRefSelector.tsx b/packages/dmn-editor/src/dataTypes/TypeRefSelector.tsx index 4e01851dd71..42456e8b817 100644 --- a/packages/dmn-editor/src/dataTypes/TypeRefSelector.tsx +++ b/packages/dmn-editor/src/dataTypes/TypeRefSelector.tsx @@ -26,7 +26,6 @@ import { ArrowUpIcon } from "@patternfly/react-icons/dist/js/icons/arrow-up-icon import { DmnEditorTab } from "../store/Store"; import { useDmnEditorStore, useDmnEditorStoreApi } from "../store/StoreContext"; import { Button, ButtonVariant } from "@patternfly/react-core/dist/js/components/Button"; -import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip"; import { DataType } from "./DataTypes"; import { builtInFeelTypeNames, builtInFeelTypes } from "./BuiltInFeelTypes"; import { Flex } from "@patternfly/react-core/dist/js/layouts/Flex"; @@ -48,6 +47,7 @@ export function TypeRefSelector({ menuAppendTo, onCreate, onToggle, + removeDataTypes, }: { zoom?: number; heightRef: React.RefObject<HTMLElement>; @@ -57,6 +57,7 @@ export function TypeRefSelector({ onCreate?: OnCreateDataType; onToggle?: OnToggle; menuAppendTo?: "parent"; + removeDataTypes?: DataType[]; }) { const [isOpen, setOpen] = useState(false); const { externalModelsByNamespace } = useExternalModels(); @@ -87,7 +88,9 @@ export function TypeRefSelector({ } if (s.namespace === state.dmn.model.definitions["@_namespace"]) { - customDataTypes.push(s); + if ((removeDataTypes ?? []).findIndex((removeDataType) => removeDataType.feelName === s.feelName) < 0) { + customDataTypes.push(s); + } } else { externalDataTypes.push(s); } @@ -113,21 +116,19 @@ export function TypeRefSelector({ spaceItems={{ default: "spaceItemsNone" }} > {selectedDataType?.itemDefinition && ( - <Tooltip content="Jump to definition" appendTo={() => document.getElementById(id)!}> - <Button - title={"Jump to definition"} - className={"kie-dmn-editor--data-type-jump-to-definition"} - variant={ButtonVariant.control} - onClick={(e) => - dmnEditorStoreApi.setState((state) => { - state.navigation.tab = DmnEditorTab.DATA_TYPES; - state.dataTypesEditor.activeItemDefinitionId = selectedDataType?.itemDefinition?.["@_id"]; - }) - } - > - <ArrowUpIcon /> - </Button> - </Tooltip> + <Button + title={"Jump to definition"} + className={"kie-dmn-editor--data-type-jump-to-definition"} + variant={ButtonVariant.control} + onClick={(e) => + dmnEditorStoreApi.setState((state) => { + state.navigation.tab = DmnEditorTab.DATA_TYPES; + state.dataTypesEditor.activeItemDefinitionId = selectedDataType?.itemDefinition?.["@_id"]; + }) + } + > + <ArrowUpIcon /> + </Button> )} <Select toggleRef={toggleRef} diff --git a/packages/dmn-editor/src/diagram/Diagram.tsx b/packages/dmn-editor/src/diagram/Diagram.tsx index bc3393e9ba7..57f591c6f9e 100644 --- a/packages/dmn-editor/src/diagram/Diagram.tsx +++ b/packages/dmn-editor/src/diagram/Diagram.tsx @@ -49,28 +49,19 @@ import { useDmnEditor } from "../DmnEditorContext"; import { AutolayoutButton } from "../autolayout/AutolayoutButton"; import { getDefaultColumnWidth } from "../boxedExpressions/getDefaultColumnWidth"; import { getDefaultBoxedExpression } from "../boxedExpressions/getDefaultBoxedExpression"; -import { - DMN_EDITOR_DIAGRAM_CLIPBOARD_MIME_TYPE, - DmnEditorDiagramClipboard, - buildClipboardFromDiagram, - getClipboard, -} from "../clipboard/Clipboard"; import { ExternalNode, MIME_TYPE_FOR_DMN_EDITOR_EXTERNAL_NODES_FROM_INCLUDED_MODELS, } from "../externalNodes/ExternalNodesPanel"; -import { getNewDmnIdRandomizer } from "../idRandomizer/dmnIdRandomizer"; import { NodeNature, nodeNatures } from "../mutations/NodeNature"; import { addConnectedNode } from "../mutations/addConnectedNode"; import { addDecisionToDecisionService } from "../mutations/addDecisionToDecisionService"; import { addEdge } from "../mutations/addEdge"; -import { addOrGetDrd } from "../mutations/addOrGetDrd"; import { addShape } from "../mutations/addShape"; import { addStandaloneNode } from "../mutations/addStandaloneNode"; import { deleteDecisionFromDecisionService } from "../mutations/deleteDecisionFromDecisionService"; import { EdgeDeletionMode, deleteEdge } from "../mutations/deleteEdge"; import { NodeDeletionMode, canRemoveNodeFromDrdOnly, deleteNode } from "../mutations/deleteNode"; -import { repopulateInputDataAndDecisionsOnAllDecisionServices } from "../mutations/repopulateInputDataAndDecisionsOnDecisionService"; import { repositionNode } from "../mutations/repositionNode"; import { resizeNode } from "../mutations/resizeNode"; import { updateExpression } from "../mutations/updateExpression"; @@ -99,12 +90,12 @@ import { } from "./edges/Edges"; import { buildHierarchy } from "./graph/graph"; import { - CONTAINER_NODES_DESIRABLE_PADDING, - getBounds, getDmnBoundsCenterPoint, getContainmentRelationship, getHandlePosition, getNodeTypeFromDmnObject, + getBounds, + CONTAINER_NODES_DESIRABLE_PADDING, } from "./maths/DmnMaths"; import { DEFAULT_NODE_SIZES, MIN_NODE_SIZES } from "./nodes/DefaultSizes"; import { NODE_TYPES } from "./nodes/NodeTypes"; @@ -126,6 +117,7 @@ import { getDecisionServicePropertiesRelativeToThisDmn, } from "../mutations/addExistingDecisionServiceToDrd"; import { updateExpressionWidths } from "../mutations/updateExpressionWidths"; +import { DiagramCommands } from "./DiagramCommands"; const isFirefox = typeof (window as any).InstallTrigger !== "undefined"; // See https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browsers @@ -133,7 +125,7 @@ const PAN_ON_DRAG = [1, 2]; const FIT_VIEW_OPTIONS: RF.FitViewOptions = { maxZoom: 1, minZoom: 0.1, duration: 400 }; -const DEFAULT_VIEWPORT = { x: 100, y: 100, zoom: 1 }; +export const DEFAULT_VIEWPORT = { x: 100, y: 100, zoom: 1 }; const DELETE_NODE_KEY_CODES = ["Backspace", "Delete"]; @@ -167,7 +159,6 @@ export const Diagram = React.forwardRef<DiagramRef, { container: React.RefObject const { externalModelsByNamespace } = useExternalModels(); const snapGrid = useDmnEditorStore((s) => s.diagram.snapGrid); const thisDmn = useDmnEditorStore((s) => s.dmn); - const { dmnModelBeforeEditingRef } = useDmnEditor(); // State @@ -177,7 +168,6 @@ export const Diagram = React.forwardRef<DiagramRef, { container: React.RefObject >(undefined); // Refs - React.useImperativeHandle( ref, () => ({ @@ -1181,8 +1171,7 @@ export const Diagram = React.forwardRef<DiagramRef, { container: React.RefObject <SelectionStatus /> <Palette pulse={isEmptyStateShowing} /> <TopRightCornerPanels /> - <PanWhenAltPressed /> - <KeyboardShortcuts /> + <DiagramCommands /> {!isFirefox && <RF.Background />} <RF.Controls fitViewOptions={FIT_VIEW_OPTIONS} position={"bottom-right"} /> <SetConnectionToReactFlowStore /> @@ -1487,393 +1476,3 @@ export function SelectionStatus() { </> ); } - -export function KeyboardShortcuts(props: {}) { - const rfStoreApi = RF.useStoreApi(); - const dmnEditorStoreApi = useDmnEditorStoreApi(); - const { externalModelsByNamespace } = useExternalModels(); - - const rf = RF.useReactFlow<DmnDiagramNodeData, DmnDiagramEdgeData>(); - - // Reset position to origin - const space = RF.useKeyPress(["Space"]); - useEffect(() => { - if (!space) { - return; - } - - rf.setViewport(DEFAULT_VIEWPORT, { duration: 200 }); - }, [rf, space]); - - // Focus on node bounds - const b = RF.useKeyPress(["b"]); - useEffect(() => { - if (!b) { - return; - } - - const selectedNodes = rf.getNodes().filter((s) => s.selected); - if (selectedNodes.length <= 0) { - return; - } - - const bounds = getBounds({ - nodes: selectedNodes, - padding: 100, - }); - - rf.fitBounds( - { - x: bounds["@_x"], - y: bounds["@_y"], - width: bounds["@_width"], - height: bounds["@_height"], - }, - { duration: 200 } - ); - }, [b, rf]); - - // Cancel action - const esc = RF.useKeyPress(["Escape"]); - useEffect(() => { - if (!esc) { - return; - } - - rfStoreApi.setState((rfState) => { - if (rfState.connectionNodeId) { - console.debug("DMN DIAGRAM: Esc pressed. Cancelling connection."); - rfState.cancelConnection(); - dmnEditorStoreApi.setState((state) => { - state.diagram.ongoingConnection = undefined; - }); - } else { - (document.activeElement as any)?.blur?.(); - } - - return rfState; - }); - }, [esc, dmnEditorStoreApi, rfStoreApi]); - - // Cut - const cut = RF.useKeyPress(["Meta+x"]); - useEffect(() => { - if (!cut) { - return; - } - console.debug("DMN DIAGRAM: Cutting selected nodes..."); - - const { clipboard, copiedEdgesById, danglingEdgesById, copiedNodesById } = buildClipboardFromDiagram( - rfStoreApi.getState(), - dmnEditorStoreApi.getState() - ); - - navigator.clipboard.writeText(JSON.stringify(clipboard)).then(() => { - dmnEditorStoreApi.setState((state) => { - // Delete edges - [...copiedEdgesById.values(), ...danglingEdgesById.values()].forEach((edge) => { - deleteEdge({ - definitions: state.dmn.model.definitions, - drdIndex: state.diagram.drdIndex, - edge: { id: edge.id, dmnObject: edge.data!.dmnObject }, - mode: EdgeDeletionMode.FROM_DRG_AND_ALL_DRDS, - }); - state.dispatch(state).diagram.setEdgeStatus(edge.id, { - selected: false, - draggingWaypoint: false, - }); - }); - - // Delete nodes - rfStoreApi - .getState() - .getNodes() - .forEach((node: RF.Node<DmnDiagramNodeData>) => { - if (copiedNodesById.has(node.id)) { - deleteNode({ - drgEdges: state.computed(state).getDiagramData(externalModelsByNamespace).drgEdges, - definitions: state.dmn.model.definitions, - drdIndex: state.diagram.drdIndex, - dmnObjectNamespace: node.data.dmnObjectNamespace ?? state.dmn.model.definitions["@_namespace"], - dmnObjectQName: node.data.dmnObjectQName, - dmnObjectId: node.data.dmnObject?.["@_id"], - nodeNature: nodeNatures[node.type as NodeType], - mode: NodeDeletionMode.FROM_DRG_AND_ALL_DRDS, - externalDmnsIndex: state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace) - .dmns, - }); - state.dispatch(state).diagram.setNodeStatus(node.id, { - selected: false, - dragging: false, - resizing: false, - }); - } - }); - }); - }); - }, [cut, dmnEditorStoreApi, rfStoreApi, externalModelsByNamespace]); - - // Copy - const copy = RF.useKeyPress(["Meta+c"]); - useEffect(() => { - if (!copy) { - return; - } - - console.debug("DMN DIAGRAM: Copying selected nodes..."); - - const { clipboard } = buildClipboardFromDiagram(rfStoreApi.getState(), dmnEditorStoreApi.getState()); - navigator.clipboard.writeText(JSON.stringify(clipboard)); - }, [copy, dmnEditorStoreApi, rfStoreApi]); - - // Paste - const paste = RF.useKeyPress(["Meta+v"]); - useEffect(() => { - if (!paste) { - return; - } - - console.debug("DMN DIAGRAM: Pasting nodes..."); - - navigator.clipboard.readText().then((text) => { - const clipboard = getClipboard<DmnEditorDiagramClipboard>(text, DMN_EDITOR_DIAGRAM_CLIPBOARD_MIME_TYPE); - if (!clipboard) { - return; - } - - getNewDmnIdRandomizer() - .ack({ - json: clipboard.drgElements, - type: "DMN15__tDefinitions", - attr: "drgElement", - }) - .ack({ - json: clipboard.artifacts, - type: "DMN15__tDefinitions", - attr: "artifact", - }) - .ack({ - json: clipboard.shapes, - type: "DMNDI15__DMNDiagram", - attr: "dmndi:DMNDiagramElement", - __$$element: "dmndi:DMNShape", - }) - .ack({ - json: clipboard.edges, - type: "DMNDI15__DMNDiagram", - attr: "dmndi:DMNDiagramElement", - __$$element: "dmndi:DMNEdge", - }) - .ack<any>({ - // This `any` argument ideally wouldn't be here, but the type of DMN's `meta` is not composed with KIE's `meta` in compile-time - json: clipboard.widths, - type: "KIE__tComponentsWidthsExtension", - attr: "kie:ComponentWidths", - }) - .randomize(); - - dmnEditorStoreApi.setState((state) => { - state.dmn.model.definitions.drgElement ??= []; - state.dmn.model.definitions.drgElement.push(...clipboard.drgElements); - state.dmn.model.definitions.artifact ??= []; - state.dmn.model.definitions.artifact.push(...clipboard.artifacts); - - const { diagramElements, widths } = addOrGetDrd({ - definitions: state.dmn.model.definitions, - drdIndex: state.diagram.drdIndex, - }); - diagramElements.push(...clipboard.shapes.map((s) => ({ ...s, __$$element: "dmndi:DMNShape" as const }))); - diagramElements.push(...clipboard.edges.map((s) => ({ ...s, __$$element: "dmndi:DMNEdge" as const }))); - - widths.push(...clipboard.widths); - - repopulateInputDataAndDecisionsOnAllDecisionServices({ definitions: state.dmn.model.definitions }); - - state.diagram._selectedNodes = [...clipboard.drgElements, ...clipboard.artifacts].map((s) => - buildXmlHref({ id: s["@_id"]! }) - ); - - if (state.diagram._selectedNodes.length === 1) { - state.focus.consumableId = parseXmlHref(state.diagram._selectedNodes[0]).id; - } - }); - }); - }, [paste, dmnEditorStoreApi]); - - // Select/deselect all - const selectAll = RF.useKeyPress(["a", "Meta+a"]); - useEffect(() => { - if (!selectAll) { - return; - } - - const allNodeIds = rfStoreApi - .getState() - .getNodes() - .map((s) => s.id); - - const allEdgeIds = rfStoreApi.getState().edges.map((s) => s.id); - - dmnEditorStoreApi.setState((state) => { - const allSelectedNodesSet = new Set(state.diagram._selectedNodes); - const allSelectedEdgesSet = new Set(state.diagram._selectedEdges); - - // If everything is selected, deselect everything. - if ( - allNodeIds.every((id) => allSelectedNodesSet.has(id) && allEdgeIds.every((id) => allSelectedEdgesSet.has(id))) - ) { - state.diagram._selectedNodes = []; - state.diagram._selectedEdges = []; - } else { - state.diagram._selectedNodes = allNodeIds; - state.diagram._selectedEdges = allEdgeIds; - } - }); - }, [selectAll, dmnEditorStoreApi, rfStoreApi]); - - // Create group wrapping selection - const g = RF.useKeyPress(["g"]); - useEffect(() => { - if (!g) { - return; - } - - const selectedNodes = rf.getNodes().filter((s) => s.selected); - if (selectedNodes.length <= 0) { - return; - } - - dmnEditorStoreApi.setState((state) => { - if (state.diagram._selectedNodes.length <= 0) { - return; - } - - const { href: newNodeId } = addStandaloneNode({ - definitions: state.dmn.model.definitions, - drdIndex: state.diagram.drdIndex, - newNode: { - type: NODE_TYPES.group, - bounds: getBounds({ - nodes: selectedNodes, - padding: CONTAINER_NODES_DESIRABLE_PADDING, - }), - }, - }); - - state.dispatch(state).diagram.setNodeStatus(newNodeId, { selected: true }); - }); - }, [g, dmnEditorStoreApi, rf]); - - // Toggle hierarchy highlights - const h = RF.useKeyPress(["h"]); - useEffect(() => { - if (!h) { - return; - } - - dmnEditorStoreApi.setState((state) => { - state.diagram.overlays.enableNodeHierarchyHighlight = !state.diagram.overlays.enableNodeHierarchyHighlight; - }); - }, [h, dmnEditorStoreApi]); - - // Show Properties panel - const i = RF.useKeyPress(["i"]); - useEffect(() => { - if (!i) { - return; - } - - dmnEditorStoreApi.setState((state) => { - state.diagram.propertiesPanel.isOpen = !state.diagram.propertiesPanel.isOpen; - }); - }, [i, dmnEditorStoreApi]); - - // Hide from DRD - const x = RF.useKeyPress(["x"]); - useEffect(() => { - if (!x) { - return; - } - - const nodesById = rf - .getNodes() - .reduce((acc, s) => acc.set(s.id, s), new Map<string, RF.Node<DmnDiagramNodeData>>()); - - dmnEditorStoreApi.setState((state) => { - const selectedNodeIds = new Set(state.diagram._selectedNodes); - for (const edge of rf.getEdges()) { - if ( - (selectedNodeIds.has(edge.source) && - canRemoveNodeFromDrdOnly({ - externalDmnsIndex: state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace).dmns, - definitions: state.dmn.model.definitions, - drdIndex: state.diagram.drdIndex, - dmnObjectNamespace: - nodesById.get(edge.source)!.data.dmnObjectNamespace ?? state.dmn.model.definitions["@_namespace"], - dmnObjectId: nodesById.get(edge.source)!.data.dmnObject?.["@_id"], - })) || - (selectedNodeIds.has(edge.target) && - canRemoveNodeFromDrdOnly({ - externalDmnsIndex: state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace).dmns, - definitions: state.dmn.model.definitions, - drdIndex: state.diagram.drdIndex, - dmnObjectNamespace: - nodesById.get(edge.target)!.data.dmnObjectNamespace ?? state.dmn.model.definitions["@_namespace"], - dmnObjectId: nodesById.get(edge.target)!.data.dmnObject?.["@_id"], - })) - ) { - deleteEdge({ - definitions: state.dmn.model.definitions, - drdIndex: state.diagram.drdIndex, - edge: { id: edge.id, dmnObject: edge.data!.dmnObject }, - mode: EdgeDeletionMode.FROM_CURRENT_DRD_ONLY, - }); - state.dispatch(state).diagram.setEdgeStatus(edge.id, { selected: false, draggingWaypoint: false }); - } - } - - for (const node of rf.getNodes().filter((s) => s.selected)) { - // Prevent hiding artifact nodes from DRD; - if (nodeNatures[node.type as NodeType] === NodeNature.ARTIFACT) { - continue; - } - const { deletedDmnShapeOnCurrentDrd: deletedShape } = deleteNode({ - drgEdges: [], // Deleting from DRD only. - definitions: state.dmn.model.definitions, - externalDmnsIndex: state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace).dmns, - drdIndex: state.diagram.drdIndex, - dmnObjectNamespace: node.data.dmnObjectNamespace ?? state.dmn.model.definitions["@_namespace"], - dmnObjectQName: node.data.dmnObjectQName, - dmnObjectId: node.data.dmnObject?.["@_id"], - nodeNature: nodeNatures[node.type as NodeType], - mode: NodeDeletionMode.FROM_CURRENT_DRD_ONLY, - }); - - if (deletedShape) { - state.dispatch(state).diagram.setNodeStatus(node.id, { - selected: false, - dragging: false, - resizing: false, - }); - } - } - }); - }, [x, dmnEditorStoreApi, rf, externalModelsByNamespace]); - - return <></>; -} - -export function PanWhenAltPressed() { - const altPressed = RF.useKeyPress("Alt"); - const rfStoreApi = RF.useStoreApi(); - - useEffect(() => { - rfStoreApi.setState({ - nodesDraggable: !altPressed, - nodesConnectable: !altPressed, - elementsSelectable: !altPressed, - }); - }, [altPressed, rfStoreApi]); - - return <></>; -} diff --git a/packages/dmn-editor/src/diagram/DiagramCommands.tsx b/packages/dmn-editor/src/diagram/DiagramCommands.tsx new file mode 100644 index 00000000000..9d073b1c98c --- /dev/null +++ b/packages/dmn-editor/src/diagram/DiagramCommands.tsx @@ -0,0 +1,449 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as RF from "reactflow"; +import * as React from "react"; +import { useEffect } from "react"; +import { + DMN_EDITOR_DIAGRAM_CLIPBOARD_MIME_TYPE, + DmnEditorDiagramClipboard, + buildClipboardFromDiagram, + getClipboard, +} from "../clipboard/Clipboard"; +import { getNewDmnIdRandomizer } from "../idRandomizer/dmnIdRandomizer"; +import { NodeNature, nodeNatures } from "../mutations/NodeNature"; +import { addOrGetDrd } from "../mutations/addOrGetDrd"; +import { addStandaloneNode } from "../mutations/addStandaloneNode"; +import { EdgeDeletionMode, deleteEdge } from "../mutations/deleteEdge"; +import { NodeDeletionMode, canRemoveNodeFromDrdOnly, deleteNode } from "../mutations/deleteNode"; +import { repopulateInputDataAndDecisionsOnAllDecisionServices } from "../mutations/repopulateInputDataAndDecisionsOnDecisionService"; +import { useDmnEditorStoreApi } from "../store/StoreContext"; +import { DmnDiagramEdgeData } from "./edges/Edges"; +import { CONTAINER_NODES_DESIRABLE_PADDING, getBounds } from "./maths/DmnMaths"; +import { NODE_TYPES } from "./nodes/NodeTypes"; +import { DmnDiagramNodeData } from "./nodes/Nodes"; +import { useExternalModels } from "../includedModels/DmnEditorDependenciesContext"; +import { NodeType } from "./connections/graphStructure"; +import { buildXmlHref, parseXmlHref } from "../xml/xmlHrefs"; +import { DEFAULT_VIEWPORT } from "./Diagram"; +import { useCommands } from "../commands/CommandsContextProvider"; + +export function DiagramCommands(props: {}) { + const rfStoreApi = RF.useStoreApi(); + const dmnEditorStoreApi = useDmnEditorStoreApi(); + const { commandsRef } = useCommands(); + const { externalModelsByNamespace } = useExternalModels(); + const rf = RF.useReactFlow<DmnDiagramNodeData, DmnDiagramEdgeData>(); + + // Cancel action + useEffect(() => { + if (!commandsRef.current) { + return; + } + commandsRef.current.cancelAction = async () => { + console.debug("DMN DIAGRAM: COMMANDS: Canceling action..."); + rfStoreApi.setState((rfState) => { + if (rfState.connectionNodeId) { + rfState.cancelConnection(); + dmnEditorStoreApi.setState((state) => { + state.diagram.ongoingConnection = undefined; + }); + } else { + (document.activeElement as any)?.blur?.(); + } + + return rfState; + }); + }; + }, [dmnEditorStoreApi, commandsRef, rfStoreApi]); + + // Reset position to origin + useEffect(() => { + if (!commandsRef.current) { + return; + } + commandsRef.current.resetPosition = async () => { + console.debug("DMN DIAGRAM: COMMANDS: Reseting position..."); + rf.setViewport(DEFAULT_VIEWPORT, { duration: 200 }); + }; + }, [commandsRef, rf]); + + // Focus on selection + useEffect(() => { + if (!commandsRef.current) { + return; + } + commandsRef.current.focusOnSelection = async () => { + console.debug("DMN DIAGRAM: COMMANDS: Focusing on selected bounds..."); + const selectedNodes = rf.getNodes().filter((s) => s.selected); + if (selectedNodes.length <= 0) { + return; + } + + const bounds = getBounds({ + nodes: selectedNodes, + padding: 100, + }); + + rf.fitBounds( + { + x: bounds["@_x"], + y: bounds["@_y"], + width: bounds["@_width"], + height: bounds["@_height"], + }, + { duration: 200 } + ); + }; + }, [commandsRef, rf]); + + // Cut nodes + useEffect(() => { + if (!commandsRef.current) { + return; + } + commandsRef.current.cut = async () => { + console.debug("DMN DIAGRAM: COMMANDS: Cutting selected nodes..."); + const { clipboard, copiedEdgesById, danglingEdgesById, copiedNodesById } = buildClipboardFromDiagram( + rfStoreApi.getState(), + dmnEditorStoreApi.getState() + ); + + navigator.clipboard.writeText(JSON.stringify(clipboard)).then(() => { + dmnEditorStoreApi.setState((state) => { + // Delete edges + [...copiedEdgesById.values(), ...danglingEdgesById.values()].forEach((edge) => { + deleteEdge({ + definitions: state.dmn.model.definitions, + drdIndex: state.diagram.drdIndex, + edge: { id: edge.id, dmnObject: edge.data!.dmnObject }, + mode: EdgeDeletionMode.FROM_DRG_AND_ALL_DRDS, + }); + state.dispatch(state).diagram.setEdgeStatus(edge.id, { + selected: false, + draggingWaypoint: false, + }); + }); + + // Delete nodes + rfStoreApi + .getState() + .getNodes() + .forEach((node: RF.Node<DmnDiagramNodeData>) => { + if (copiedNodesById.has(node.id)) { + deleteNode({ + drgEdges: state.computed(state).getDiagramData(externalModelsByNamespace).drgEdges, + definitions: state.dmn.model.definitions, + drdIndex: state.diagram.drdIndex, + dmnObjectNamespace: node.data.dmnObjectNamespace ?? state.dmn.model.definitions["@_namespace"], + dmnObjectQName: node.data.dmnObjectQName, + dmnObjectId: node.data.dmnObject?.["@_id"], + nodeNature: nodeNatures[node.type as NodeType], + mode: NodeDeletionMode.FROM_DRG_AND_ALL_DRDS, + externalDmnsIndex: state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace) + .dmns, + }); + state.dispatch(state).diagram.setNodeStatus(node.id, { + selected: false, + dragging: false, + resizing: false, + }); + } + }); + }); + }); + }; + }, [dmnEditorStoreApi, externalModelsByNamespace, commandsRef, rfStoreApi]); + + // Copy nodes + useEffect(() => { + if (!commandsRef.current) { + return; + } + commandsRef.current.copy = async () => { + console.debug("DMN DIAGRAM: COMMANDS: Copying selected nodes..."); + const { clipboard } = buildClipboardFromDiagram(rfStoreApi.getState(), dmnEditorStoreApi.getState()); + navigator.clipboard.writeText(JSON.stringify(clipboard)); + }; + }, [dmnEditorStoreApi, commandsRef, rfStoreApi]); + + // Paste nodes + useEffect(() => { + if (!commandsRef.current) { + return; + } + commandsRef.current.paste = async () => { + console.debug("DMN DIAGRAM: COMMANDS: Pasting nodes..."); + navigator.clipboard.readText().then((text) => { + const clipboard = getClipboard<DmnEditorDiagramClipboard>(text, DMN_EDITOR_DIAGRAM_CLIPBOARD_MIME_TYPE); + if (!clipboard) { + return; + } + + getNewDmnIdRandomizer() + .ack({ + json: clipboard.drgElements, + type: "DMN15__tDefinitions", + attr: "drgElement", + }) + .ack({ + json: clipboard.artifacts, + type: "DMN15__tDefinitions", + attr: "artifact", + }) + .ack({ + json: clipboard.shapes, + type: "DMNDI15__DMNDiagram", + attr: "dmndi:DMNDiagramElement", + __$$element: "dmndi:DMNShape", + }) + .ack({ + json: clipboard.edges, + type: "DMNDI15__DMNDiagram", + attr: "dmndi:DMNDiagramElement", + __$$element: "dmndi:DMNEdge", + }) + .ack<any>({ + // This `any` argument ideally wouldn't be here, but the type of DMN's `meta` is not composed with KIE's `meta` in compile-time + json: clipboard.widths, + type: "KIE__tComponentsWidthsExtension", + attr: "kie:ComponentWidths", + }) + .randomize(); + + dmnEditorStoreApi.setState((state) => { + state.dmn.model.definitions.drgElement ??= []; + state.dmn.model.definitions.drgElement.push(...clipboard.drgElements); + state.dmn.model.definitions.artifact ??= []; + state.dmn.model.definitions.artifact.push(...clipboard.artifacts); + + const { diagramElements, widths } = addOrGetDrd({ + definitions: state.dmn.model.definitions, + drdIndex: state.diagram.drdIndex, + }); + diagramElements.push(...clipboard.shapes.map((s) => ({ ...s, __$$element: "dmndi:DMNShape" as const }))); + diagramElements.push(...clipboard.edges.map((s) => ({ ...s, __$$element: "dmndi:DMNEdge" as const }))); + + widths.push(...clipboard.widths); + + repopulateInputDataAndDecisionsOnAllDecisionServices({ definitions: state.dmn.model.definitions }); + + state.diagram._selectedNodes = [...clipboard.drgElements, ...clipboard.artifacts].map((s) => + buildXmlHref({ id: s["@_id"]! }) + ); + + if (state.diagram._selectedNodes.length === 1) { + state.focus.consumableId = parseXmlHref(state.diagram._selectedNodes[0]).id; + } + }); + }); + }; + }, [dmnEditorStoreApi, commandsRef]); + + // Select/deselect all nodes + useEffect(() => { + if (!commandsRef.current) { + return; + } + commandsRef.current.selectAll = async () => { + console.debug("DMN DIAGRAM: COMMANDS: Selecting/Deselecting nodes..."); + const allNodeIds = rfStoreApi + .getState() + .getNodes() + .map((s) => s.id); + + const allEdgeIds = rfStoreApi.getState().edges.map((s) => s.id); + + dmnEditorStoreApi.setState((state) => { + const allSelectedNodesSet = new Set(state.diagram._selectedNodes); + const allSelectedEdgesSet = new Set(state.diagram._selectedEdges); + + // If everything is selected, deselect everything. + if ( + allNodeIds.every((id) => allSelectedNodesSet.has(id) && allEdgeIds.every((id) => allSelectedEdgesSet.has(id))) + ) { + state.diagram._selectedNodes = []; + state.diagram._selectedEdges = []; + } else { + state.diagram._selectedNodes = allNodeIds; + state.diagram._selectedEdges = allEdgeIds; + } + }); + }; + }, [dmnEditorStoreApi, commandsRef, rfStoreApi]); + + // Create group wrapping selection + useEffect(() => { + if (!commandsRef.current) { + return; + } + commandsRef.current.createGroup = async () => { + console.debug("DMN DIAGRAM: COMMANDS: Grouping nodes..."); + const selectedNodes = rf.getNodes().filter((s) => s.selected); + if (selectedNodes.length <= 0) { + return; + } + + dmnEditorStoreApi.setState((state) => { + if (state.diagram._selectedNodes.length <= 0) { + return; + } + + const { href: newNodeId } = addStandaloneNode({ + definitions: state.dmn.model.definitions, + drdIndex: state.diagram.drdIndex, + newNode: { + type: NODE_TYPES.group, + bounds: getBounds({ + nodes: selectedNodes, + padding: CONTAINER_NODES_DESIRABLE_PADDING, + }), + }, + }); + + state.dispatch(state).diagram.setNodeStatus(newNodeId, { selected: true }); + }); + }; + }, [dmnEditorStoreApi, commandsRef, rf]); + + // Toggle hierarchy highlights + useEffect(() => { + if (!commandsRef.current) { + return; + } + commandsRef.current.toggleHierarchyHighlight = async () => { + console.debug("DMN DIAGRAM: COMMANDS: Toggle hierarchy highlights..."); + dmnEditorStoreApi.setState((state) => { + state.diagram.overlays.enableNodeHierarchyHighlight = !state.diagram.overlays.enableNodeHierarchyHighlight; + }); + }; + }, [dmnEditorStoreApi, commandsRef]); + + // Show Properties panel + useEffect(() => { + if (!commandsRef.current) { + return; + } + commandsRef.current.togglePropertiesPanel = async () => { + console.debug("DMN DIAGRAM: COMMANDS: Toggle properties panel..."); + dmnEditorStoreApi.setState((state) => { + state.diagram.propertiesPanel.isOpen = !state.diagram.propertiesPanel.isOpen; + }); + }; + }, [dmnEditorStoreApi, commandsRef]); + + // Hide from DRD + useEffect(() => { + if (!commandsRef.current) { + return; + } + commandsRef.current.hideFromDrd = async () => { + console.debug("DMN DIAGRAM: COMMANDS: Hide node from DRD..."); + const nodesById = rf + .getNodes() + .reduce((acc, s) => acc.set(s.id, s), new Map<string, RF.Node<DmnDiagramNodeData>>()); + + dmnEditorStoreApi.setState((state) => { + const selectedNodeIds = new Set(state.diagram._selectedNodes); + for (const edge of rf.getEdges()) { + if ( + (selectedNodeIds.has(edge.source) && + canRemoveNodeFromDrdOnly({ + externalDmnsIndex: state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace) + .dmns, + definitions: state.dmn.model.definitions, + drdIndex: state.diagram.drdIndex, + dmnObjectNamespace: + nodesById.get(edge.source)!.data.dmnObjectNamespace ?? state.dmn.model.definitions["@_namespace"], + dmnObjectId: nodesById.get(edge.source)!.data.dmnObject?.["@_id"], + })) || + (selectedNodeIds.has(edge.target) && + canRemoveNodeFromDrdOnly({ + externalDmnsIndex: state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace) + .dmns, + definitions: state.dmn.model.definitions, + drdIndex: state.diagram.drdIndex, + dmnObjectNamespace: + nodesById.get(edge.target)!.data.dmnObjectNamespace ?? state.dmn.model.definitions["@_namespace"], + dmnObjectId: nodesById.get(edge.target)!.data.dmnObject?.["@_id"], + })) + ) { + deleteEdge({ + definitions: state.dmn.model.definitions, + drdIndex: state.diagram.drdIndex, + edge: { id: edge.id, dmnObject: edge.data!.dmnObject }, + mode: EdgeDeletionMode.FROM_CURRENT_DRD_ONLY, + }); + state.dispatch(state).diagram.setEdgeStatus(edge.id, { selected: false, draggingWaypoint: false }); + } + } + + for (const node of rf.getNodes().filter((s) => s.selected)) { + // Prevent hiding artifact nodes from DRD; + if (nodeNatures[node.type as NodeType] === NodeNature.ARTIFACT) { + continue; + } + const { deletedDmnShapeOnCurrentDrd: deletedShape } = deleteNode({ + drgEdges: [], // Deleting from DRD only. + definitions: state.dmn.model.definitions, + externalDmnsIndex: state.computed(state).getExternalModelTypesByNamespace(externalModelsByNamespace).dmns, + drdIndex: state.diagram.drdIndex, + dmnObjectNamespace: node.data.dmnObjectNamespace ?? state.dmn.model.definitions["@_namespace"], + dmnObjectQName: node.data.dmnObjectQName, + dmnObjectId: node.data.dmnObject?.["@_id"], + nodeNature: nodeNatures[node.type as NodeType], + mode: NodeDeletionMode.FROM_CURRENT_DRD_ONLY, + }); + + if (deletedShape) { + state.dispatch(state).diagram.setNodeStatus(node.id, { + selected: false, + dragging: false, + resizing: false, + }); + } + } + }); + }; + }, [dmnEditorStoreApi, externalModelsByNamespace, commandsRef, rf]); + + useEffect(() => { + if (!commandsRef.current) { + return; + } + commandsRef.current.panDown = async () => { + console.debug("DMN DIAGRAM: COMMANDS: Panning down"); + rfStoreApi.setState({ + nodesDraggable: false, + nodesConnectable: false, + elementsSelectable: false, + }); + }; + commandsRef.current.panUp = async () => { + console.debug("DMN DIAGRAM: COMMANDS: Panning up"); + rfStoreApi.setState({ + nodesDraggable: true, + nodesConnectable: true, + elementsSelectable: true, + }); + }; + }, [commandsRef, rfStoreApi]); + + return <></>; +} diff --git a/packages/dmn-editor/src/draggable/Draggable.tsx b/packages/dmn-editor/src/draggable/Draggable.tsx index cdffd6aeac4..27a605b65c5 100644 --- a/packages/dmn-editor/src/draggable/Draggable.tsx +++ b/packages/dmn-editor/src/draggable/Draggable.tsx @@ -213,6 +213,7 @@ export function Draggable(props: { childrenClassName?: string; itemStyle?: React.CSSProperties; itemClassName?: string; + isDisabled: boolean; }) { const { source, dragging, leftOrigin } = useDraggableStateContext(); const { onDragStart, onDragOver, onDragEnd, onDragEnter, onDragLeave } = useDraggableDispatchContext(); @@ -252,18 +253,22 @@ export function Draggable(props: { onPointerLeave={() => setHoveredItem(-1)} onPointerOver={() => setHoveredItem(props.index)} > - <Icon - className={"kie-dmn-editor--draggable-icon"} - onPointerEnter={() => setDraggable(true)} - onPointerLeave={() => setDraggable(false)} - style={props.handlerStyle} - > - <GripVerticalIcon - className={ - hovered ? "kie-dmn-editor--draggable-icon-handler-hovered" : "kie-dmn-editor--draggable-icon-handler" - } - /> - </Icon> + {!props.isDisabled ? ( + <Icon + className={"kie-dmn-editor--draggable-icon"} + onPointerEnter={() => setDraggable(true)} + onPointerLeave={() => setDraggable(false)} + style={props.handlerStyle} + > + <GripVerticalIcon + className={ + hovered ? "kie-dmn-editor--draggable-icon-handler-hovered" : "kie-dmn-editor--draggable-icon-handler" + } + /> + </Icon> + ) : ( + <div style={{ width: "36px" }}></div> + )} <div style={props.childrenStyle} className={`kie-dmn-editor--draggable-children ${props.childrenClassName ? props.childrenClassName : ""}`} diff --git a/packages/dmn-editor/src/mutations/addMissingImportNamespaces.ts b/packages/dmn-editor/src/mutations/addMissingImportNamespaces.ts new file mode 100644 index 00000000000..198c07b0f98 --- /dev/null +++ b/packages/dmn-editor/src/mutations/addMissingImportNamespaces.ts @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { DMN15__tDefinitions } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; + +export function addMissingImportNamespaces(definitions: DMN15__tDefinitions) { + if (definitions.import === undefined) { + return; + } + + // Collect all declared namespaces + const definedNamespaces = new Set( + Object.keys(definitions) + .filter((keys: keyof DMN15__tDefinitions) => String(keys).startsWith("@_xmlns:")) + .map((xmlnsKey: keyof DMN15__tDefinitions) => definitions[xmlnsKey]) + ); + + // Add missing import namespace declarations as `xmlns:included*` + let includedIndex = 0; + for (let index = 0; index < definitions.import.length; index++) { + const importedModelNamespace = definitions.import[index]["@_namespace"]; + + // Check if namespace is already declared + if (definedNamespaces.has(importedModelNamespace)) { + // Ignore namespaces that are already declared + continue; + } + + // Get next available `included*` namespace declaration name + while (definitions[`@_xmlns:included${includedIndex}`]) { + includedIndex++; + } + + definitions[`@_xmlns:included${includedIndex}`] = importedModelNamespace; + } +} diff --git a/packages/dmn-editor/src/mutations/deleteNode.ts b/packages/dmn-editor/src/mutations/deleteNode.ts index a3f07d7819a..c7dc7d75889 100644 --- a/packages/dmn-editor/src/mutations/deleteNode.ts +++ b/packages/dmn-editor/src/mutations/deleteNode.ts @@ -131,7 +131,12 @@ export function deleteNode({ throw new Error(`DMN MUTATION: Unknown node nature '${nodeNature}'.`); } - if (!dmnObject) { + if (!dmnObject && nodeNature !== NodeNature.UNKNOWN) { + /** + * We do not want to throw error in case of `nodeNature` equals to `NodeNature.UNKNOWN`. + * In such scenario it is expected `dmnObject` is undefined as we can not pair `dmnObject` with the `DMNShape`. + * However we are still able to delete at least the selected `DMNShape` from the diagram. + */ throw new Error(`DMN MUTATION: Can't delete DMN object that doesn't exist: ID=${dmnObjectId}`); } } diff --git a/packages/dmn-editor/src/normalization/normalize.ts b/packages/dmn-editor/src/normalization/normalize.ts new file mode 100644 index 00000000000..c3951676a50 --- /dev/null +++ b/packages/dmn-editor/src/normalization/normalize.ts @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { getNewDmnIdRandomizer } from "../idRandomizer/dmnIdRandomizer"; +import { addMissingImportNamespaces } from "../mutations/addMissingImportNamespaces"; +import { State } from "../store/Store"; + +export function normalize(model: State["dmn"]["model"]) { + getNewDmnIdRandomizer() + .ack({ + json: model.definitions.drgElement, + type: "DMN15__tDefinitions", + attr: "drgElement", + }) + .ack({ + json: model.definitions.artifact, + type: "DMN15__tDefinitions", + attr: "artifact", + }) + .ack({ + json: model.definitions["dmndi:DMNDI"], + type: "DMN15__tDefinitions", + attr: "dmndi:DMNDI", + }) + .ack({ + json: model.definitions.import, + type: "DMN15__tDefinitions", + attr: "import", + }) + .ack({ + json: model.definitions.itemDefinition, + type: "DMN15__tDefinitions", + attr: "itemDefinition", + }) + .randomize({ skipAlreadyAttributedIds: true }); + + addMissingImportNamespaces(model.definitions); + + return model; +} diff --git a/packages/dmn-editor/src/propertiesPanel/BeePropertiesPanel.tsx b/packages/dmn-editor/src/propertiesPanel/BeePropertiesPanel.tsx index 1321b95629b..5707a3ed75f 100644 --- a/packages/dmn-editor/src/propertiesPanel/BeePropertiesPanel.tsx +++ b/packages/dmn-editor/src/propertiesPanel/BeePropertiesPanel.tsx @@ -55,7 +55,7 @@ export function BeePropertiesPanel() { isResizable={true} minSize={"300px"} defaultSize={"500px"} - onKeyDown={(e) => e.stopPropagation()} // This prevents ReactFlow KeyboardShortcuts from triggering when editing stuff on Properties Panel + onKeyDown={(e) => e.stopPropagation()} // Prevent ReactFlow KeyboardShortcuts from triggering when editing stuff on Properties Panel > <DrawerHead> {shouldDisplayDecisionOrBkmProps && <SingleNodeProperties nodeId={node.id} />} diff --git a/packages/dmn-editor/src/propertiesPanel/BkmProperties.tsx b/packages/dmn-editor/src/propertiesPanel/BkmProperties.tsx index 1383fe45b67..a8c9d9aacb8 100644 --- a/packages/dmn-editor/src/propertiesPanel/BkmProperties.tsx +++ b/packages/dmn-editor/src/propertiesPanel/BkmProperties.tsx @@ -77,6 +77,7 @@ export function BkmProperties({ <TypeRefSelector heightRef={dmnEditorRootElementRef} typeRef={resolvedTypeRef} + isDisabled={isReadonly} onChange={(newTypeRef) => { setState((state) => { const drgElement = state.dmn.model.definitions.drgElement![index] as DMN15__tBusinessKnowledgeModel; diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanel.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanel.tsx new file mode 100644 index 00000000000..2e12587303d --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanel.tsx @@ -0,0 +1,205 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { + DrawerActions, + DrawerCloseButton, + DrawerHead, + DrawerPanelContent, +} from "@patternfly/react-core/dist/js/components/Drawer"; +import { useMemo } from "react"; +import { buildXmlHref } from "../xml/xmlHrefs"; +import { SingleNodeProperties } from "./SingleNodeProperties"; +import { generateBoxedExpressionIndex } from "../boxedExpressions/boxedExpressionIndex"; +import { Form, FormSection } from "@patternfly/react-core/dist/js/components/Form"; +import { RelationInformationItemCell } from "./BoxedExpressionPropertiesPanelComponents/RelationInformationItemCell"; +import { DecisionTableInputHeaderCell } from "./BoxedExpressionPropertiesPanelComponents/DecisionTableInputHeaderCell"; +import { DecisionTableOutputHeaderCell } from "./BoxedExpressionPropertiesPanelComponents/DecisionTableOutputHeaderCell"; +import { LiteralExpressionContentCell } from "./BoxedExpressionPropertiesPanelComponents/LiteralExpressionContentCell"; +import { ExpressionRootCell } from "./BoxedExpressionPropertiesPanelComponents/ExpressionRootCell"; +import { DecisionTableInputRule } from "./BoxedExpressionPropertiesPanelComponents/DecisionTableInputRuleCell"; +import { AllExpressions } from "../dataTypes/DataTypeSpec"; +import { DecisionTableRootCell } from "./BoxedExpressionPropertiesPanelComponents/DecisionTableRootCell"; +import { InvocationFunctionCallCell } from "./BoxedExpressionPropertiesPanelComponents/InvocationFunctionCallCell"; +import { FunctionDefinitionParameterCell } from "./BoxedExpressionPropertiesPanelComponents/FunctionDefinitionParametersCell"; +import { FunctionDefinitionRootCell } from "./BoxedExpressionPropertiesPanelComponents/FunctionDefinitionRootCell"; +import { WithoutPropertiesCell } from "./BoxedExpressionPropertiesPanelComponents/WithoutPropertiesCell"; +import { DecisionTableOutputRuleCell } from "./BoxedExpressionPropertiesPanelComponents/DecisionTableOutputRuleCell"; +import { ContextInformationItemCell } from "./BoxedExpressionPropertiesPanelComponents/ContextInformationItemCell"; +import { InvocationInformationItemCell } from "./BoxedExpressionPropertiesPanelComponents/InvocationInformationItemCell"; +import { SelectExpressionCell } from "./BoxedExpressionPropertiesPanelComponents/SelectExpressionCell"; +import { + BoxedExpressionPropertiesPanelComponent, + getBoxedExpressionPropertiesPanelComponent, +} from "./BoxedExpressionPropertiesPanelComponents/getBoxedExpressionPropertiesPanelComponent"; +import { useDmnEditorStore, useDmnEditorStoreApi } from "../store/StoreContext"; +import { useExternalModels } from "../includedModels/DmnEditorDependenciesContext"; +import { drgElementToBoxedExpression } from "../boxedExpressions/BoxedExpressionScreen"; +import { IteratorVariableCell } from "./BoxedExpressionPropertiesPanelComponents/IteratorVariableCell"; + +export function BoxedExpressionPropertiesPanel() { + const dmnEditorStoreApi = useDmnEditorStoreApi(); + const thisDmnsNamespace = useDmnEditorStore((s) => s.dmn.model.definitions["@_namespace"]); + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const activeDrgElementId = useDmnEditorStore((s) => s.boxedExpressionEditor.activeDrgElementId); + const { externalModelsByNamespace } = useExternalModels(); + + const shouldDisplayDecisionOrBkmProps = useMemo( + () => selectedObjectId === undefined || (selectedObjectId && selectedObjectId === activeDrgElementId), + [activeDrgElementId, selectedObjectId] + ); + + const node = useDmnEditorStore((s) => + s + .computed(s) + .getDiagramData(externalModelsByNamespace) + .nodesById.get(buildXmlHref({ id: activeDrgElementId ?? "" })) + ); + + const isReadonly = !!node?.data.dmnObjectNamespace && node.data.dmnObjectNamespace !== thisDmnsNamespace; + + const boxedExpressionIndex = useMemo(() => { + if (node?.data.dmnObject === undefined) { + return; + } + + if ( + node.data.dmnObject?.__$$element === "businessKnowledgeModel" || + node.data.dmnObject?.__$$element === "decision" + ) { + const expression = drgElementToBoxedExpression(node.data.dmnObject); + return expression ? generateBoxedExpressionIndex(expression, new Map(), []) : undefined; + } + return; + }, [node?.data.dmnObject]); + + const boxedExpressionPropertiesPanelComponent = useMemo(() => { + const selectedObjectInfos = boxedExpressionIndex?.get(selectedObjectId ?? ""); + const selectedObjectPath = selectedObjectInfos?.expressionPath[selectedObjectInfos.expressionPath.length - 1]; + if (!selectedObjectPath) { + return; + } + return getBoxedExpressionPropertiesPanelComponent(selectedObjectPath); + }, [boxedExpressionIndex, selectedObjectId]); + + return ( + <> + {node && ( + <DrawerPanelContent + isResizable={true} + minSize={"300px"} + defaultSize={"500px"} + onKeyDown={(e) => e.stopPropagation()} // Prevent ReactFlow KeyboardShortcuts from triggering when editing stuff on Properties Panel + > + <DrawerHead> + {shouldDisplayDecisionOrBkmProps && <SingleNodeProperties nodeId={node.id} />} + <DrawerActions> + <DrawerCloseButton + onClick={() => { + dmnEditorStoreApi.setState((state) => { + state.boxedExpressionEditor.propertiesPanel.isOpen = false; + }); + }} + /> + </DrawerActions> + {!shouldDisplayDecisionOrBkmProps && ( + <Form> + <FormSection title={boxedExpressionPropertiesPanelComponent?.title ?? ""}> + {(((selectedObjectId === undefined || selectedObjectId === "") && + boxedExpressionPropertiesPanelComponent === undefined) || + boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.WITHOUT_PROPERTIES_CELL) && <WithoutPropertiesCell />} + {selectedObjectId !== "" && boxedExpressionPropertiesPanelComponent === undefined && ( + <SelectExpressionCell selectedObjectId={selectedObjectId!} /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.CONTEXT_INFORMATION_ITEM_CELL && ( + <ContextInformationItemCell boxedExpressionIndex={boxedExpressionIndex} isReadonly={isReadonly} /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.DECISION_TABLE_INPUT_HEADER && ( + <DecisionTableInputHeaderCell boxedExpressionIndex={boxedExpressionIndex} isReadonly={isReadonly} /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.DECISION_TABLE_INPUT_RULE && ( + <DecisionTableInputRule boxedExpressionIndex={boxedExpressionIndex} isReadonly={isReadonly} /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.DECISION_TABLE_OUTPUT_HEADER && ( + <DecisionTableOutputHeaderCell + boxedExpressionIndex={boxedExpressionIndex} + isReadonly={isReadonly} + /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.DECISION_TABLE_OUTPUT_RULE && ( + <DecisionTableOutputRuleCell boxedExpressionIndex={boxedExpressionIndex} isReadonly={isReadonly} /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.DECISION_TABLE_ROOT && ( + <DecisionTableRootCell boxedExpressionIndex={boxedExpressionIndex} isReadonly={isReadonly} /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.EXPRESSION_ROOT && ( + <ExpressionRootCell boxedExpressionIndex={boxedExpressionIndex} isReadonly={isReadonly} /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.FUNCTION_DEFINITION_PARAMETERS && ( + <FunctionDefinitionParameterCell + boxedExpressionIndex={boxedExpressionIndex} + isReadonly={isReadonly} + /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.FUNCTION_DEFINITION_ROOT && ( + <FunctionDefinitionRootCell boxedExpressionIndex={boxedExpressionIndex} isReadonly={isReadonly} /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.INVOCATION_FUNCTION_CALL && ( + <InvocationFunctionCallCell boxedExpressionIndex={boxedExpressionIndex} isReadonly={isReadonly} /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.INVOCATION_INFORMATION_ITEM_CELL && ( + <InvocationInformationItemCell + boxedExpressionIndex={boxedExpressionIndex} + isReadonly={isReadonly} + /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.ITERATOR_VARIABLE_CELL && ( + <IteratorVariableCell boxedExpressionIndex={boxedExpressionIndex} isReadonly={isReadonly} /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.LITERAL_EXPRESSION_CONTENT && ( + <LiteralExpressionContentCell boxedExpressionIndex={boxedExpressionIndex} isReadonly={isReadonly} /> + )} + {boxedExpressionPropertiesPanelComponent?.component === + BoxedExpressionPropertiesPanelComponent.RELATION_INFORMATION_ITEM_CELL && ( + <RelationInformationItemCell boxedExpressionIndex={boxedExpressionIndex} isReadonly={isReadonly} /> + )} + </FormSection> + </Form> + )} + </DrawerHead> + </DrawerPanelContent> + )} + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/ContextInformationItemCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/ContextInformationItemCell.tsx new file mode 100644 index 00000000000..db4821eef99 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/ContextInformationItemCell.tsx @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useMemo } from "react"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { DMN15__tContext, DMN15__tInformationItem } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { InformationItemCell } from "./InformationItemCell"; +import { useDmnEditorStore } from "../../store/StoreContext"; + +export function ContextInformationItemCell(props: { + boxedExpressionIndex?: BoxedExpressionIndex; + isReadonly: boolean; +}) { + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const cellPath = useMemo( + () => selectedObjectInfos?.expressionPath[selectedObjectInfos?.expressionPath.length - 1], + [selectedObjectInfos?.expressionPath] + ); + const rootPath = useMemo( + () => props.boxedExpressionIndex?.get(cellPath?.root ?? "")?.expressionPath, + [cellPath?.root, props.boxedExpressionIndex] + ); + + const updater = useBoxedExpressionUpdater<DMN15__tInformationItem>(selectedObjectInfos?.expressionPath ?? []); + const rootExpressionUpdater = useBoxedExpressionUpdater<DMN15__tContext>(rootPath ?? []); + + return ( + <> + <InformationItemCell + {...props} + onDescriptionChange={(newDescription) => { + updater((dmnObject) => { + dmnObject.description ??= { __$$text: "" }; + dmnObject.description.__$$text = newDescription; + }); + }} + onNameChange={(newName) => { + updater((dmnObject) => { + dmnObject["@_name"] = newName; + }); + }} + onTypeRefChange={(newTypeRef) => { + updater((dmnObject) => { + dmnObject["@_typeRef"] = newTypeRef; + }); + rootExpressionUpdater((dmnObject) => { + if (cellPath?.type === "context") { + const expression = (dmnObject as DMN15__tContext).contextEntry![cellPath.row ?? 0].expression; + if (expression) { + expression["@_typeRef"] = newTypeRef; + } + } + }); + }} + /> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableInputHeaderCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableInputHeaderCell.tsx new file mode 100644 index 00000000000..1256d589102 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableInputHeaderCell.tsx @@ -0,0 +1,210 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useCallback, useMemo, useState } from "react"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { ContentField, DescriptionField, ExpressionLanguageField, NameField, TypeRefField } from "./Fields"; +import { FormGroup, FormSection } from "@patternfly/react-core/dist/js/components/Form"; +import { DMN15__tInputClause } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { useDmnEditor } from "../../DmnEditorContext"; +import { DmnBuiltInDataType } from "@kie-tools/boxed-expression-component/dist/api"; +import { PropertiesPanelHeader } from "../PropertiesPanelHeader"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { ClipboardCopy } from "@patternfly/react-core/dist/js/components/ClipboardCopy"; +import { ConstraintsFromTypeConstraintAttribute } from "../../dataTypes/Constraints"; +import { useDmnEditorStore, useDmnEditorStoreApi } from "../../store/StoreContext"; +import { useExternalModels } from "../../includedModels/DmnEditorDependenciesContext"; +import { State } from "../../store/Store"; + +export function DecisionTableInputHeaderCell(props: { + boxedExpressionIndex?: BoxedExpressionIndex; + isReadonly: boolean; +}) { + const dmnEditorStoreApi = useDmnEditorStoreApi(); + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const { externalModelsByNamespace } = useExternalModels(); + const { dmnEditorRootElementRef } = useDmnEditor(); + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const updater = useBoxedExpressionUpdater<DMN15__tInputClause>(selectedObjectInfos?.expressionPath ?? []); + + const cell = useMemo(() => selectedObjectInfos?.cell as DMN15__tInputClause, [selectedObjectInfos?.cell]); + const inputExpression = useMemo(() => cell.inputExpression, [cell.inputExpression]); + const inputValues = useMemo(() => cell.inputValues, [cell.inputValues]); + + const inputExpressionItemDefinition = useMemo(() => { + const { allDataTypesById, allTopLevelItemDefinitionUniqueNames } = dmnEditorStoreApi + .getState() + .computed(dmnEditorStoreApi.getState()) + .getDataTypes(externalModelsByNamespace); + return allDataTypesById.get(allTopLevelItemDefinitionUniqueNames.get(inputExpression?.["@_typeRef"] ?? "") ?? "") + ?.itemDefinition; + }, [dmnEditorStoreApi, externalModelsByNamespace, inputExpression]); + + const [isInputExpressionExpanded, setInputExpressionExpanded] = useState(true); + const [isInputValuesExpanded, setInputValuesExpanded] = useState(false); + + const getAllUniqueNames = useCallback((s: State) => new Map(), []); + + return ( + <> + <FormGroup label="ID"> + <ClipboardCopy isReadOnly={true} hoverTip="Copy" clickTip="Copied"> + {selectedObjectId} + </ClipboardCopy> + </FormGroup> + <DescriptionField + isReadonly={props.isReadonly} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + initialValue={cell?.description?.__$$text ?? ""} + onChange={(newDescription: string) => + updater((dmnObject) => { + dmnObject.description ??= { __$$text: "" }; + dmnObject.description.__$$text = newDescription; + }) + } + /> + <FormSection> + <PropertiesPanelHeader + expands={true} + fixed={false} + isSectionExpanded={isInputExpressionExpanded} + toogleSectionExpanded={() => setInputExpressionExpanded((prev) => !prev)} + title={"Input Expression"} + /> + {isInputExpressionExpanded && ( + <> + <NameField + id={inputExpression["@_id"]!} + isReadonly={props.isReadonly} + name={inputExpression?.text?.__$$text ?? ""} + getAllUniqueNames={getAllUniqueNames} + onChange={(newName) => + updater((dmnObject) => { + dmnObject.inputExpression ??= {}; + dmnObject.inputExpression.text ??= { __$$text: "" }; + dmnObject.inputExpression.text.__$$text = newName; + }) + } + /> + <TypeRefField + isReadonly={props.isReadonly} + dmnEditorRootElementRef={dmnEditorRootElementRef} + typeRef={inputExpression?.["@_typeRef"] ?? DmnBuiltInDataType.Undefined} + onChange={(newTypeRef) => + updater((dmnObject) => { + dmnObject.inputExpression ??= {}; + dmnObject.inputExpression["@_typeRef"] = newTypeRef; + dmnObject.inputValues ??= { text: { __$$text: "" } }; + dmnObject.inputValues["@_typeRef"] = newTypeRef; + }) + } + /> + {inputExpressionItemDefinition && ( + <FormGroup label="Constraint"> + <ConstraintsFromTypeConstraintAttribute + isReadonly={true} + itemDefinition={inputExpressionItemDefinition} + editItemDefinition={() => {}} + renderOnPropertiesPanel={true} + defaultsToAllowedValues={true} + /> + </FormGroup> + )} + <ExpressionLanguageField + isReadonly={props.isReadonly} + initialValue={inputExpression?.["@_expressionLanguage"] ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newExpressionLanguage) => + updater((dmnObject) => { + dmnObject.inputExpression ??= {}; + dmnObject.inputExpression["@_expressionLanguage"] = newExpressionLanguage; + }) + } + /> + <DescriptionField + isReadonly={props.isReadonly} + initialValue={inputExpression?.description?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newDescription) => + updater((dmnObject) => { + dmnObject.inputExpression ??= {}; + dmnObject.inputExpression.description ??= { __$$text: "" }; + dmnObject.inputExpression.description.__$$text = newDescription; + }) + } + /> + </> + )} + </FormSection> + <FormSection> + <PropertiesPanelHeader + expands={true} + fixed={false} + isSectionExpanded={isInputValuesExpanded} + toogleSectionExpanded={() => setInputValuesExpanded((prev) => !prev)} + title={"Input Values"} + /> + {isInputValuesExpanded && ( + <> + <ExpressionLanguageField + isReadonly={props.isReadonly} + initialValue={inputValues?.["@_expressionLanguage"] ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newExpressionLanguage) => + updater((dmnObject) => { + dmnObject.inputValues ??= { text: { __$$text: "" } }; + dmnObject.inputValues["@_expressionLanguage"] = newExpressionLanguage; + }) + } + /> + <ContentField + isReadonly={props.isReadonly} + initialValue={inputValues?.text?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newText) => + updater((dmnObject) => { + dmnObject.inputValues ??= { text: { __$$text: "" } }; + dmnObject.inputValues.text ??= { __$$text: "" }; + dmnObject.inputValues.text.__$$text = newText; + }) + } + /> + <DescriptionField + isReadonly={props.isReadonly} + initialValue={inputValues?.description?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newDescription: string) => + updater((dmnObject) => { + dmnObject.inputValues ??= { text: { __$$text: "" } }; + dmnObject.inputValues.description ??= { __$$text: "" }; + dmnObject.inputValues.description.__$$text = newDescription; + }) + } + /> + </> + )} + </FormSection> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableInputRuleCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableInputRuleCell.tsx new file mode 100644 index 00000000000..6fa40b414ea --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableInputRuleCell.tsx @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useMemo } from "react"; +import { DescriptionField, ExpressionLanguageField, TypeRefField } from "./Fields"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { DMN15__tDecisionTable, DMN15__tUnaryTests } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { useDmnEditorStore, useDmnEditorStoreApi } from "../../store/StoreContext"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { ClipboardCopy } from "@patternfly/react-core/dist/js/components/ClipboardCopy"; +import { FormGroup } from "@patternfly/react-core/dist/js/components/Form"; +import { ConstraintsFromTypeConstraintAttribute } from "../../dataTypes/Constraints"; +import { useDmnEditor } from "../../DmnEditorContext"; +import { DmnBuiltInDataType } from "@kie-tools/boxed-expression-component/dist/api"; +import { useExternalModels } from "../../includedModels/DmnEditorDependenciesContext"; + +export function DecisionTableInputRule(props: { boxedExpressionIndex?: BoxedExpressionIndex; isReadonly: boolean }) { + const dmnEditorStoreApi = useDmnEditorStoreApi(); + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const { externalModelsByNamespace } = useExternalModels(); + const { dmnEditorRootElementRef } = useDmnEditor(); + + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const headerType = useMemo(() => { + const cellPath = selectedObjectInfos?.expressionPath[selectedObjectInfos?.expressionPath.length - 1]; + if (cellPath && cellPath.root) { + const root = props.boxedExpressionIndex?.get(cellPath.root); + if ( + root?.expressionPath[root.expressionPath.length - 1]?.type === "decisionTable" && + cellPath.type === "decisionTable" + ) { + const { allDataTypesById, allTopLevelItemDefinitionUniqueNames } = dmnEditorStoreApi + .getState() + .computed(dmnEditorStoreApi.getState()) + .getDataTypes(externalModelsByNamespace); + const typeRef = + allTopLevelItemDefinitionUniqueNames.get( + (root?.cell as DMN15__tDecisionTable)?.input?.[cellPath.column ?? 0].inputExpression["@_typeRef"] ?? "" + ) ?? DmnBuiltInDataType.Undefined; + return { typeRef, itemDefinition: allDataTypesById.get(typeRef)?.itemDefinition }; + } + } + }, [dmnEditorStoreApi, externalModelsByNamespace, props.boxedExpressionIndex, selectedObjectInfos?.expressionPath]); + + const updater = useBoxedExpressionUpdater<DMN15__tUnaryTests>(selectedObjectInfos?.expressionPath ?? []); + + const cell = useMemo(() => selectedObjectInfos?.cell as DMN15__tUnaryTests, [selectedObjectInfos?.cell]); + + return ( + <> + <FormGroup label="ID"> + <ClipboardCopy isReadOnly={true} hoverTip="Copy" clickTip="Copied"> + {selectedObjectId} + </ClipboardCopy> + </FormGroup> + {headerType && ( + <> + <TypeRefField + alternativeFieldName={"Input header type"} + isReadonly={true} + dmnEditorRootElementRef={dmnEditorRootElementRef} + typeRef={headerType.itemDefinition?.["@_name"] ?? headerType.typeRef} + /> + </> + )} + {headerType?.itemDefinition && ( + <> + <FormGroup label="Constraint"> + <ConstraintsFromTypeConstraintAttribute + isReadonly={true} + itemDefinition={headerType.itemDefinition} + editItemDefinition={() => {}} + renderOnPropertiesPanel={true} + defaultsToAllowedValues={true} + /> + </FormGroup> + </> + )} + <ExpressionLanguageField + isReadonly={props.isReadonly} + initialValue={cell["@_expressionLanguage"] ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newExpressionLanguage: string) => + updater((dmnObject) => { + dmnObject["@_expressionLanguage"] = newExpressionLanguage; + }) + } + /> + <DescriptionField + isReadonly={props.isReadonly} + initialValue={cell.description?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newDescription: string) => + updater((dmnObject) => { + dmnObject.description ??= { __$$text: "" }; + dmnObject.description.__$$text = newDescription; + }) + } + /> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableOutputHeaderCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableOutputHeaderCell.tsx new file mode 100644 index 00000000000..68a51490169 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableOutputHeaderCell.tsx @@ -0,0 +1,268 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useCallback, useMemo, useState } from "react"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { ContentField, DescriptionField, ExpressionLanguageField, NameField, TypeRefField } from "./Fields"; +import { FormGroup, FormSection } from "@patternfly/react-core/dist/js/components/Form"; +import { DMN15__tOutputClause } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { PropertiesPanelHeader } from "../PropertiesPanelHeader"; +import { BoxedDecisionTable, DmnBuiltInDataType } from "@kie-tools/boxed-expression-component/dist/api"; +import { useDmnEditor } from "../../DmnEditorContext"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { ClipboardCopy } from "@patternfly/react-core/dist/js/components/ClipboardCopy"; +import { ConstraintsFromTypeConstraintAttribute } from "../../dataTypes/Constraints"; +import { useDmnEditorStore, useDmnEditorStoreApi } from "../../store/StoreContext"; +import { useExternalModels } from "../../includedModels/DmnEditorDependenciesContext"; +import { State } from "../../store/Store"; + +export function DecisionTableOutputHeaderCell(props: { + boxedExpressionIndex?: BoxedExpressionIndex; + isReadonly: boolean; +}) { + const dmnEditorStoreApi = useDmnEditorStoreApi(); + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const { dmnEditorRootElementRef } = useDmnEditor(); + const { externalModelsByNamespace } = useExternalModels(); + + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const updater = useBoxedExpressionUpdater<DMN15__tOutputClause>(selectedObjectInfos?.expressionPath ?? []); + + const cell = useMemo(() => selectedObjectInfos?.cell as DMN15__tOutputClause, [selectedObjectInfos?.cell]); + const defaultOutputEntry = useMemo(() => cell.defaultOutputEntry, [cell.defaultOutputEntry]); + const outputValues = useMemo(() => cell.outputValues, [cell.outputValues]); + + const itemDefinition = useMemo(() => { + const { allDataTypesById, allTopLevelItemDefinitionUniqueNames } = dmnEditorStoreApi + .getState() + .computed(dmnEditorStoreApi.getState()) + .getDataTypes(externalModelsByNamespace); + return allDataTypesById.get(allTopLevelItemDefinitionUniqueNames.get(cell?.["@_typeRef"] ?? "") ?? "") + ?.itemDefinition; + }, [cell, dmnEditorStoreApi, externalModelsByNamespace]); + + const root = useMemo( + () => + props.boxedExpressionIndex?.get( + selectedObjectInfos?.expressionPath[selectedObjectInfos?.expressionPath.length - 1]?.root ?? "" + )?.cell as BoxedDecisionTable | undefined, + [props.boxedExpressionIndex, selectedObjectInfos?.expressionPath] + ); + + const [isDefaultOutputEntryExpanded, setDefaultOutputEntryExpanded] = useState(false); + const [isOutputValuesExpanded, setOutputValuesExpanded] = useState(false); + + const getAllUniqueNames = useCallback((s: State) => new Map(), []); + + const alternativeFieldName = useMemo(() => { + if (selectedObjectInfos?.expressionPath.length === 1) { + return "Decision"; + } + const parentType = selectedObjectInfos?.expressionPath[selectedObjectInfos?.expressionPath.length - 2].type; + switch (parentType) { + case "context": + return "Entry"; + case "functionDefinition": + return "Function"; + case "invocation": + return "Parameter"; + case "list": + return "Item"; + case "conditional": + case "every": + case "filter": + case "for": + case "some": + default: + return "Expression"; + } + }, [selectedObjectInfos?.expressionPath]); + + return ( + <> + <FormGroup label="ID"> + <ClipboardCopy isReadOnly={true} hoverTip="Copy" clickTip="Copied"> + {selectedObjectId} + </ClipboardCopy> + </FormGroup> + {root?.output.length === 1 && ( + <> + <NameField + alternativeFieldName={`${alternativeFieldName} Name`} + isReadonly={true} + id={root["@_id"]!} + name={root?.["@_label"] ?? ""} + getAllUniqueNames={getAllUniqueNames} + /> + <TypeRefField + alternativeFieldName={`${alternativeFieldName} Type`} + isReadonly={true} + dmnEditorRootElementRef={dmnEditorRootElementRef} + typeRef={root?.["@_typeRef"] ?? DmnBuiltInDataType.Undefined} + /> + </> + )} + <NameField + alternativeFieldName={root?.output.length === 1 ? "Column Name" : undefined} + isReadonly={props.isReadonly} + id={cell["@_id"]!} + name={cell?.["@_name"] ?? ""} + getAllUniqueNames={getAllUniqueNames} + onChange={(newName) => + updater((dmnObject) => { + dmnObject["@_name"] = newName; + }) + } + /> + <TypeRefField + alternativeFieldName={root?.output.length === 1 ? "Column Type" : undefined} + isReadonly={props.isReadonly} + dmnEditorRootElementRef={dmnEditorRootElementRef} + typeRef={cell?.["@_typeRef"] ?? DmnBuiltInDataType.Undefined} + onChange={(newTypeRef) => + updater((dmnObject) => { + dmnObject["@_typeRef"] = newTypeRef; + }) + } + /> + {itemDefinition && ( + <FormGroup label="Constraint"> + <ConstraintsFromTypeConstraintAttribute + isReadonly={true} + itemDefinition={itemDefinition} + editItemDefinition={() => {}} + renderOnPropertiesPanel={true} + defaultsToAllowedValues={true} + /> + </FormGroup> + )} + <DescriptionField + isReadonly={props.isReadonly} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + initialValue={cell?.description?.__$$text ?? ""} + onChange={(newDescription: string) => + updater((dmnObject) => { + dmnObject.description ??= { __$$text: "" }; + dmnObject.description.__$$text = newDescription; + }) + } + /> + <FormSection> + <PropertiesPanelHeader + expands={true} + fixed={false} + isSectionExpanded={isDefaultOutputEntryExpanded} + toogleSectionExpanded={() => setDefaultOutputEntryExpanded((prev) => !prev)} + title={"Default Output Entry"} + /> + {isDefaultOutputEntryExpanded && ( + <> + <ExpressionLanguageField + isReadonly={props.isReadonly} + initialValue={defaultOutputEntry?.["@_expressionLanguage"] ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newExpressionLanguage) => + updater((dmnObject) => { + dmnObject.defaultOutputEntry ??= {}; + dmnObject.defaultOutputEntry["@_expressionLanguage"] = newExpressionLanguage; + }) + } + /> + <ContentField + isReadonly={props.isReadonly} + initialValue={defaultOutputEntry?.text?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newText) => + updater((dmnObject) => { + dmnObject.defaultOutputEntry ??= { text: { __$$text: "" } }; + dmnObject.defaultOutputEntry.text ??= { __$$text: "" }; + dmnObject.defaultOutputEntry.text.__$$text = newText; + }) + } + /> + <DescriptionField + isReadonly={props.isReadonly} + initialValue={defaultOutputEntry?.description?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newDescription) => + updater((dmnObject) => { + dmnObject.defaultOutputEntry ??= { description: { __$$text: "" } }; + dmnObject.defaultOutputEntry.description ??= { __$$text: "" }; + dmnObject.defaultOutputEntry.description.__$$text = newDescription; + }) + } + /> + </> + )} + </FormSection> + <FormSection> + <PropertiesPanelHeader + expands={true} + fixed={false} + isSectionExpanded={isOutputValuesExpanded} + toogleSectionExpanded={() => setOutputValuesExpanded((prev) => !prev)} + title={"Output Values"} + /> + {isOutputValuesExpanded && ( + <> + <ExpressionLanguageField + isReadonly={props.isReadonly} + initialValue={outputValues?.["@_expressionLanguage"] ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newExpressionLanguage) => + updater((dmnObject) => { + dmnObject.outputValues ??= { text: { __$$text: "" } }; + dmnObject.outputValues["@_expressionLanguage"] = newExpressionLanguage; + }) + } + /> + <ContentField + isReadonly={props.isReadonly} + initialValue={outputValues?.text?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newText) => + updater((dmnObject) => { + dmnObject.outputValues ??= { text: { __$$text: "" } }; + dmnObject.outputValues.text.__$$text = newText; + }) + } + /> + <DescriptionField + isReadonly={props.isReadonly} + initialValue={outputValues?.description?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newDescription: string) => + updater((dmnObject) => { + dmnObject.outputValues ??= { text: { __$$text: "" } }; + dmnObject.outputValues.description ??= { __$$text: "" }; + dmnObject.outputValues.description.__$$text = newDescription; + }) + } + /> + </> + )} + </FormSection> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableOutputRuleCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableOutputRuleCell.tsx new file mode 100644 index 00000000000..069526dfde9 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableOutputRuleCell.tsx @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useMemo } from "react"; +import { DescriptionField, ExpressionLanguageField, TypeRefField } from "./Fields"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { + DMN15__tDecisionTable, + DMN15__tLiteralExpression, +} from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { ClipboardCopy } from "@patternfly/react-core/dist/js/components/ClipboardCopy"; +import { FormGroup } from "@patternfly/react-core/dist/js/components/Form"; +import { ConstraintsFromTypeConstraintAttribute } from "../../dataTypes/Constraints"; +import { DmnBuiltInDataType } from "@kie-tools/boxed-expression-component/dist/api"; +import { useDmnEditor } from "../../DmnEditorContext"; +import { useDmnEditorStore, useDmnEditorStoreApi } from "../../store/StoreContext"; +import { useExternalModels } from "../../includedModels/DmnEditorDependenciesContext"; + +export function DecisionTableOutputRuleCell(props: { + boxedExpressionIndex?: BoxedExpressionIndex; + isReadonly: boolean; +}) { + const dmnEditorStoreApi = useDmnEditorStoreApi(); + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const { externalModelsByNamespace } = useExternalModels(); + const { dmnEditorRootElementRef } = useDmnEditor(); + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const headerType = useMemo(() => { + const cellPath = selectedObjectInfos?.expressionPath[selectedObjectInfos?.expressionPath.length - 1]; + if (cellPath && cellPath.root) { + const root = props.boxedExpressionIndex?.get(cellPath.root); + const { allDataTypesById, allTopLevelItemDefinitionUniqueNames } = dmnEditorStoreApi + .getState() + .computed(dmnEditorStoreApi.getState()) + .getDataTypes(externalModelsByNamespace); + if ( + root?.expressionPath[root.expressionPath.length - 1]?.type === "decisionTable" && + cellPath.type === "decisionTable" + ) { + const typeRef = + allTopLevelItemDefinitionUniqueNames.get( + (root?.cell as DMN15__tDecisionTable)?.output?.[cellPath.column ?? 0]["@_typeRef"] ?? "" + ) ?? DmnBuiltInDataType.Undefined; + return { typeRef, itemDefinition: allDataTypesById.get(typeRef)?.itemDefinition }; + } + } + }, [dmnEditorStoreApi, externalModelsByNamespace, props.boxedExpressionIndex, selectedObjectInfos?.expressionPath]); + + const updater = useBoxedExpressionUpdater<DMN15__tLiteralExpression>(selectedObjectInfos?.expressionPath ?? []); + + const cell = useMemo(() => selectedObjectInfos?.cell as DMN15__tLiteralExpression, [selectedObjectInfos?.cell]); + + return ( + <> + <FormGroup label="ID"> + <ClipboardCopy isReadOnly={true} hoverTip="Copy" clickTip="Copied"> + {selectedObjectId} + </ClipboardCopy> + </FormGroup> + {headerType && ( + <> + <TypeRefField + alternativeFieldName={"Output header type"} + isReadonly={true} + dmnEditorRootElementRef={dmnEditorRootElementRef} + typeRef={headerType.itemDefinition?.["@_name"] ?? headerType.typeRef} + /> + </> + )} + {headerType?.itemDefinition && ( + <> + <FormGroup label="Constraint"> + <ConstraintsFromTypeConstraintAttribute + isReadonly={true} + itemDefinition={headerType.itemDefinition} + editItemDefinition={() => {}} + renderOnPropertiesPanel={true} + defaultsToAllowedValues={true} + /> + </FormGroup> + </> + )} + <ExpressionLanguageField + isReadonly={props.isReadonly} + initialValue={cell["@_expressionLanguage"] ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newExpressionLanguage: string) => + updater((dmnObject) => { + dmnObject["@_expressionLanguage"] = newExpressionLanguage; + }) + } + /> + <DescriptionField + isReadonly={props.isReadonly} + initialValue={cell.description?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newDescription: string) => + updater((dmnObject) => { + dmnObject.description ??= { __$$text: "" }; + dmnObject.description.__$$text = newDescription; + }) + } + /> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableRootCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableRootCell.tsx new file mode 100644 index 00000000000..906e6e7f0e8 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/DecisionTableRootCell.tsx @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useMemo } from "react"; +import { DescriptionField, TextField, TextFieldType } from "./Fields"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { DMN15__tDecisionTable } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { ClipboardCopy } from "@patternfly/react-core/dist/js/components/ClipboardCopy"; +import { FormGroup } from "@patternfly/react-core/dist/js/components/Form"; +import { useDmnEditorStore } from "../../store/StoreContext"; + +type DecisionTableRoot = Pick< + DMN15__tDecisionTable, + "@_label" | "description" | "@_typeRef" | "@_outputLabel" | "@_aggregation" | "@_hitPolicy" +>; + +export function DecisionTableRootCell(props: { boxedExpressionIndex?: BoxedExpressionIndex; isReadonly: boolean }) { + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const updater = useBoxedExpressionUpdater<DecisionTableRoot>(selectedObjectInfos?.expressionPath ?? []); + + const cell = useMemo(() => selectedObjectInfos?.cell as DecisionTableRoot, [selectedObjectInfos?.cell]); + + return ( + <> + <FormGroup label="ID"> + <ClipboardCopy isReadOnly={true} hoverTip="Copy" clickTip="Copied"> + {selectedObjectId} + </ClipboardCopy> + </FormGroup> + <TextField + type={TextFieldType.TEXT_INPUT} + title={"Hit Policy"} + isReadonly={true} + initialValue={cell["@_hitPolicy"] ?? ""} + /> + {cell["@_hitPolicy"] === "COLLECT" && ( + <TextField + type={TextFieldType.TEXT_INPUT} + title={"Aggregation"} + isReadonly={true} + initialValue={cell["@_aggregation"] ?? "<None>"} + /> + )} + <TextField + type={TextFieldType.TEXT_INPUT} + title={"Output Label"} + placeholder={"Enter a output label..."} + isReadonly={props.isReadonly} + initialValue={cell["@_outputLabel"] ?? ""} + onChange={(newOutputLabel: string) => + updater((dmnObject) => { + dmnObject["@_outputLabel"] = newOutputLabel; + }) + } + expressionPath={selectedObjectInfos?.expressionPath ?? []} + /> + <DescriptionField + isReadonly={props.isReadonly} + initialValue={cell.description?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newDescription: string) => + updater((dmnObject) => { + dmnObject.description ??= { __$$text: "" }; + dmnObject.description.__$$text = newDescription; + }) + } + /> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/ExpressionRootCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/ExpressionRootCell.tsx new file mode 100644 index 00000000000..5aeace5c2cc --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/ExpressionRootCell.tsx @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useMemo } from "react"; +import { DescriptionField } from "./Fields"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { AllExpressionsWithoutTypes } from "../../dataTypes/DataTypeSpec"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { ClipboardCopy } from "@patternfly/react-core/dist/js/components/ClipboardCopy"; +import { FormGroup } from "@patternfly/react-core/dist/js/components/Form"; +import { useDmnEditorStore } from "../../store/StoreContext"; + +type ExpressionRoot = Pick<AllExpressionsWithoutTypes, "description" | "@_typeRef">; + +export function ExpressionRootCell(props: { boxedExpressionIndex?: BoxedExpressionIndex; isReadonly: boolean }) { + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const updater = useBoxedExpressionUpdater<ExpressionRoot>(selectedObjectInfos?.expressionPath ?? []); + + const cell = useMemo(() => selectedObjectInfos?.cell as ExpressionRoot, [selectedObjectInfos?.cell]); + + return ( + <> + <FormGroup label="ID"> + <ClipboardCopy isReadOnly={true} hoverTip="Copy" clickTip="Copied"> + {selectedObjectId} + </ClipboardCopy> + </FormGroup> + <DescriptionField + isReadonly={props.isReadonly} + initialValue={cell.description?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newDescription: string) => + updater((dmnObject) => { + dmnObject.description ??= { __$$text: "" }; + dmnObject.description.__$$text = newDescription; + }) + } + /> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/Fields.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/Fields.tsx new file mode 100644 index 00000000000..f38004f7f21 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/Fields.tsx @@ -0,0 +1,208 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useEffect, useState } from "react"; +import { FormGroup } from "@patternfly/react-core/dist/js/components/Form"; +import { InlineFeelNameInput } from "../../feel/InlineFeelNameInput"; +import { TextArea } from "@patternfly/react-core/dist/js/components/TextArea"; +import { ExpressionPath } from "../../boxedExpressions/boxedExpressionIndex"; +import { TextInput } from "@patternfly/react-core/dist/js/components/TextInput"; +import { TypeRefSelector } from "../../dataTypes/TypeRefSelector"; +import { UniqueNameIndex } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/Dmn15Spec"; +import { State } from "../../store/Store"; + +export function ContentField(props: { + initialValue: string; + onChange: (newTextValue: string, expressionPath: ExpressionPath[]) => void; + expressionPath: ExpressionPath[]; + isReadonly: boolean; +}) { + return <TextField {...props} type={TextFieldType.TEXT_AREA} title="Content" placeholder="Enter the content..." />; +} + +export function DescriptionField(props: { + initialValue: string; + onChange: (newTextValue: string, expressionPath: ExpressionPath[]) => void; + expressionPath: ExpressionPath[]; + isReadonly: boolean; +}) { + return ( + <TextField {...props} type={TextFieldType.TEXT_AREA} title="Description" placeholder="Enter a description..." /> + ); +} + +export function ExpressionLanguageField(props: { + initialValue: string; + onChange?: (newTextValue: string, expressionPath?: ExpressionPath[]) => void; + expressionPath?: ExpressionPath[]; + isReadonly: boolean; +}) { + return ( + <TextField + {...props} + type={TextFieldType.TEXT_INPUT} + title="Expression Language" + placeholder="Enter the expression language..." + /> + ); +} + +export function NameField(props: { + alternativeFieldName?: string; + id: string; + name: string; + isReadonly: boolean; + getAllUniqueNames: (s: State) => UniqueNameIndex; + onChange?: (newName: string) => void; +}) { + return ( + <FormGroup label={props.alternativeFieldName ? props.alternativeFieldName : "Name"}> + <InlineFeelNameInput + enableAutoFocusing={false} + isPlain={false} + id={props.id} + name={props.name} + isReadonly={props.isReadonly} + shouldCommitOnBlur={true} + className={"pf-c-form-control"} + onRenamed={(newName) => props.onChange?.(newName)} + allUniqueNames={props.getAllUniqueNames} + /> + </FormGroup> + ); +} + +export function TypeRefField(props: { + alternativeFieldName?: string; + typeRef: string; + isReadonly: boolean; + dmnEditorRootElementRef: React.RefObject<HTMLElement>; + onChange?: (newTypeRef: string) => void; +}) { + return ( + <FormGroup label={props.alternativeFieldName ? props.alternativeFieldName : "Type"}> + <TypeRefSelector + heightRef={props.dmnEditorRootElementRef} + typeRef={props.typeRef} + isDisabled={props.isReadonly} + onChange={(newValue: string) => props.onChange?.(newValue)} + /> + </FormGroup> + ); +} + +export enum TextFieldType { + TEXT_AREA = "text-area", + TEXT_INPUT = "text-input", +} + +export function TextField({ + onChange, + ...props +}: { + initialValue: string; + onChange?: (newTextValue: string, expressionPath?: ExpressionPath[]) => void; + expressionPath?: ExpressionPath[]; + isReadonly: boolean; + title: string; + placeholder?: string; + type: TextFieldType; +}) { + // used to save the expression path value until the flush operation + const [expressionPath, setExpressionPath] = useState(props.expressionPath); + const [value, setValue] = useState(props.initialValue); + + // Uses refs to prevent `useEffect` to run multiple times + const valueRef = React.useRef(props.initialValue); + const isEditing = React.useRef(false); + + // Updates the value and expression path with the props value + useEffect(() => { + if (isEditing.current === false) { + setValue(props.initialValue); + setExpressionPath(props.expressionPath); + valueRef.current = props.initialValue; + } + }, [props.initialValue, props.expressionPath]); + + // Handle special case where the component is umounted and the onBlur is not called + useEffect(() => { + return () => { + if (isEditing.current === true) { + if (props.initialValue === valueRef.current) { + return; + } + onChange?.(valueRef.current, expressionPath); + isEditing.current = false; + } + }; + }, [expressionPath, onChange, props.initialValue]); + + return ( + <FormGroup label={props.title}> + {props.type === TextFieldType.TEXT_AREA && ( + <TextArea + aria-label={"Content"} + type={"text"} + isDisabled={props.isReadonly} + value={value} + onChange={(newContent) => { + setValue(newContent); + valueRef.current = newContent; + isEditing.current = true; + }} + onBlur={() => { + if (props.initialValue === value) { + return; + } + onChange?.(value, expressionPath); + isEditing.current = false; + }} + placeholder={props.placeholder ?? "Enter the expression content..."} + style={{ resize: "vertical", minHeight: "40px" }} + rows={6} + /> + )} + {props.type === TextFieldType.TEXT_INPUT && ( + <TextInput + aria-label={"Content"} + type={"text"} + isDisabled={props.isReadonly} + value={value} + onChange={(newContent) => { + setValue(newContent); + valueRef.current = newContent; + isEditing.current = true; + }} + onBlur={() => { + if (props.initialValue === value) { + return; + } + onChange?.(value, expressionPath); + isEditing.current = false; + }} + placeholder={props.placeholder ?? "Enter the expression content..."} + style={{ resize: "vertical", minHeight: "40px" }} + rows={6} + /> + )} + </FormGroup> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/FunctionDefinitionParametersCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/FunctionDefinitionParametersCell.tsx new file mode 100644 index 00000000000..f1c66238126 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/FunctionDefinitionParametersCell.tsx @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useCallback, useMemo, useState } from "react"; +import { DescriptionField, NameField, TypeRefField } from "./Fields"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { DmnBuiltInDataType } from "@kie-tools/boxed-expression-component/dist/api"; +import { useDmnEditor } from "../../DmnEditorContext"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { ClipboardCopy } from "@patternfly/react-core/dist/js/components/ClipboardCopy"; +import { FormGroup, FormSection } from "@patternfly/react-core/dist/js/components/Form"; +import { + DMN15__tFunctionDefinition, + DMN15__tInformationItem, +} from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { PropertiesPanelHeader } from "../PropertiesPanelHeader"; +import { Text } from "@patternfly/react-core/dist/js/components/Text"; +import { ConstraintsFromTypeConstraintAttribute } from "../../dataTypes/Constraints"; +import { useDmnEditorStore, useDmnEditorStoreApi } from "../../store/StoreContext"; +import { useExternalModels } from "../../includedModels/DmnEditorDependenciesContext"; +import { State } from "../../store/Store"; + +export function FunctionDefinitionParameterCell(props: { + boxedExpressionIndex?: BoxedExpressionIndex; + isReadonly: boolean; +}) { + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const updater = useBoxedExpressionUpdater<DMN15__tFunctionDefinition>(selectedObjectInfos?.expressionPath ?? []); + + const cell = useMemo(() => selectedObjectInfos?.cell as DMN15__tInformationItem[], [selectedObjectInfos?.cell]); + const [isParameterExpanded, setParameterExpaded] = useState<boolean[]>([]); + + const getAllUniqueNames = useCallback((s: State) => new Map(), []); + + return ( + <> + <FormGroup label="ID"> + <ClipboardCopy isReadOnly={true} hoverTip="Copy" clickTip="Copied"> + {selectedObjectId} + </ClipboardCopy> + </FormGroup> + {cell.length === 0 && ( + <> + <Text>{"Empty parameters list"}</Text> + </> + )} + {cell.map((parameter, i) => ( + <FormSection key={i}> + <PropertiesPanelHeader + expands={true} + fixed={false} + isSectionExpanded={isParameterExpanded[i] ?? false} + toogleSectionExpanded={() => + setParameterExpaded((prev) => { + const newExpanded = [...prev]; + newExpanded[i] = !(newExpanded[i] ?? false); + return newExpanded; + }) + } + title={ + <p> + Parameter <b>{parameter["@_name"]}</b> + </p> + } + /> + {isParameterExpanded[i] && ( + <> + <NameField + isReadonly={props.isReadonly} + id={parameter["@_id"]!} + name={parameter["@_name"] ?? ""} + getAllUniqueNames={getAllUniqueNames} + onChange={(newName: string) => { + updater((dmnObject) => { + dmnObject.formalParameter ??= []; + dmnObject.formalParameter[i] ??= { "@_name": "" }; + dmnObject.formalParameter[i]["@_name"] = newName; + }); + }} + /> + <FunctionDefinitionParameterTypeRef + parameter={parameter} + isReadonly={props.isReadonly} + onTypeRefChange={(newTypeRef) => + updater((dmnObject) => { + dmnObject.formalParameter ??= []; + dmnObject.formalParameter[i] ??= { "@_name": "" }; + dmnObject.formalParameter[i]["@_typeRef"] = newTypeRef; + }) + } + /> + <DescriptionField + isReadonly={props.isReadonly} + initialValue={parameter.description?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newDescription: string) => { + updater((dmnObject) => { + dmnObject.formalParameter ??= []; + dmnObject.formalParameter[i] ??= { "@_name": "", description: { __$$text: "" } }; + dmnObject.formalParameter[i].description ??= { __$$text: "" }; + dmnObject.formalParameter[i].description!.__$$text = newDescription; + }); + }} + /> + </> + )} + </FormSection> + ))} + </> + ); +} + +function FunctionDefinitionParameterTypeRef(props: { + parameter: DMN15__tInformationItem; + isReadonly: boolean; + onTypeRefChange: (newTypeRef: string) => void; +}) { + const dmnEditorStoreApi = useDmnEditorStoreApi(); + const { externalModelsByNamespace } = useExternalModels(); + const { dmnEditorRootElementRef } = useDmnEditor(); + + const itemDefinition = useMemo(() => { + const { allDataTypesById, allTopLevelItemDefinitionUniqueNames } = dmnEditorStoreApi + .getState() + .computed(dmnEditorStoreApi.getState()) + .getDataTypes(externalModelsByNamespace); + return allDataTypesById.get(allTopLevelItemDefinitionUniqueNames.get(props.parameter?.["@_typeRef"] ?? "") ?? "") + ?.itemDefinition; + }, [dmnEditorStoreApi, externalModelsByNamespace, props.parameter]); + + return ( + <> + <TypeRefField + isReadonly={props.isReadonly} + dmnEditorRootElementRef={dmnEditorRootElementRef} + typeRef={props.parameter["@_typeRef"] ?? DmnBuiltInDataType.Undefined} + onChange={props.onTypeRefChange} + /> + {itemDefinition && ( + <FormGroup label="Constraint"> + <ConstraintsFromTypeConstraintAttribute + isReadonly={true} + itemDefinition={itemDefinition} + editItemDefinition={() => {}} + renderOnPropertiesPanel={true} + defaultsToAllowedValues={true} + /> + </FormGroup> + )} + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/FunctionDefinitionRootCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/FunctionDefinitionRootCell.tsx new file mode 100644 index 00000000000..b86bf3f2f69 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/FunctionDefinitionRootCell.tsx @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useMemo } from "react"; +import { DescriptionField, TextField, TextFieldType } from "./Fields"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { ClipboardCopy } from "@patternfly/react-core/dist/js/components/ClipboardCopy"; +import { FormGroup } from "@patternfly/react-core/dist/js/components/Form"; +import { DMN15__tFunctionDefinition } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { useDmnEditorStore } from "../../store/StoreContext"; + +type FunctionDefinitionRoot = Pick<DMN15__tFunctionDefinition, "@_kind" | "@_typeRef" | "description">; + +export function FunctionDefinitionRootCell(props: { + boxedExpressionIndex?: BoxedExpressionIndex; + isReadonly: boolean; +}) { + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const updater = useBoxedExpressionUpdater<FunctionDefinitionRoot>(selectedObjectInfos?.expressionPath ?? []); + + const cell = useMemo(() => selectedObjectInfos?.cell as FunctionDefinitionRoot, [selectedObjectInfos?.cell]); + + return ( + <> + <FormGroup label="ID"> + <ClipboardCopy isReadOnly={true} hoverTip="Copy" clickTip="Copied"> + {selectedObjectId} + </ClipboardCopy> + </FormGroup> + <TextField type={TextFieldType.TEXT_INPUT} title={"Kind"} isReadonly={true} initialValue={cell["@_kind"] ?? ""} /> + <DescriptionField + isReadonly={props.isReadonly} + initialValue={cell.description?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newDescription: string) => + updater((dmnObject) => { + dmnObject.description ??= { __$$text: "" }; + dmnObject.description.__$$text = newDescription; + }) + } + /> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/InformationItemCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/InformationItemCell.tsx new file mode 100644 index 00000000000..8cc221a2232 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/InformationItemCell.tsx @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useCallback, useMemo } from "react"; +import { DescriptionField, NameField, TypeRefField } from "./Fields"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { DMN15__tInformationItem } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { useDmnEditorStore, useDmnEditorStoreApi } from "../../store/StoreContext"; +import { ClipboardCopy } from "@patternfly/react-core/dist/js/components/ClipboardCopy"; +import { FormGroup } from "@patternfly/react-core/dist/js/components/Form"; +import { DmnBuiltInDataType } from "@kie-tools/boxed-expression-component/dist/api"; +import { useDmnEditor } from "../../DmnEditorContext"; +import { Constraints, ConstraintsFromTypeConstraintAttribute } from "../../dataTypes/Constraints"; +import { useExternalModels } from "../../includedModels/DmnEditorDependenciesContext"; +import { State } from "../../store/Store"; + +export function InformationItemCell(props: { + boxedExpressionIndex?: BoxedExpressionIndex; + isReadonly: boolean; + onNameChange: (newName: string) => void; + onTypeRefChange: (newTypeRef: string) => void; + onDescriptionChange: (newDescription: string) => void; +}) { + const dmnEditorStoreApi = useDmnEditorStoreApi(); + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const { externalModelsByNamespace } = useExternalModels(); + const { dmnEditorRootElementRef } = useDmnEditor(); + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const cell = useMemo(() => selectedObjectInfos?.cell as DMN15__tInformationItem, [selectedObjectInfos?.cell]); + + const itemDefinition = useMemo(() => { + const { allDataTypesById, allTopLevelItemDefinitionUniqueNames } = dmnEditorStoreApi + .getState() + .computed(dmnEditorStoreApi.getState()) + .getDataTypes(externalModelsByNamespace); + return allDataTypesById.get(allTopLevelItemDefinitionUniqueNames.get(cell?.["@_typeRef"] ?? "") ?? "") + ?.itemDefinition; + }, [cell, dmnEditorStoreApi, externalModelsByNamespace]); + + const getAllUniqueNames = useCallback((s: State) => new Map(), []); + + return ( + <> + <FormGroup label="ID"> + <ClipboardCopy isReadOnly={true} hoverTip="Copy" clickTip="Copied"> + {selectedObjectId} + </ClipboardCopy> + </FormGroup> + <NameField + isReadonly={props.isReadonly} + id={cell["@_id"]!} + name={cell["@_name"] ?? ""} + getAllUniqueNames={getAllUniqueNames} + onChange={props.onNameChange} + /> + <TypeRefField + isReadonly={props.isReadonly} + typeRef={cell["@_typeRef"] ?? DmnBuiltInDataType.Undefined} + dmnEditorRootElementRef={dmnEditorRootElementRef} + onChange={props.onTypeRefChange} + /> + {itemDefinition && ( + <FormGroup label="Constraint"> + <ConstraintsFromTypeConstraintAttribute + isReadonly={true} + itemDefinition={itemDefinition} + editItemDefinition={() => {}} + renderOnPropertiesPanel={true} + defaultsToAllowedValues={true} + /> + </FormGroup> + )} + <DescriptionField + isReadonly={props.isReadonly} + initialValue={cell.description?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={props.onDescriptionChange} + /> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/InvocationFunctionCallCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/InvocationFunctionCallCell.tsx new file mode 100644 index 00000000000..736e4f4ba4d --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/InvocationFunctionCallCell.tsx @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useMemo } from "react"; +import { TextField, TextFieldType } from "./Fields"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { useDmnEditorStore } from "../../store/StoreContext"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { DMN15__tLiteralExpression } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; + +export function InvocationFunctionCallCell(props: { + boxedExpressionIndex?: BoxedExpressionIndex; + isReadonly: boolean; +}) { + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const updater = useBoxedExpressionUpdater<DMN15__tLiteralExpression>(selectedObjectInfos?.expressionPath ?? []); + + const cell = useMemo(() => selectedObjectInfos?.cell as DMN15__tLiteralExpression, [selectedObjectInfos?.cell]); + + return ( + <> + <TextField + type={TextFieldType.TEXT_INPUT} + title={"Function to be called"} + placeholder="Enter the function name..." + isReadonly={props.isReadonly} + initialValue={cell.text?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newDescription: string) => + updater((dmnObject) => { + dmnObject.text = { __$$text: newDescription }; + }) + } + /> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/InvocationInformationItemCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/InvocationInformationItemCell.tsx new file mode 100644 index 00000000000..66aeacb05a5 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/InvocationInformationItemCell.tsx @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useMemo } from "react"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { + DMN15__tInformationItem, + DMN15__tInvocation, +} from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { useDmnEditorStore } from "../../store/StoreContext"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { InformationItemCell } from "./InformationItemCell"; + +export function InvocationInformationItemCell(props: { + boxedExpressionIndex?: BoxedExpressionIndex; + isReadonly: boolean; +}) { + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const cellPath = useMemo( + () => selectedObjectInfos?.expressionPath[selectedObjectInfos?.expressionPath.length - 1], + [selectedObjectInfos?.expressionPath] + ); + const rootPath = useMemo( + () => props.boxedExpressionIndex?.get(cellPath?.root ?? "")?.expressionPath, + [cellPath?.root, props.boxedExpressionIndex] + ); + + const updater = useBoxedExpressionUpdater<DMN15__tInformationItem>(selectedObjectInfos?.expressionPath ?? []); + const rootExpressionUpdater = useBoxedExpressionUpdater<DMN15__tInvocation>(rootPath ?? []); + + return ( + <> + <InformationItemCell + {...props} + onDescriptionChange={(newDescription) => { + updater((dmnObject) => { + dmnObject.description ??= { __$$text: "" }; + dmnObject.description.__$$text = newDescription; + }); + }} + onNameChange={(newName) => { + updater((dmnObject) => { + dmnObject["@_name"] = newName; + }); + }} + onTypeRefChange={(newTypeRef) => { + updater((dmnObject) => { + dmnObject["@_typeRef"] = newTypeRef; + }); + rootExpressionUpdater((dmnObject) => { + if (cellPath?.type === "invocation") { + const expression = (dmnObject as DMN15__tInvocation).binding![cellPath.row ?? 0].expression; + if (expression) { + expression["@_typeRef"] = newTypeRef; + } + } + }); + }} + /> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/IteratorVariableCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/IteratorVariableCell.tsx new file mode 100644 index 00000000000..2860e49cce5 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/IteratorVariableCell.tsx @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useMemo } from "react"; +import { TextField, TextFieldType } from "./Fields"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { useDmnEditorStore } from "../../store/StoreContext"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { DMN15__tIterator } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; + +export function IteratorVariableCell(props: { boxedExpressionIndex?: BoxedExpressionIndex; isReadonly: boolean }) { + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const updater = useBoxedExpressionUpdater<DMN15__tIterator>(selectedObjectInfos?.expressionPath ?? []); + + const cell = useMemo(() => selectedObjectInfos?.cell as DMN15__tIterator, [selectedObjectInfos?.cell]); + + return ( + <> + <TextField + type={TextFieldType.TEXT_INPUT} + title={"Variable to interate over"} + placeholder="Enter the variable name..." + isReadonly={props.isReadonly} + initialValue={cell["@_iteratorVariable"] ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newVariable: string) => + updater((dmnObject) => { + dmnObject["@_iteratorVariable"] = newVariable; + }) + } + /> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/LiteralExpressionContentCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/LiteralExpressionContentCell.tsx new file mode 100644 index 00000000000..4dd5ba09a72 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/LiteralExpressionContentCell.tsx @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useMemo } from "react"; +import { DescriptionField, ExpressionLanguageField } from "./Fields"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { DMN15__tLiteralExpression } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { useDmnEditorStore } from "../../store/StoreContext"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { ClipboardCopy } from "@patternfly/react-core/dist/js/components/ClipboardCopy"; +import { FormGroup } from "@patternfly/react-core/dist/js/components/Form"; + +export function LiteralExpressionContentCell(props: { + boxedExpressionIndex?: BoxedExpressionIndex; + isReadonly: boolean; +}) { + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const updater = useBoxedExpressionUpdater<DMN15__tLiteralExpression>(selectedObjectInfos?.expressionPath ?? []); + + const cell = useMemo(() => selectedObjectInfos?.cell as DMN15__tLiteralExpression, [selectedObjectInfos?.cell]); + + return ( + <> + <FormGroup label="ID"> + <ClipboardCopy isReadOnly={true} hoverTip="Copy" clickTip="Copied"> + {selectedObjectId} + </ClipboardCopy> + </FormGroup> + <ExpressionLanguageField + isReadonly={props.isReadonly} + initialValue={cell["@_expressionLanguage"] ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newExpressionLanguage: string) => + updater((dmnObject) => { + dmnObject["@_expressionLanguage"] = newExpressionLanguage; + }) + } + /> + <DescriptionField + isReadonly={props.isReadonly} + initialValue={cell.description?.__$$text ?? ""} + expressionPath={selectedObjectInfos?.expressionPath ?? []} + onChange={(newDescription: string) => + updater((dmnObject) => { + dmnObject.description ??= { __$$text: "" }; + dmnObject.description.__$$text = newDescription; + }) + } + /> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/RelationInformationItemCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/RelationInformationItemCell.tsx new file mode 100644 index 00000000000..de835fb77d9 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/RelationInformationItemCell.tsx @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useMemo } from "react"; +import { BoxedExpressionIndex } from "../../boxedExpressions/boxedExpressionIndex"; +import { DMN15__tInformationItem } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { useDmnEditorStore } from "../../store/StoreContext"; +import { useBoxedExpressionUpdater } from "./useBoxedExpressionUpdater"; +import { InformationItemCell } from "./InformationItemCell"; + +export function RelationInformationItemCell(props: { + boxedExpressionIndex?: BoxedExpressionIndex; + isReadonly: boolean; +}) { + const selectedObjectId = useDmnEditorStore((s) => s.boxedExpressionEditor.selectedObjectId); + const selectedObjectInfos = useMemo( + () => props.boxedExpressionIndex?.get(selectedObjectId ?? ""), + [props.boxedExpressionIndex, selectedObjectId] + ); + + const updater = useBoxedExpressionUpdater<DMN15__tInformationItem>(selectedObjectInfos?.expressionPath ?? []); + + return ( + <> + <InformationItemCell + {...props} + onDescriptionChange={(newDescription) => { + updater((dmnObject) => { + dmnObject.description ??= { __$$text: "" }; + dmnObject.description.__$$text = newDescription; + }); + }} + onNameChange={(newName) => { + updater((dmnObject) => { + dmnObject["@_name"] = newName; + }); + }} + onTypeRefChange={(newTypeRef) => { + updater((dmnObject) => { + dmnObject["@_typeRef"] = newTypeRef; + }); + }} + /> + </> + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/SelectExpressionCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/SelectExpressionCell.tsx new file mode 100644 index 00000000000..0222333893d --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/SelectExpressionCell.tsx @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { Text } from "@patternfly/react-core/dist/js/components/Text"; +import { Title } from "@patternfly/react-core/dist/js/components/Title"; +import { FormGroup } from "@patternfly/react-core/dist/js/components/Form"; +import { ClipboardCopy } from "@patternfly/react-core/dist/js/components/ClipboardCopy"; + +export function SelectExpressionCell(props: { selectedObjectId: string }) { + return ( + <> + <Title headingLevel={"h2"}>{"Select expression"} + + + {props.selectedObjectId} + + + {"The selected cell still doesn't have an expresison associate with it."} + + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/WithoutPropertiesCell.tsx b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/WithoutPropertiesCell.tsx new file mode 100644 index 00000000000..7eb59a9027f --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/WithoutPropertiesCell.tsx @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { Text, TextContent } from "@patternfly/react-core/dist/js/components/Text"; +import { EmptyState, EmptyStateIcon } from "@patternfly/react-core/dist/js/components/EmptyState"; +import CubeIcon from "@patternfly/react-icons/dist/js/icons/cube-icon"; + +export function WithoutPropertiesCell() { + return ( + <> + + + + No properties to display + + + + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/getBoxedExpressionPropertiesPanelComponent.ts b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/getBoxedExpressionPropertiesPanelComponent.ts new file mode 100644 index 00000000000..4be9404d0f4 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/getBoxedExpressionPropertiesPanelComponent.ts @@ -0,0 +1,200 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ExpressionPath } from "../../boxedExpressions/boxedExpressionIndex"; + +export enum BoxedExpressionPropertiesPanelComponent { + CONTEXT_INFORMATION_ITEM_CELL = "context-information-item-cell", + DECISION_TABLE_INPUT_HEADER = "decision-table-input-header", + DECISION_TABLE_INPUT_RULE = "decision-table-input-rule", + DECISION_TABLE_OUTPUT_HEADER = "decision-table-output-header", + DECISION_TABLE_OUTPUT_RULE = "decision-table-output-rule", + DECISION_TABLE_ROOT = "decision-table-root", + EXPRESSION_ROOT = "expression-root", + FUNCTION_DEFINITION_PARAMETERS = "function-definition-parameters", + FUNCTION_DEFINITION_ROOT = "function-definition-root", + INVOCATION_FUNCTION_CALL = "invocation-function-call", + INVOCATION_INFORMATION_ITEM_CELL = "invocation-information-item-cell", + ITERATOR_VARIABLE_CELL = "iterator-variable-cell", + LITERAL_EXPRESSION_CONTENT = "literal-expression-content", + RELATION_INFORMATION_ITEM_CELL = "relation-information-item-cell", + WITHOUT_PROPERTIES_CELL = "without-properties-cell", +} + +export function getBoxedExpressionPropertiesPanelComponent(selectedObjectPath: ExpressionPath): { + component: BoxedExpressionPropertiesPanelComponent; + title: string; +} { + if (selectedObjectPath.type === "conditional") { + if (selectedObjectPath.row === undefined) { + return { component: BoxedExpressionPropertiesPanelComponent.EXPRESSION_ROOT, title: "Boxed Conditional" }; + } + } + + if (selectedObjectPath.type === "context") { + if (selectedObjectPath.column === undefined) { + return { component: BoxedExpressionPropertiesPanelComponent.EXPRESSION_ROOT, title: "Boxed Context" }; + } + if (selectedObjectPath.column === "variable") { + return { + component: BoxedExpressionPropertiesPanelComponent.CONTEXT_INFORMATION_ITEM_CELL, + title: "Boxed Context Variable", + }; + } + } + + if (selectedObjectPath.type === "decisionTable") { + if (selectedObjectPath.row === undefined) { + return { component: BoxedExpressionPropertiesPanelComponent.DECISION_TABLE_ROOT, title: "Decision Table" }; + } + if (selectedObjectPath.header === "input") { + if (selectedObjectPath.row < 0) { + return { + component: BoxedExpressionPropertiesPanelComponent.DECISION_TABLE_INPUT_HEADER, + title: "Decision Table Input Header", + }; + } + return { + component: BoxedExpressionPropertiesPanelComponent.DECISION_TABLE_INPUT_RULE, + title: "Decision Table Input Cell", + }; + } + if (selectedObjectPath.header === "output") { + if (selectedObjectPath.row < 0) { + return { + component: BoxedExpressionPropertiesPanelComponent.DECISION_TABLE_OUTPUT_HEADER, + title: "Decision Table Output Header", + }; + } + return { + component: BoxedExpressionPropertiesPanelComponent.DECISION_TABLE_OUTPUT_RULE, + title: "Decision Table Output Cell", + }; + } + } + + if (selectedObjectPath.type === "every") { + if (selectedObjectPath.row === undefined) { + return { component: BoxedExpressionPropertiesPanelComponent.EXPRESSION_ROOT, title: "Boxed Every" }; + } + if (selectedObjectPath.row === "variable") { + return { + component: BoxedExpressionPropertiesPanelComponent.ITERATOR_VARIABLE_CELL, + title: "Boxed Every Variable", + }; + } + } + + if (selectedObjectPath.type === "filter") { + if (selectedObjectPath.row === undefined) { + return { component: BoxedExpressionPropertiesPanelComponent.EXPRESSION_ROOT, title: "Boxed Filter" }; + } + } + + if (selectedObjectPath.type === "for") { + if (selectedObjectPath.row === undefined) { + return { component: BoxedExpressionPropertiesPanelComponent.EXPRESSION_ROOT, title: "Boxed For" }; + } + if (selectedObjectPath.row === "variable") { + return { component: BoxedExpressionPropertiesPanelComponent.ITERATOR_VARIABLE_CELL, title: "Boxed For Variable" }; + } + } + + if (selectedObjectPath.type === "functionDefinition") { + if (selectedObjectPath.parameterIndex === undefined) { + return { + component: BoxedExpressionPropertiesPanelComponent.FUNCTION_DEFINITION_ROOT, + title: "Function Definition", + }; + } + return { + component: BoxedExpressionPropertiesPanelComponent.FUNCTION_DEFINITION_PARAMETERS, + title: "Function Parameters", + }; + } + + if (selectedObjectPath.type === "invocation") { + if (selectedObjectPath.row === undefined || selectedObjectPath.column === undefined) { + return { + component: BoxedExpressionPropertiesPanelComponent.EXPRESSION_ROOT, + title: "Boxed Invocation", + }; + } + if (selectedObjectPath.row < 0) { + return { + component: BoxedExpressionPropertiesPanelComponent.INVOCATION_FUNCTION_CALL, + title: "Boxed Invocation Called Function", + }; + } + if (selectedObjectPath.column === "parameter") { + return { + component: BoxedExpressionPropertiesPanelComponent.INVOCATION_INFORMATION_ITEM_CELL, + title: "Boxed Invocation Parameter", + }; + } + if (selectedObjectPath.column === "expression") { + return { + component: BoxedExpressionPropertiesPanelComponent.LITERAL_EXPRESSION_CONTENT, + title: "Boxed Invocation", + }; + } + } + + if (selectedObjectPath.type === "list") { + if (selectedObjectPath.row === undefined) { + return { component: BoxedExpressionPropertiesPanelComponent.EXPRESSION_ROOT, title: "Boxed List" }; + } + } + + if (selectedObjectPath.type === "literalExpression") { + return { + component: BoxedExpressionPropertiesPanelComponent.LITERAL_EXPRESSION_CONTENT, + title: "Literal Expression", + }; + } + + if (selectedObjectPath.type === "relation") { + if (selectedObjectPath.row === undefined) { + return { component: BoxedExpressionPropertiesPanelComponent.EXPRESSION_ROOT, title: "Boxed Relation" }; + } + if (selectedObjectPath.row < 0) { + return { + component: BoxedExpressionPropertiesPanelComponent.RELATION_INFORMATION_ITEM_CELL, + title: "Boxed Relation Header", + }; + } + return { + component: BoxedExpressionPropertiesPanelComponent.LITERAL_EXPRESSION_CONTENT, + title: "Boxed Relation Cell", + }; + } + + if (selectedObjectPath.type === "some") { + if (selectedObjectPath.row === undefined) { + return { component: BoxedExpressionPropertiesPanelComponent.EXPRESSION_ROOT, title: "Boxed Some" }; + } + if (selectedObjectPath.row === "variable") { + return { + component: BoxedExpressionPropertiesPanelComponent.ITERATOR_VARIABLE_CELL, + title: "Boxed Some Variable", + }; + } + } + return { component: BoxedExpressionPropertiesPanelComponent.WITHOUT_PROPERTIES_CELL, title: "" }; +} diff --git a/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/useBoxedExpressionUpdater.ts b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/useBoxedExpressionUpdater.ts new file mode 100644 index 00000000000..bd12efde335 --- /dev/null +++ b/packages/dmn-editor/src/propertiesPanel/BoxedExpressionPropertiesPanelComponents/useBoxedExpressionUpdater.ts @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { useCallback, useMemo } from "react"; +import { ExpressionPath, getDmnObjectByPath } from "../../boxedExpressions/boxedExpressionIndex"; +import { + DMN15__tBusinessKnowledgeModel, + DMN15__tDecision, +} from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; +import { useDmnEditorStore, useDmnEditorStoreApi } from "../../store/StoreContext"; +import { buildXmlHref } from "../../xml/xmlHrefs"; +import { AllExpressionsWithoutTypes } from "../../dataTypes/DataTypeSpec"; +import { useExternalModels } from "../../includedModels/DmnEditorDependenciesContext"; + +export function useBoxedExpressionUpdater( + expressionPath: ExpressionPath[] | undefined +) { + const dmnEditorStoreApi = useDmnEditorStoreApi(); + const activeDrgElementId = useDmnEditorStore((s) => s.boxedExpressionEditor.activeDrgElementId); + const { externalModelsByNamespace } = useExternalModels(); + + const node = useMemo(() => { + const nodesById = dmnEditorStoreApi + .getState() + .computed(dmnEditorStoreApi.getState()) + .getDiagramData(externalModelsByNamespace).nodesById; + return activeDrgElementId ? nodesById.get(buildXmlHref({ id: activeDrgElementId })) : undefined; + }, [activeDrgElementId, dmnEditorStoreApi, externalModelsByNamespace]); + + return useCallback( + (consumer: (dmnObject: T) => void) => { + dmnEditorStoreApi.setState((state) => { + if (state.dmn.model.definitions.drgElement?.[node?.data.index ?? 0]?.__$$element === "businessKnowledgeModel") { + const dmnObject = getDmnObjectByPath( + expressionPath ?? [], + (state.dmn.model.definitions.drgElement?.[node?.data.index ?? 0] as DMN15__tBusinessKnowledgeModel) + ?.encapsulatedLogic + ); + dmnObject && consumer(dmnObject as T); + } + if (state.dmn.model.definitions.drgElement?.[node?.data.index ?? 0]?.__$$element === "decision") { + const dmnObject = getDmnObjectByPath( + expressionPath ?? [], + (state.dmn.model.definitions.drgElement?.[node?.data.index ?? 0] as DMN15__tDecision)?.expression + ); + dmnObject && consumer(dmnObject as T); + } + }); + }, + [dmnEditorStoreApi, expressionPath, node?.data.index] + ); +} diff --git a/packages/dmn-editor/src/propertiesPanel/DecisionProperties.tsx b/packages/dmn-editor/src/propertiesPanel/DecisionProperties.tsx index 4a571eb9cb0..a51e9d40ed9 100644 --- a/packages/dmn-editor/src/propertiesPanel/DecisionProperties.tsx +++ b/packages/dmn-editor/src/propertiesPanel/DecisionProperties.tsx @@ -77,6 +77,7 @@ export function DecisionProperties({ { setState((state) => { const drgElement = state.dmn.model.definitions.drgElement![index] as DMN15__tDecision; diff --git a/packages/dmn-editor/src/propertiesPanel/DecisionServiceProperties.tsx b/packages/dmn-editor/src/propertiesPanel/DecisionServiceProperties.tsx index 0581d7ce441..803bf9cf870 100644 --- a/packages/dmn-editor/src/propertiesPanel/DecisionServiceProperties.tsx +++ b/packages/dmn-editor/src/propertiesPanel/DecisionServiceProperties.tsx @@ -122,6 +122,7 @@ export function DecisionServiceProperties({ { setState((state) => { const drgElement = state.dmn.model.definitions.drgElement![index] as DMN15__tDecisionService; @@ -184,6 +185,7 @@ export function DecisionServiceProperties({ newInputDecisions; }); }} + isDisabled={isReadonly} /> @@ -196,6 +198,7 @@ export function DecisionServiceProperties({ (state.dmn.model.definitions.drgElement![index] as DMN15__tDecisionService).inputData = newInputData; }); }} + isDisabled={isReadonly} /> @@ -276,11 +279,13 @@ export function DraggableDecisionServiceElementList({ elements, allDrgElementsByHref, onChange, + isDisabled, }: { decisionServiceNamespace: string | undefined; elements: DMN15__tDecisionService["outputDecision"]; allDrgElementsByHref: AllKnownDrgElementsByHref; onChange: (hrefs: DMN15__tDMNElementReference[] | undefined) => void; + isDisabled: boolean; }) { const thisDmnsNamespace = useDmnEditorStore((s) => s.dmn.model.definitions["@_namespace"]); const [keys, setKeys] = React.useState(() => elements?.map((e) => e["@_href"]) ?? []); @@ -328,6 +333,7 @@ export function DraggableDecisionServiceElementList({ handlerStyle={ keys[index] ? { paddingLeft: "16px", paddingRight: "16px" } : { paddingLeft: "16px", paddingRight: "16px" } } + isDisabled={isDisabled} >
  • ); }, - [allDrgElementsByHref, decisionServiceNamespace, keys, thisDmnsNamespace] + [allDrgElementsByHref, decisionServiceNamespace, isDisabled, keys, thisDmnsNamespace] ); return ( @@ -357,7 +363,7 @@ export function DraggableDecisionServiceElementList({ onDragEnd={onDragEnd} values={elements} draggableItem={draggableItem} - isDisabled={false} + isDisabled={isDisabled} /> ); diff --git a/packages/dmn-editor/src/propertiesPanel/DiagramPropertiesPanel.tsx b/packages/dmn-editor/src/propertiesPanel/DiagramPropertiesPanel.tsx index a13a355a3ad..66ebf6aa595 100644 --- a/packages/dmn-editor/src/propertiesPanel/DiagramPropertiesPanel.tsx +++ b/packages/dmn-editor/src/propertiesPanel/DiagramPropertiesPanel.tsx @@ -39,7 +39,7 @@ export function DiagramPropertiesPanel() { isResizable={true} minSize={"300px"} defaultSize={"500px"} - onKeyDown={(e) => e.stopPropagation()} // This prevents ReactFlow KeyboardShortcuts from triggering when editing stuff on Properties Panel + onKeyDown={(e) => e.stopPropagation()} // Prevent ReactFlow KeyboardShortcuts from triggering when editing stuff on Properties Panel > {selectedNodesById.size <= 0 && } diff --git a/packages/dmn-editor/src/propertiesPanel/DocumentationLinksFormGroup.tsx b/packages/dmn-editor/src/propertiesPanel/DocumentationLinksFormGroup.tsx index 59edffc1f2e..f82b7be7891 100644 --- a/packages/dmn-editor/src/propertiesPanel/DocumentationLinksFormGroup.tsx +++ b/packages/dmn-editor/src/propertiesPanel/DocumentationLinksFormGroup.tsx @@ -176,6 +176,7 @@ export function DocumentationLinksFormGroup({ ? { alignSelf: "flex-start", paddingTop: "8px", paddingLeft: "16px", paddingRight: "16px" } : { paddingLeft: "16px", paddingRight: "16px" } } + isDisabled={isReadonly} >
  • shapeStyles[0]?.["@_fontStrikeThrough"] ?? false, [shapeStyles]); const fontSize = useMemo(() => shapeStyles[0]?.["@_fontSize"] ?? DEFAULT_FONT_SIZE, [shapeStyles]); const fontColor = useMemo(() => { - const b = (shapeStyles[0]?.["dmndi:FontColor"]?.["@_blue"] ?? DEFAULT_FONT_COLOR["@_red"]).toString(16); + const b = (shapeStyles[0]?.["dmndi:FontColor"]?.["@_blue"] ?? DEFAULT_FONT_COLOR["@_blue"]).toString(16); const g = (shapeStyles[0]?.["dmndi:FontColor"]?.["@_green"] ?? DEFAULT_FONT_COLOR["@_green"]).toString(16); - const r = (shapeStyles[0]?.["dmndi:FontColor"]?.["@_red"] ?? DEFAULT_FONT_COLOR["@_blue"]).toString(16); + const r = (shapeStyles[0]?.["dmndi:FontColor"]?.["@_red"] ?? DEFAULT_FONT_COLOR["@_red"]).toString(16); return `#${r.length === 1 ? "0" + r : r}${g.length === 1 ? "0" + g : g}${b.length === 1 ? "0" + b : b}`; }, [shapeStyles]); @@ -233,7 +233,7 @@ export function FontOptions({ startExpanded, nodeIds }: { startExpanded: boolean setShapeStyles((shapes, state) => { shapes.forEach((shape) => { state.diagram.isEditingStyle = false; - shape["di:Style"]!["dmndi:FontColor"] ??= DEFAULT_FONT_COLOR; + shape["di:Style"]!["dmndi:FontColor"] ??= { ...DEFAULT_FONT_COLOR }; shape["di:Style"]!["dmndi:FontColor"]["@_red"] = parseInt(temporaryFontColor.slice(0, 2), 16); shape["di:Style"]!["dmndi:FontColor"]["@_green"] = parseInt(temporaryFontColor.slice(2, 4), 16); shape["di:Style"]!["dmndi:FontColor"]["@_blue"] = parseInt(temporaryFontColor.slice(4, 6), 16); @@ -256,10 +256,7 @@ export function FontOptions({ startExpanded, nodeIds }: { startExpanded: boolean shape["di:Style"]!["@_fontStrikeThrough"] = undefined; shape["di:Style"]!["@_fontSize"] = undefined; shape["di:Style"]!["@_fontFamily"] = undefined; - shape["di:Style"]!["dmndi:FontColor"] ??= DEFAULT_FONT_COLOR; - shape["di:Style"]!["dmndi:FontColor"]["@_red"] = DEFAULT_FONT_COLOR["@_red"]; - shape["di:Style"]!["dmndi:FontColor"]["@_green"] = DEFAULT_FONT_COLOR["@_green"]; - shape["di:Style"]!["dmndi:FontColor"]["@_blue"] = DEFAULT_FONT_COLOR["@_blue"]; + shape["di:Style"]!["dmndi:FontColor"] = { ...DEFAULT_FONT_COLOR }; }); }); }, [setShapeStyles]); diff --git a/packages/dmn-editor/src/propertiesPanel/InputDataProperties.tsx b/packages/dmn-editor/src/propertiesPanel/InputDataProperties.tsx index 8a5d8b7c0d4..eddba2809a6 100644 --- a/packages/dmn-editor/src/propertiesPanel/InputDataProperties.tsx +++ b/packages/dmn-editor/src/propertiesPanel/InputDataProperties.tsx @@ -76,6 +76,7 @@ export function InputDataProperties({ { setState((state) => { const drgElement = state.dmn.model.definitions.drgElement![index] as DMN15__tInputData; diff --git a/packages/dmn-editor/src/propertiesPanel/ShapeOptions.tsx b/packages/dmn-editor/src/propertiesPanel/ShapeOptions.tsx index 35e8dcfee4a..b58e300ee03 100644 --- a/packages/dmn-editor/src/propertiesPanel/ShapeOptions.tsx +++ b/packages/dmn-editor/src/propertiesPanel/ShapeOptions.tsx @@ -18,7 +18,7 @@ */ import * as React from "react"; -import { useState, useMemo, useCallback, useEffect } from "react"; +import { useState, useMemo, useCallback, useEffect, useRef } from "react"; import { FormGroup, FormSection } from "@patternfly/react-core/dist/js/components/Form"; import { TextInput } from "@patternfly/react-core/dist/js/components/TextInput"; import { CubeIcon } from "@patternfly/react-icons/dist/js/icons/cube-icon"; @@ -34,6 +34,11 @@ import UndoAltIcon from "@patternfly/react-icons/dist/js/icons/undo-alt-icon"; import { ColorPicker } from "./ColorPicker"; import { ToggleGroup, ToggleGroupItem } from "@patternfly/react-core/dist/js/components/ToggleGroup"; import "./ShapeOptions.css"; +import { useExternalModels } from "../includedModels/DmnEditorDependenciesContext"; +import { MIN_NODE_SIZES } from "../diagram/nodes/DefaultSizes"; +import { NodeType } from "../diagram/connections/graphStructure"; +import { Button, ButtonVariant } from "@patternfly/react-core/dist/js/components/Button"; +import { DC__Dimension } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_2/ts-gen/types"; const DEFAULT_FILL_COLOR = { "@_blue": 255, "@_green": 255, "@_red": 255 }; const DEFAULT_STROKE_COLOR = { "@_blue": 0, "@_green": 0, "@_red": 0 }; @@ -50,10 +55,12 @@ export function ShapeOptions({ isPositioningEnabled: boolean; }) { const dmnEditorStoreApi = useDmnEditorStoreApi(); + const { externalModelsByNamespace } = useExternalModels(); const shapes = useDmnEditorStore((s) => nodeIds.map((nodeId) => s.computed(s).indexedDrd().dmnShapesByHref.get(nodeId)) ); + const nodesById = useDmnEditorStore((s) => s.computed(s).getDiagramData(externalModelsByNamespace).nodesById); const shapeStyles = useMemo(() => shapes.map((shape) => shape?.["di:Style"]), [shapes]); // For when a single node is selected. @@ -63,30 +70,50 @@ export function ShapeOptions({ const boundPositionX = useMemo(() => +(shapeBound?.["@_x"]?.toFixed(2) ?? ""), [shapeBound]); const boundPositionY = useMemo(() => +(shapeBound?.["@_y"]?.toFixed(2) ?? ""), [shapeBound]); + const [width, setWidth] = useState(boundWidth); + const [height, setHeight] = useState(boundHeight); + /** + * The `setBounds` method uses the `nodeId` to update a specific node. + * Filling the `TextField` and changing the `nodeId` will cause the `onBlur` + * method to be called with this new `nodeId`. This reference keep the + * old `nodeId` saved, so the `setBounds` can be update the correct node. + */ + const previousNodeId = useRef(nodeIds[0]); + + useEffect(() => { + setWidth(boundWidth); + previousNodeId.current = nodeIds[0]; + }, [boundWidth, nodeIds]); + + useEffect(() => { + setHeight(boundHeight); + previousNodeId.current = nodeIds[0]; + }, [boundHeight, nodeIds]); + const fillColor = useMemo(() => { - const b = (shapeStyles[0]?.["dmndi:FillColor"]?.["@_blue"] ?? DEFAULT_FILL_COLOR["@_red"]).toString(16); + const b = (shapeStyles[0]?.["dmndi:FillColor"]?.["@_blue"] ?? DEFAULT_FILL_COLOR["@_blue"]).toString(16); const g = (shapeStyles[0]?.["dmndi:FillColor"]?.["@_green"] ?? DEFAULT_FILL_COLOR["@_green"]).toString(16); - const r = (shapeStyles[0]?.["dmndi:FillColor"]?.["@_red"] ?? DEFAULT_FILL_COLOR["@_blue"]).toString(16); + const r = (shapeStyles[0]?.["dmndi:FillColor"]?.["@_red"] ?? DEFAULT_FILL_COLOR["@_red"]).toString(16); return `#${r.length === 1 ? "0" + r : r}${g.length === 1 ? "0" + g : g}${b.length === 1 ? "0" + b : b}`; }, [shapeStyles]); const strokeColor = useMemo(() => { - const b = (shapeStyles[0]?.["dmndi:StrokeColor"]?.["@_blue"] ?? DEFAULT_STROKE_COLOR["@_red"]).toString(16); + const b = (shapeStyles[0]?.["dmndi:StrokeColor"]?.["@_blue"] ?? DEFAULT_STROKE_COLOR["@_blue"]).toString(16); const g = (shapeStyles[0]?.["dmndi:StrokeColor"]?.["@_green"] ?? DEFAULT_STROKE_COLOR["@_green"]).toString(16); - const r = (shapeStyles[0]?.["dmndi:StrokeColor"]?.["@_red"] ?? DEFAULT_STROKE_COLOR["@_blue"]).toString(16); + const r = (shapeStyles[0]?.["dmndi:StrokeColor"]?.["@_red"] ?? DEFAULT_STROKE_COLOR["@_red"]).toString(16); return `#${r.length === 1 ? "0" + r : r}${g.length === 1 ? "0" + g : g}${b.length === 1 ? "0" + b : b}`; }, [shapeStyles]); const [isShapeSectionExpanded, setShapeSectionExpanded] = useState(startExpanded); const setBounds = useCallback( - (callback: (bounds: DC__Bounds, state: State) => void) => { + (callback: (bounds: DC__Bounds, state: State) => void, nodeId: string) => { dmnEditorStoreApi.setState((s) => { const { diagramElements } = addOrGetDrd({ definitions: s.dmn.model.definitions, drdIndex: s.diagram.drdIndex }); - const index = nodeIds.map((nodeId) => s.computed(s).indexedDrd().dmnShapesByHref.get(nodeId))[0]?.index ?? -1; + const index = s.computed(s).indexedDrd()?.dmnShapesByHref?.get(nodeId)?.index ?? -1; if (index < 0) { - throw new Error(`DMN Shape for '${nodeIds[0]}' does not exist.`); + throw new Error(`DMN Shape for '${nodeId}' does not exist.`); } const shape = diagramElements?.[index]; @@ -100,61 +127,103 @@ export function ShapeOptions({ callback(shape["dc:Bounds"], s); }); }, - [dmnEditorStoreApi, nodeIds] + [dmnEditorStoreApi] ); - const onChangeWidth = useCallback( - (newWidth: string) => { - setBounds((bounds) => { - bounds["@_width"] = +parseFloat(newWidth).toFixed(2); - }); + const onChangeWidth = useCallback((newWidth: string) => { + setWidth(+newWidth); + }, []); + + const onBlurWidth = useCallback( + (event) => { + setBounds((bounds, state) => { + const node = nodesById.get(previousNodeId.current); + const minNodeSize = MIN_NODE_SIZES[node?.type as NodeType]({ + snapGrid: state.diagram.snapGrid, + isAlternativeInputDataShape: state.computed(state).isAlternativeInputDataShape(), + }); + + if (parseInt(event.target.value) < minNodeSize["@_width"]) { + bounds["@_width"] = minNodeSize["@_width"]; + setWidth(minNodeSize["@_width"]); + } else { + bounds["@_width"] = parseInt(event.target.value); + } + }, previousNodeId.current); }, - [setBounds] + [nodesById, setBounds] ); - const onChangeHeight = useCallback( - (newHeight: string) => { - setBounds((bounds) => { - bounds["@_height"] = +parseFloat(newHeight).toFixed(2); - }); + const onChangeHeight = useCallback((newHeight: string) => { + setHeight(+newHeight); + }, []); + + const onBlurHeight = useCallback( + (event) => { + setBounds((bounds, state) => { + const node = nodesById.get(previousNodeId.current); + const minNodeSize = MIN_NODE_SIZES[node?.type as NodeType]({ + snapGrid: state.diagram.snapGrid, + isAlternativeInputDataShape: state.computed(state).isAlternativeInputDataShape(), + }); + + if (parseInt(event.target.value) < minNodeSize["@_height"]) { + bounds["@_height"] = minNodeSize["@_height"]; + setHeight(minNodeSize["@_height"]); + } else { + bounds["@_height"] = parseInt(event.target.value); + } + }, previousNodeId.current); }, - [setBounds] + [nodesById, setBounds] ); const onChangePositionX = useCallback( (newX: string) => { setBounds((bounds) => { bounds["@_x"] = +parseFloat(newX).toFixed(2); - }); + }, nodeIds[0]); }, - [setBounds] + [nodeIds, setBounds] ); const onChangePositionY = useCallback( (newY: string) => { setBounds((bounds) => { bounds["@_y"] = +parseFloat(newY).toFixed(2); - }); + }, nodeIds[0]); }, - [setBounds] + [nodeIds, setBounds] ); const setShapeStyles = useCallback( - (callback: (shape: DMNDI15__DMNShape[], state: State) => void) => { + ( + callback: ( + shapesWithMinNodeSize: { shape: DMNDI15__DMNShape; minNodeSize: DC__Dimension }[], + state: State + ) => void + ) => { dmnEditorStoreApi.setState((s) => { const { diagramElements } = addOrGetDrd({ definitions: s.dmn.model.definitions, drdIndex: s.diagram.drdIndex }); - const shapes = nodeIds.map((nodeId) => { + const shapesWithMinNodeSize = nodeIds.map((nodeId) => { const shape = s.computed(s).indexedDrd().dmnShapesByHref.get(nodeId); + const node = s.computed(s).getDiagramData(externalModelsByNamespace).nodesById.get(nodeId); + + const minNodeSize = MIN_NODE_SIZES[node?.type as NodeType]({ + snapGrid: s.diagram.snapGrid, + isAlternativeInputDataShape: s.computed(s).isAlternativeInputDataShape(), + }); + if (!shape) { throw new Error(`DMN Shape for '${nodeId}' does not exist.`); } - return diagramElements[shape.index]; + return { shape: diagramElements[shape.index], minNodeSize }; }); let i = 0; - for (const shape of shapes) { + for (const { shape } of shapesWithMinNodeSize) { if (shape.__$$element !== "dmndi:DMNShape") { throw new Error(`DMN Element with index ${i++} is not a DMNShape.`); } @@ -162,10 +231,10 @@ export function ShapeOptions({ shape["di:Style"] ??= { __$$element: "dmndi:DMNStyle" }; } - callback(shapes, s); + callback(shapesWithMinNodeSize, s); }); }, - [dmnEditorStoreApi, nodeIds] + [dmnEditorStoreApi, externalModelsByNamespace, nodeIds] ); const [temporaryStrokeColor, setTemporaryStrokeColor] = useState(); @@ -187,10 +256,10 @@ export function ShapeOptions({ setTemporaryStrokeColor(undefined); - setShapeStyles((shapes, state) => { - shapes.forEach((shape) => { + setShapeStyles((shapesWithMinNodeSize, state) => { + shapesWithMinNodeSize.forEach(({ shape }) => { state.diagram.isEditingStyle = false; - shape!["di:Style"]!["dmndi:StrokeColor"] ??= DEFAULT_STROKE_COLOR; + shape!["di:Style"]!["dmndi:StrokeColor"] ??= { ...DEFAULT_STROKE_COLOR }; shape!["di:Style"]!["dmndi:StrokeColor"]["@_red"] = parseInt(temporaryStrokeColor.slice(0, 2), 16); shape!["di:Style"]!["dmndi:StrokeColor"]["@_green"] = parseInt(temporaryStrokeColor.slice(2, 4), 16); shape!["di:Style"]!["dmndi:StrokeColor"]["@_blue"] = parseInt(temporaryStrokeColor.slice(4, 6), 16); @@ -222,10 +291,10 @@ export function ShapeOptions({ setTemporaryFillColor(undefined); - setShapeStyles((shapes, state) => { - shapes.forEach((shape) => { + setShapeStyles((shapesWithMinNodeSize, state) => { + shapesWithMinNodeSize.forEach(({ shape }) => { state.diagram.isEditingStyle = false; - shape!["di:Style"]!["dmndi:FillColor"] ??= DEFAULT_FILL_COLOR; + shape!["di:Style"]!["dmndi:FillColor"] ??= { ...DEFAULT_FILL_COLOR }; shape!["di:Style"]!["dmndi:FillColor"]["@_red"] = parseInt(temporaryFillColor.slice(0, 2), 16); shape!["di:Style"]!["dmndi:FillColor"]["@_green"] = parseInt(temporaryFillColor.slice(2, 4), 16); shape!["di:Style"]!["dmndi:FillColor"]["@_blue"] = parseInt(temporaryFillColor.slice(4, 6), 16); @@ -239,17 +308,24 @@ export function ShapeOptions({ }, [setShapeStyles, temporaryFillColor]); const onReset = useCallback(() => { - setShapeStyles((shapes) => { - shapes.forEach((shape) => { - shape!["di:Style"]!["dmndi:FillColor"] ??= DEFAULT_FILL_COLOR; - shape!["di:Style"]!["dmndi:FillColor"]["@_red"] = DEFAULT_FILL_COLOR["@_red"]; - shape!["di:Style"]!["dmndi:FillColor"]["@_green"] = DEFAULT_FILL_COLOR["@_green"]; - shape!["di:Style"]!["dmndi:FillColor"]["@_blue"] = DEFAULT_FILL_COLOR["@_blue"]; - - shape!["di:Style"]!["dmndi:StrokeColor"] ??= DEFAULT_STROKE_COLOR; - shape!["di:Style"]!["dmndi:StrokeColor"]["@_red"] = DEFAULT_STROKE_COLOR["@_red"]; - shape!["di:Style"]!["dmndi:StrokeColor"]["@_green"] = DEFAULT_STROKE_COLOR["@_green"]; - shape!["di:Style"]!["dmndi:StrokeColor"]["@_blue"] = DEFAULT_STROKE_COLOR["@_blue"]; + setShapeStyles((shapeWithNodes) => { + shapeWithNodes.forEach(({ shape, minNodeSize }) => { + shape["di:Style"] ??= { + __$$element: "dmndi:DMNStyle", + "dmndi:FillColor": { ...DEFAULT_FILL_COLOR }, + "dmndi:StrokeColor": { ...DEFAULT_STROKE_COLOR }, + }; + shape["di:Style"]["dmndi:FillColor"] = { ...DEFAULT_FILL_COLOR }; + shape["di:Style"]["dmndi:StrokeColor"] = { ...DEFAULT_STROKE_COLOR }; + + shape["dc:Bounds"] ??= { + "@_width": minNodeSize["@_width"], + "@_height": minNodeSize["@_height"], + "@_x": 0, + "@_y": 0, + }; + shape["dc:Bounds"]["@_width"] = minNodeSize["@_width"]; + shape["dc:Bounds"]["@_height"] = minNodeSize["@_height"]; }); }); }, [setShapeStyles]); @@ -266,9 +342,19 @@ export function ShapeOptions({ isSectionExpanded={isShapeSectionExpanded} toogleSectionExpanded={() => setShapeSectionExpanded((prev) => !prev)} title={"Shape"} + action={ + + } /> {isShapeSectionExpanded && ( - + @@ -349,10 +435,11 @@ export function ShapeOptions({ data-testid={"kie-tools--dmn-editor--properties-panel-node-shape-width-input"} type={"number"} isDisabled={isDimensioningEnabled ? false : true} - value={isDimensioningEnabled ? boundWidth : undefined} + value={isDimensioningEnabled ? width : undefined} placeholder={isDimensioningEnabled ? "Enter a value..." : undefined} + onBlur={onBlurWidth} onChange={onChangeWidth} - style={{ maxWidth: "80px", minWidth: "60px", border: "none", backgroundColor: "transparent" }} + style={{ border: "none", backgroundColor: "transparent" }} />
    @@ -375,10 +462,11 @@ export function ShapeOptions({ data-testid={"kie-tools--dmn-editor--properties-panel-node-shape-height-input"} type={"number"} isDisabled={isDimensioningEnabled ? false : true} - value={isDimensioningEnabled ? boundHeight : undefined} + value={isDimensioningEnabled ? height : undefined} placeholder={isDimensioningEnabled ? "Enter a value..." : undefined} + onBlur={onBlurHeight} onChange={onChangeHeight} - style={{ maxWidth: "80px", minWidth: "60px", border: "none", backgroundColor: "transparent" }} + style={{ border: "none", backgroundColor: "transparent" }} />
    @@ -389,16 +477,6 @@ export function ShapeOptions({ buttonId={"shape-style-toggle-group-bound-height"} /> - - } - key={"reset"} - buttonId={"shape-style-toggle-group-reset"} - /> - {isPositioningEnabled && ( diff --git a/packages/dmn-editor/src/store/Store.ts b/packages/dmn-editor/src/store/Store.ts index fb96ef26f89..108f9fa5385 100644 --- a/packages/dmn-editor/src/store/Store.ts +++ b/packages/dmn-editor/src/store/Store.ts @@ -25,6 +25,7 @@ import { create } from "zustand"; import { immer } from "zustand/middleware/immer"; import { ExternalModelsIndex } from "../DmnEditor"; import { DmnDiagramNodeData } from "../diagram/nodes/Nodes"; +import { normalize } from "../normalization/normalize"; import { ComputedStateCache } from "./ComputedStateCache"; import { computeAllFeelVariableUniqueNames } from "./computed/computeAllFeelVariableUniqueNames"; import { computeDataTypes } from "./computed/computeDataTypes"; @@ -217,7 +218,7 @@ export function createDmnEditorStore(model: State["dmn"]["model"], computedCache return create( immer(() => ({ dmn: { - model, + model: normalize(model), }, ...defaultStaticState(), dispatch(s: State) { diff --git a/packages/dmn-editor/stories/dev/externalModels.ts b/packages/dmn-editor/stories/dev/externalModels.ts index 3733a0c26c4..0c293ed34b9 100644 --- a/packages/dmn-editor/stories/dev/externalModels.ts +++ b/packages/dmn-editor/stories/dev/externalModels.ts @@ -111,6 +111,14 @@ export const sumDiffDs = `number + + + number + + 100,500,1000 + + + diff --git a/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/bkmPropertiesPanel.ts b/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/bkmPropertiesPanel.ts index f3d5d96fe09..eba7a26fd69 100644 --- a/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/bkmPropertiesPanel.ts +++ b/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/bkmPropertiesPanel.ts @@ -40,9 +40,9 @@ export class BkmPropertiesPanel extends PropertiesPanelBase { super(diagram, page); this.nameProperties = new NameProperties(this.panel(), page); this.dataTypeProperties = new DataTypeProperties(this.panel(), page); - this.descriptionProperties = new DescriptionProperties(this.panel(), diagram); + this.descriptionProperties = new DescriptionProperties(this.panel()); this.documentationProperties = new DocumentationProperties(this.panel(), page); - this.fontProperties = new FontProperties(this.panel(), diagram); + this.fontProperties = new FontProperties(this.panel()); this.shapeProperties = new ShapeProperties(this.panel()); } diff --git a/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/decisionServicePropertiesPanel.ts b/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/decisionServicePropertiesPanel.ts index 10664787a70..e760bc2c8fb 100644 --- a/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/decisionServicePropertiesPanel.ts +++ b/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/decisionServicePropertiesPanel.ts @@ -40,9 +40,9 @@ export class DecisionServicePropertiesPanel extends PropertiesPanelBase { super(diagram, page); this.nameProperties = new NameProperties(this.panel(), page); this.dataTypeProperties = new DataTypeProperties(this.panel(), page); - this.descriptionProperties = new DescriptionProperties(this.panel(), diagram); + this.descriptionProperties = new DescriptionProperties(this.panel()); this.documentationProperties = new DocumentationProperties(this.panel(), page); - this.fontProperties = new FontProperties(this.panel(), diagram); + this.fontProperties = new FontProperties(this.panel()); this.shapeProperties = new ShapeProperties(this.panel()); } diff --git a/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/groupPropertiesPanel.ts b/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/groupPropertiesPanel.ts index d3e8ee67a88..44ed3fa74c6 100644 --- a/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/groupPropertiesPanel.ts +++ b/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/groupPropertiesPanel.ts @@ -34,8 +34,8 @@ export class GroupPropertiesPanel extends PropertiesPanelBase { constructor(public diagram: Diagram, public page: Page) { super(diagram, page); this.nameProperties = new NameProperties(this.panel(), page); - this.descriptionProperties = new DescriptionProperties(this.panel(), diagram); - this.fontProperties = new FontProperties(this.panel(), diagram); + this.descriptionProperties = new DescriptionProperties(this.panel()); + this.fontProperties = new FontProperties(this.panel()); this.shapeProperties = new ShapeProperties(this.panel()); } diff --git a/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/inputDataPropertiesPanel.ts b/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/inputDataPropertiesPanel.ts index c53c3aeb4dd..06f5a278ffb 100644 --- a/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/inputDataPropertiesPanel.ts +++ b/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/inputDataPropertiesPanel.ts @@ -40,9 +40,9 @@ export class InputDataPropertiesPanel extends PropertiesPanelBase { super(diagram, page); this.nameProperties = new NameProperties(this.panel(), page); this.dataTypeProperties = new DataTypeProperties(this.panel(), page); - this.descriptionProperties = new DescriptionProperties(this.panel(), diagram); + this.descriptionProperties = new DescriptionProperties(this.panel()); this.documentationProperties = new DocumentationProperties(this.panel(), page); - this.fontProperties = new FontProperties(this.panel(), diagram); + this.fontProperties = new FontProperties(this.panel()); this.shapeProperties = new ShapeProperties(this.panel()); } diff --git a/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/multipleNodesPropertiesPanel.ts b/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/multipleNodesPropertiesPanel.ts index abf56f641d4..2f8816040c8 100644 --- a/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/multipleNodesPropertiesPanel.ts +++ b/packages/dmn-editor/tests/e2e/__fixtures__/propertiesPanel/multipleNodesPropertiesPanel.ts @@ -29,7 +29,7 @@ export class MultipleNodesPropertiesPanel extends PropertiesPanelBase { constructor(public diagram: Diagram, public page: Page) { super(diagram, page); - this.fontProperties = new FontProperties(this.panel(), diagram); + this.fontProperties = new FontProperties(this.panel()); this.shapeProperties = new ShapeProperties(this.panel()); } diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/change-multiple-nodes-shape.png b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/change-multiple-nodes-shape.png new file mode 100644 index 00000000000..c052f944118 Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/change-multiple-nodes-shape.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drdArtifacts/reset-group-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drdArtifacts/reset-group-font.png new file mode 100644 index 00000000000..c146635f7cf Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drdArtifacts/reset-group-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drdArtifacts/reset-text-annotation-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drdArtifacts/reset-text-annotation-font.png new file mode 100644 index 00000000000..0e31a72e9dd Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drdArtifacts/reset-text-annotation-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-bkm-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-bkm-font.png new file mode 100644 index 00000000000..8c087b90d6c Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-bkm-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-decision-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-decision-font.png new file mode 100644 index 00000000000..d4221a2272a Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-decision-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-decision-service-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-decision-service-font.png new file mode 100644 index 00000000000..f43f4671954 Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-decision-service-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-input-data-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-input-data-font.png new file mode 100644 index 00000000000..510a03d20df Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-input-data-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-knowledge-source-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-knowledge-source-font.png new file mode 100644 index 00000000000..3d9c3c31994 Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/drgElements/reset-knowledge-source-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/reset-multiple-nodes-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/reset-multiple-nodes-font.png new file mode 100644 index 00000000000..6133efc520e Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/Google-Chrome/reset-multiple-nodes-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/chromium/change-multiple-nodes-shape.png b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/change-multiple-nodes-shape.png new file mode 100644 index 00000000000..89de4527746 Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/change-multiple-nodes-shape.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drdArtifacts/reset-group-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drdArtifacts/reset-group-font.png new file mode 100644 index 00000000000..5775a3d8534 Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drdArtifacts/reset-group-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drdArtifacts/reset-text-annotation-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drdArtifacts/reset-text-annotation-font.png new file mode 100644 index 00000000000..012527fb58c Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drdArtifacts/reset-text-annotation-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-bkm-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-bkm-font.png new file mode 100644 index 00000000000..a37507507ca Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-bkm-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-decision-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-decision-font.png new file mode 100644 index 00000000000..b19fc88bb46 Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-decision-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-decision-service-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-decision-service-font.png new file mode 100644 index 00000000000..451cb9ef09d Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-decision-service-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-input-data-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-input-data-font.png new file mode 100644 index 00000000000..5b56cd2eabe Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-input-data-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-knowledge-source-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-knowledge-source-font.png new file mode 100644 index 00000000000..04f381f0155 Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/drgElements/reset-knowledge-source-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/chromium/reset-multiple-nodes-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/reset-multiple-nodes-font.png new file mode 100644 index 00000000000..48c863ac2e3 Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/chromium/reset-multiple-nodes-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/webkit/change-multiple-nodes-shape.png b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/change-multiple-nodes-shape.png new file mode 100644 index 00000000000..edeff3d434c Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/change-multiple-nodes-shape.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drdArtifacts/reset-group-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drdArtifacts/reset-group-font.png new file mode 100644 index 00000000000..b49995386ef Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drdArtifacts/reset-group-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drdArtifacts/reset-text-annotation-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drdArtifacts/reset-text-annotation-font.png new file mode 100644 index 00000000000..feb8939a9b5 Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drdArtifacts/reset-text-annotation-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-bkm-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-bkm-font.png new file mode 100644 index 00000000000..12cbb9909fe Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-bkm-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-decision-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-decision-font.png new file mode 100644 index 00000000000..df0c92fd02f Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-decision-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-decision-service-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-decision-service-font.png new file mode 100644 index 00000000000..a158c2474cb Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-decision-service-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-input-data-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-input-data-font.png new file mode 100644 index 00000000000..eaea399872d Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-input-data-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-knowledge-source-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-knowledge-source-font.png new file mode 100644 index 00000000000..d168add4d55 Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/drgElements/reset-knowledge-source-font.png differ diff --git a/packages/dmn-editor/tests/e2e/__screenshots__/webkit/reset-multiple-nodes-font.png b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/reset-multiple-nodes-font.png new file mode 100644 index 00000000000..e304b6afb5e Binary files /dev/null and b/packages/dmn-editor/tests/e2e/__screenshots__/webkit/reset-multiple-nodes-font.png differ diff --git a/packages/dmn-editor/tests/e2e/changeMultipleNodesProperties.spec.ts b/packages/dmn-editor/tests/e2e/changeMultipleNodesProperties.spec.ts index 4bae371c624..378241d0ad4 100644 --- a/packages/dmn-editor/tests/e2e/changeMultipleNodesProperties.spec.ts +++ b/packages/dmn-editor/tests/e2e/changeMultipleNodesProperties.spec.ts @@ -45,4 +45,67 @@ test.describe("Change Properties - Multiple Nodes", () => { await expect(diagram.get()).toHaveScreenshot("change-multiple-nodes-font.png"); }); + + test("should reset multiple nodes shape", async ({ nodes, palette, diagram, multipleNodesPropertiesPanel }) => { + await palette.dragNewNode({ type: NodeType.INPUT_DATA, targetPosition: { x: 100, y: 100 } }); + await nodes.resize({ nodeName: DefaultNodeName.INPUT_DATA, xOffset: 50, yOffset: 50 }); + await diagram.resetFocus(); + await palette.dragNewNode({ type: NodeType.DECISION, targetPosition: { x: 400, y: 100 } }); + await nodes.resize({ nodeName: DefaultNodeName.DECISION, xOffset: 50, yOffset: 50 }); + await diagram.resetFocus(); + + await multipleNodesPropertiesPanel.open(); + await nodes.selectMultiple({ names: [DefaultNodeName.INPUT_DATA, DefaultNodeName.DECISION] }); + await multipleNodesPropertiesPanel.resetShape(); + + await expect(diagram.get()).toHaveScreenshot("change-multiple-nodes-shape.png"); + }); + + test("should update shape properties when switching between nodes", async ({ + nodes, + palette, + diagram, + inputDataPropertiesPanel, + decisionPropertiesPanel, + }) => { + await palette.dragNewNode({ type: NodeType.INPUT_DATA, targetPosition: { x: 100, y: 100 } }); + await nodes.resize({ nodeName: DefaultNodeName.INPUT_DATA, xOffset: 50, yOffset: 50 }); + await diagram.resetFocus(); + await palette.dragNewNode({ type: NodeType.DECISION, targetPosition: { x: 400, y: 100 } }); + await nodes.resize({ nodeName: DefaultNodeName.DECISION, xOffset: 100, yOffset: 100 }); + await diagram.resetFocus(); + + await inputDataPropertiesPanel.open(); + await nodes.select({ name: DefaultNodeName.INPUT_DATA }); + const { width: inputDataWidth, height: inputDataHeight } = await inputDataPropertiesPanel.getShape(); + expect(inputDataWidth).toEqual("200"); + expect(inputDataHeight).toEqual("120"); + + await nodes.select({ name: DefaultNodeName.DECISION }); + const { width: decisionWidth, height: decisionHeight } = await decisionPropertiesPanel.getShape(); + expect(decisionWidth).toEqual("260"); + expect(decisionHeight).toEqual("180"); + }); + + test("should reset multiple nodes font", async ({ nodes, palette, diagram, multipleNodesPropertiesPanel }) => { + await palette.dragNewNode({ type: NodeType.INPUT_DATA, targetPosition: { x: 100, y: 100 } }); + await diagram.resetFocus(); + await palette.dragNewNode({ type: NodeType.DECISION, targetPosition: { x: 300, y: 100 } }); + await diagram.resetFocus(); + + await multipleNodesPropertiesPanel.open(); + await nodes.selectMultiple({ names: [DefaultNodeName.INPUT_DATA, DefaultNodeName.DECISION] }); + await multipleNodesPropertiesPanel.setFont({ + fontSize: "40", + bold: true, + italic: true, + underline: true, + striketrough: true, + color: "#f12200", + fontFamily: "Verdana", + }); + await multipleNodesPropertiesPanel.resetFont(); + + await expect(diagram.get()).toHaveScreenshot("reset-multiple-nodes-font.png"); + }); }); diff --git a/packages/dmn-editor/tests/e2e/drdArtifacts/changeGroupProperties.spec.ts b/packages/dmn-editor/tests/e2e/drdArtifacts/changeGroupProperties.spec.ts index 7f9ceaf9c28..d9ff99bd2f6 100644 --- a/packages/dmn-editor/tests/e2e/drdArtifacts/changeGroupProperties.spec.ts +++ b/packages/dmn-editor/tests/e2e/drdArtifacts/changeGroupProperties.spec.ts @@ -71,7 +71,7 @@ test.describe("Change Properties - Group", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1076", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1076"); + await nodes.select({ name: DefaultNodeName.GROUP, position: NodePosition.TOP }); await groupPropertiesPanel.setFont({ fontSize: "40", diff --git a/packages/dmn-editor/tests/e2e/drdArtifacts/changeTextAnnotationProperties.spec.ts b/packages/dmn-editor/tests/e2e/drdArtifacts/changeTextAnnotationProperties.spec.ts index 8bf1ac348fd..3713bbad41e 100644 --- a/packages/dmn-editor/tests/e2e/drdArtifacts/changeTextAnnotationProperties.spec.ts +++ b/packages/dmn-editor/tests/e2e/drdArtifacts/changeTextAnnotationProperties.spec.ts @@ -82,7 +82,7 @@ test.describe("Change Properties - Text Annotation", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1076", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1076"); + await nodes.select({ name: DefaultNodeName.TEXT_ANNOTATION }); await textAnnotationPropertiesPanel.setFont({ fontSize: "40", diff --git a/packages/dmn-editor/tests/e2e/drdArtifacts/resizeGroup.spec.ts b/packages/dmn-editor/tests/e2e/drdArtifacts/resizeGroup.spec.ts index 75b0a108a08..2db5b779f85 100644 --- a/packages/dmn-editor/tests/e2e/drdArtifacts/resizeGroup.spec.ts +++ b/packages/dmn-editor/tests/e2e/drdArtifacts/resizeGroup.spec.ts @@ -183,7 +183,6 @@ test.describe("Resize node - Group", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1074", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1074"); await groupPropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.GROUP, position: NodePosition.TOP }); await groupPropertiesPanel.setShape({ width: "100", height: "100" }); @@ -196,17 +195,17 @@ test.describe("Resize node - Group", () => { expect(width).toEqual("280"); }); - test("should reset Group node size", async ({ nodes, groupPropertiesPanel }) => { + test("should reset Group node size", async ({ diagram, nodes, groupPropertiesPanel }) => { test.info().annotations.push({ type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1075", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1075"); await groupPropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.GROUP, position: NodePosition.TOP }); await groupPropertiesPanel.setShape({ width: "325", height: "325" }); await groupPropertiesPanel.resetShape(); + await diagram.resetFocus(); await nodes.select({ name: DefaultNodeName.GROUP, position: NodePosition.TOP }); const { width, height } = await groupPropertiesPanel.getShape(); diff --git a/packages/dmn-editor/tests/e2e/drdArtifacts/resizeTextAnnotation.spec.ts b/packages/dmn-editor/tests/e2e/drdArtifacts/resizeTextAnnotation.spec.ts index 138b8fcaa4f..4ce89792bc3 100644 --- a/packages/dmn-editor/tests/e2e/drdArtifacts/resizeTextAnnotation.spec.ts +++ b/packages/dmn-editor/tests/e2e/drdArtifacts/resizeTextAnnotation.spec.ts @@ -277,7 +277,6 @@ test.describe("Resize node - Text Annotation", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1074", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1074"); await textAnnotationPropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.TEXT_ANNOTATION, position: NodePosition.TOP }); await textAnnotationPropertiesPanel.setShape({ width: "50", height: "50" }); @@ -295,7 +294,6 @@ test.describe("Resize node - Text Annotation", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1075", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1075"); await textAnnotationPropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.TEXT_ANNOTATION, position: NodePosition.TOP }); await textAnnotationPropertiesPanel.setShape({ width: "300", height: "300" }); diff --git a/packages/dmn-editor/tests/e2e/drgElements/changeBkmProperties.spec.ts b/packages/dmn-editor/tests/e2e/drgElements/changeBkmProperties.spec.ts index 39c14dfecae..db866f507d2 100644 --- a/packages/dmn-editor/tests/e2e/drgElements/changeBkmProperties.spec.ts +++ b/packages/dmn-editor/tests/e2e/drgElements/changeBkmProperties.spec.ts @@ -96,7 +96,7 @@ test.describe("Change Properties - BKM", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1076", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1076"); + await nodes.select({ name: DefaultNodeName.BKM }); await bkmPropertiesPanel.setFont({ fontSize: "40", diff --git a/packages/dmn-editor/tests/e2e/drgElements/changeDecisionProperties.spec.ts b/packages/dmn-editor/tests/e2e/drgElements/changeDecisionProperties.spec.ts index 509040c143c..6e0d665c618 100644 --- a/packages/dmn-editor/tests/e2e/drgElements/changeDecisionProperties.spec.ts +++ b/packages/dmn-editor/tests/e2e/drgElements/changeDecisionProperties.spec.ts @@ -117,7 +117,7 @@ test.describe("Change Properties - Decision", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1076", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1076"); + await nodes.select({ name: DefaultNodeName.DECISION }); await decisionPropertiesPanel.setFont({ fontSize: "40", diff --git a/packages/dmn-editor/tests/e2e/drgElements/changeDecisionServiceProperties.spec.ts b/packages/dmn-editor/tests/e2e/drgElements/changeDecisionServiceProperties.spec.ts index 305415322b6..6e463fe499f 100644 --- a/packages/dmn-editor/tests/e2e/drgElements/changeDecisionServiceProperties.spec.ts +++ b/packages/dmn-editor/tests/e2e/drgElements/changeDecisionServiceProperties.spec.ts @@ -104,7 +104,7 @@ test.describe("Change Properties - Decision Service", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1076", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1076"); + await nodes.select({ name: DefaultNodeName.DECISION_SERVICE, position: NodePosition.TOP }); await decisionServicePropertiesPanel.setFont({ fontSize: "40", diff --git a/packages/dmn-editor/tests/e2e/drgElements/changeInputDataProperties.spec.ts b/packages/dmn-editor/tests/e2e/drgElements/changeInputDataProperties.spec.ts index 41c3825fadc..38830383375 100644 --- a/packages/dmn-editor/tests/e2e/drgElements/changeInputDataProperties.spec.ts +++ b/packages/dmn-editor/tests/e2e/drgElements/changeInputDataProperties.spec.ts @@ -97,7 +97,7 @@ test.describe("Change Properties - Input Data", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1076", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1076"); + await nodes.select({ name: DefaultNodeName.INPUT_DATA }); await inputDataPropertiesPanel.setFont({ fontSize: "40", diff --git a/packages/dmn-editor/tests/e2e/drgElements/changeKnowledgeSourceProperties.spec.ts b/packages/dmn-editor/tests/e2e/drgElements/changeKnowledgeSourceProperties.spec.ts index b644ce6c8e5..49002d946a9 100644 --- a/packages/dmn-editor/tests/e2e/drgElements/changeKnowledgeSourceProperties.spec.ts +++ b/packages/dmn-editor/tests/e2e/drgElements/changeKnowledgeSourceProperties.spec.ts @@ -110,7 +110,7 @@ test.describe("Change Properties - Knowledge Source", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1076", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1076"); + await nodes.select({ name: DefaultNodeName.KNOWLEDGE_SOURCE }); await knowledgeSourcePropertiesPanel.setFont({ fontSize: "40", diff --git a/packages/dmn-editor/tests/e2e/drgElements/resizeBkm.spec.ts b/packages/dmn-editor/tests/e2e/drgElements/resizeBkm.spec.ts index b36fb0669dc..fabaad49447 100644 --- a/packages/dmn-editor/tests/e2e/drgElements/resizeBkm.spec.ts +++ b/packages/dmn-editor/tests/e2e/drgElements/resizeBkm.spec.ts @@ -185,7 +185,6 @@ test.describe("Resize node - BKM", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1074", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1074"); await bkmPropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.BKM }); await bkmPropertiesPanel.setShape({ width: "50", height: "50" }); @@ -203,7 +202,6 @@ test.describe("Resize node - BKM", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1075", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1075"); await bkmPropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.BKM }); await bkmPropertiesPanel.setShape({ width: "300", height: "300" }); diff --git a/packages/dmn-editor/tests/e2e/drgElements/resizeDecision.spec.ts b/packages/dmn-editor/tests/e2e/drgElements/resizeDecision.spec.ts index aba78ff6062..ece747147f4 100644 --- a/packages/dmn-editor/tests/e2e/drgElements/resizeDecision.spec.ts +++ b/packages/dmn-editor/tests/e2e/drgElements/resizeDecision.spec.ts @@ -187,7 +187,6 @@ test.describe("Resize node - Decision", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1074", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1074"); await decisionPropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.DECISION }); await decisionPropertiesPanel.setShape({ width: "50", height: "50" }); @@ -205,7 +204,6 @@ test.describe("Resize node - Decision", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1075", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1075"); await decisionPropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.DECISION }); await decisionPropertiesPanel.setShape({ width: "300", height: "300" }); diff --git a/packages/dmn-editor/tests/e2e/drgElements/resizeDecisionService.spec.ts b/packages/dmn-editor/tests/e2e/drgElements/resizeDecisionService.spec.ts index 7a8af54ea86..c1e3dd2e4bf 100644 --- a/packages/dmn-editor/tests/e2e/drgElements/resizeDecisionService.spec.ts +++ b/packages/dmn-editor/tests/e2e/drgElements/resizeDecisionService.spec.ts @@ -275,7 +275,6 @@ test.describe("Resize node - Decision Service", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1074", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1074"); await decisionServicePropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.DECISION_SERVICE, position: NodePosition.TOP }); await decisionServicePropertiesPanel.setShape({ width: "50", height: "50" }); @@ -293,7 +292,6 @@ test.describe("Resize node - Decision Service", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1075", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1075"); await decisionServicePropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.DECISION_SERVICE, position: NodePosition.TOP }); await decisionServicePropertiesPanel.setShape({ width: "300", height: "300" }); diff --git a/packages/dmn-editor/tests/e2e/drgElements/resizeInputData.spec.ts b/packages/dmn-editor/tests/e2e/drgElements/resizeInputData.spec.ts index db11996e358..ecaba01d3d5 100644 --- a/packages/dmn-editor/tests/e2e/drgElements/resizeInputData.spec.ts +++ b/packages/dmn-editor/tests/e2e/drgElements/resizeInputData.spec.ts @@ -189,7 +189,6 @@ test.describe("Resize node - Input Data", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1074", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1074"); await inputDataPropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.INPUT_DATA }); await inputDataPropertiesPanel.setShape({ width: "50", height: "50" }); @@ -207,7 +206,6 @@ test.describe("Resize node - Input Data", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1075", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1075"); await inputDataPropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.INPUT_DATA }); await inputDataPropertiesPanel.setShape({ width: "300", height: "300" }); diff --git a/packages/dmn-editor/tests/e2e/drgElements/resizeKnowledgeSource.spec.ts b/packages/dmn-editor/tests/e2e/drgElements/resizeKnowledgeSource.spec.ts index b67b6e6fb9e..73c49eb8425 100644 --- a/packages/dmn-editor/tests/e2e/drgElements/resizeKnowledgeSource.spec.ts +++ b/packages/dmn-editor/tests/e2e/drgElements/resizeKnowledgeSource.spec.ts @@ -202,7 +202,6 @@ test.describe("Resize node - Knowledge Source", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1074", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1074"); await knowledgeSourcePropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.KNOWLEDGE_SOURCE }); await knowledgeSourcePropertiesPanel.setShape({ width: "50", height: "50" }); @@ -220,7 +219,6 @@ test.describe("Resize node - Knowledge Source", () => { type: TestAnnotations.REGRESSION, description: "https://github.com/apache/incubator-kie-issues/issues/1075", }); - test.skip(true, "https://github.com/apache/incubator-kie-issues/issues/1075"); await knowledgeSourcePropertiesPanel.open(); await nodes.select({ name: DefaultNodeName.KNOWLEDGE_SOURCE }); await knowledgeSourcePropertiesPanel.setShape({ width: "300", height: "300" }); diff --git a/packages/dmn-feel-antlr4-parser/src/parser/VariablesRepository.ts b/packages/dmn-feel-antlr4-parser/src/parser/VariablesRepository.ts index c26f7ba35f1..78988ed333d 100644 --- a/packages/dmn-feel-antlr4-parser/src/parser/VariablesRepository.ts +++ b/packages/dmn-feel-antlr4-parser/src/parser/VariablesRepository.ts @@ -43,7 +43,7 @@ import { DMN15__tRelation, } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; import { Expression } from "./VariableOccurrence"; -import { DmnLatestModel, getMarshaller } from "@kie-tools/dmn-marshaller"; +import { DmnLatestModel } from "@kie-tools/dmn-marshaller"; type DmnLiteralExpression = { __$$element: "literalExpression" } & DMN15__tLiteralExpression; type DmnInvocation = { __$$element: "invocation" } & DMN15__tInvocation; @@ -53,14 +53,11 @@ type DmnFunctionDefinition = { __$$element: "functionDefinition" } & DMN15__tFun type DmnRelation = { __$$element: "relation" } & DMN15__tRelation; type DmnList = { __$$element: "list" } & DMN15__tList; type DmnKnowledgeRequirement = DMN15__tKnowledgeRequirement; - -type UnsupportedDmnExpressions = - | ({ __$$element: "for" } & DMN15__tFor) - | ({ __$$element: "every" } & DMN15__tQuantified) - | ({ __$$element: "some" } & DMN15__tQuantified) - | ({ __$$element: "conditional" } & DMN15__tConditional) - | ({ __$$element: "filter" } & DMN15__tFilter); - +type DmnConditional = { __$$element: "conditional" } & DMN15__tConditional; +type DmnFilter = { __$$element: "filter" } & DMN15__tFilter; +type DmnFor = { __$$element: "for" } & DMN15__tFor; +type DmnEvery = { __$$element: "every" } & DMN15__tQuantified; +type DmnSome = { __$$element: "some" } & DMN15__tQuantified; type DmnDecisionNode = { __$$element: "decision" } & DMN15__tDecision; type DmnBusinessKnowledgeModel = DMN15__tBusinessKnowledgeModel; export type DmnDefinitions = DMN15__tDefinitions; @@ -471,6 +468,45 @@ export class VariablesRepository { } } + private addConditional(parent: VariableContext, element: DmnConditional) { + if (element.if?.expression) { + this.addInnerExpression(parent, element.if.expression); + } + if (element.then?.expression) { + this.addInnerExpression(parent, element.then.expression); + } + if (element.else?.expression) { + this.addInnerExpression(parent, element.else.expression); + } + } + + private addIterable(parent: VariableContext, expression: DmnSome | DmnEvery) { + if (expression.satisfies.expression) { + this.addInnerExpression(parent, expression.satisfies.expression); + } + if (expression.in.expression) { + this.addInnerExpression(parent, expression.in.expression); + } + } + + private addFor(parent: VariableContext, expression: DmnFor) { + if (expression.return.expression) { + this.addInnerExpression(parent, expression.return.expression); + } + if (expression.in.expression) { + this.addInnerExpression(parent, expression.in.expression); + } + } + + private addFilter(parent: VariableContext, expression: DmnFilter) { + if (expression.in.expression) { + this.addInnerExpression(parent, expression.in.expression); + } + if (expression.match.expression) { + this.addInnerExpression(parent, expression.match.expression); + } + } + private addInnerExpression( parent: VariableContext, expression: @@ -481,7 +517,11 @@ export class VariablesRepository { | DmnFunctionDefinition | DmnRelation | DmnList - | UnsupportedDmnExpressions + | DmnFor + | DmnFilter + | DmnEvery + | DmnSome + | DmnConditional ) { switch (expression.__$$element) { case "literalExpression": @@ -512,6 +552,23 @@ export class VariablesRepository { this.addList(parent, expression); break; + case "conditional": + this.addConditional(parent, expression); + break; + + case "every": + case "some": + this.addIterable(parent, expression); + break; + + case "for": + this.addFor(parent, expression); + break; + + case "filter": + this.addFilter(parent, expression); + break; + default: // throw new Error("Unknown or not supported type for expression."); } diff --git a/packages/dmn-testing-models/install.js b/packages/dmn-testing-models/install.js index 6f6ba519d0d..1e1c38e2b32 100644 --- a/packages/dmn-testing-models/install.js +++ b/packages/dmn-testing-models/install.js @@ -22,6 +22,4 @@ const { setup } = require("@kie-tools/maven-config-setup-helper"); setup(` -Drevision=${buildEnv.env.dmnTestingModels.version} - -Dquarkus.platform.version=${buildEnv.env.quarkusPlatform.version} - -Dversion.org.kie.kogito=${buildEnv.env.kogitoRuntime.version} `); diff --git a/packages/dmn-testing-models/package.json b/packages/dmn-testing-models/package.json index d9e338e2ee1..8105ac9a720 100644 --- a/packages/dmn-testing-models/package.json +++ b/packages/dmn-testing-models/package.json @@ -23,8 +23,10 @@ "install": "node install.js", "powershell": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command" }, + "dependencies": { + "@kie-tools/maven-base": "workspace:*" + }, "devDependencies": { - "@kie-tools/maven-base": "workspace:*", "@kie-tools/maven-config-setup-helper": "workspace:*", "@kie-tools/root-env": "workspace:*", "copyfiles": "^2.4.1", diff --git a/packages/dmn-testing-models/pom.xml b/packages/dmn-testing-models/pom.xml index cf5273e8a7a..375bd3f7310 100644 --- a/packages/dmn-testing-models/pom.xml +++ b/packages/dmn-testing-models/pom.xml @@ -23,18 +23,16 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > - - org.kie - kie-tools-maven-base - ${revision} - ./node_modules/@kie-tools/maven-base/pom.xml - + + org.kie + kie-tools-maven-base + ${revision} + ./node_modules/@kie-tools/maven-base/pom.xml + 4.0.0 org.kie.tools dmn-testing-models - ${revision} - jar DMN Testing Models Testing models for DMN marshaller @@ -47,45 +45,7 @@ - - scm:git:git@github.com:apache/incubator-kie-tools.git - scm:git:git@github.com:apache/incubator-kie-tools.git - scm:git:git@github.com:apache/incubator-kie-tools.git - - - - - - central - Central Repository - https://repo.maven.apache.org/maven2 - default - - false - - - - apache-public-repository-group - Apache Public Repository Group - https://repository.apache.org/content/groups/public/ - - true - never - - - true - daily - - - - - UTF-8 - UTF-8 3.6.1 diff --git a/packages/dmn-vscode-extension/package.json b/packages/dmn-vscode-extension/package.json index a672effb66f..fb774e131ce 100644 --- a/packages/dmn-vscode-extension/package.json +++ b/packages/dmn-vscode-extension/package.json @@ -31,8 +31,7 @@ "@kie-tools-core/patternfly-base": "workspace:*", "@kie-tools-core/vscode-extension": "workspace:*", "@kie-tools/dmn-editor-envelope": "workspace:*", - "@kie-tools/kie-bc-editors": "workspace:*", - "@kie-tools/vscode-java-code-completion-extension-plugin": "workspace:*" + "@kie-tools/kie-bc-editors": "workspace:*" }, "devDependencies": { "@kie-tools-core/webpack-base": "workspace:*", @@ -40,6 +39,7 @@ "@kie-tools/root-env": "workspace:*", "@kie-tools/stunner-editors": "workspace:*", "@kie-tools/tsconfig": "workspace:*", + "@kie-tools/vscode-java-code-completion-extension-plugin": "workspace:*", "@types/vscode": "1.67.0", "@vscode/test-web": "^0.0.30", "@vscode/vsce": "^2.22.0", diff --git a/packages/editor/src/envelope/LoadingScreen/LoadingScreen.tsx b/packages/editor/src/envelope/LoadingScreen/LoadingScreen.tsx index 7a1a89cefe9..722e192d171 100644 --- a/packages/editor/src/envelope/LoadingScreen/LoadingScreen.tsx +++ b/packages/editor/src/envelope/LoadingScreen/LoadingScreen.tsx @@ -24,7 +24,7 @@ import { Title } from "@patternfly/react-core/dist/js/components/Title"; import { Bullseye } from "@patternfly/react-core/dist/js/layouts/Bullseye"; import { useEditorEnvelopeI18nContext } from "../i18n"; -export function LoadingScreen(props: { loading: boolean }) { +export function LoadingScreen(props: { loading: boolean; styleTag?: string }) { const [mustRender, setMustRender] = useState(true); const { i18n } = useEditorEnvelopeI18nContext(); @@ -47,9 +47,11 @@ export function LoadingScreen(props: { loading: boolean }) { } }, [props.loading]); + const style = (props.styleTag ? `${props.styleTag} ` : "") + "kie-tools--loading-screen"; + return ( (mustRender && ( -
    +
    + + org.kie + kie-tools-maven-base + ${revision} + ./node_modules/@kie-tools/maven-base/pom.xml + 4.0.0 org.kie.tools extended-services-java - ${revision} - jar Extended Services - Java Extended Services - Java @@ -40,65 +44,10 @@ - - scm:git:git@github.com:apache/incubator-kie-tools.git - scm:git:git@github.com:apache/incubator-kie-tools.git - scm:git:git@github.com:apache/incubator-kie-tools.git - - - - - - central - Central Repository - https://repo.maven.apache.org/maven2 - default - - false - - - - apache-public-repository-group - Apache Public Repository Group - https://repository.apache.org/content/groups/public/ - - true - never - - - true - daily - - - - - 3.12.1 - true - 17 - 17 - UTF-8 - UTF-8 - 3.2.5 - 4.13.2 + org.kie.tools.extended-services - - - - io.quarkus - quarkus-bom - ${quarkus.platform.version} - pom - import - - - - org.kie.kogito diff --git a/packages/jbpm-quarkus-devui/env/index.js b/packages/jbpm-quarkus-devui/env/index.js index e093fcea57d..6982d036d6f 100644 --- a/packages/jbpm-quarkus-devui/env/index.js +++ b/packages/jbpm-quarkus-devui/env/index.js @@ -19,7 +19,7 @@ const { varsWithName, composeEnv } = require("@kie-tools-scripts/build-env"); -module.exports = composeEnv([require("@kie-tools/root-env/env")], { +module.exports = composeEnv([require("@kie-tools/root-env/env"), require("@kie-tools/maven-base/env")], { vars: varsWithName({}), get env() { return { diff --git a/packages/jbpm-quarkus-devui/install.js b/packages/jbpm-quarkus-devui/install.js index 986e7034e18..fbc73cb1c4c 100644 --- a/packages/jbpm-quarkus-devui/install.js +++ b/packages/jbpm-quarkus-devui/install.js @@ -22,6 +22,4 @@ const { setup } = require("@kie-tools/maven-config-setup-helper"); setup(` -Drevision=${buildEnv.env.jbpmQuarkusDevuiExtension.version} - -Dquarkus.platform.version=${buildEnv.env.quarkusPlatform.version} - -Dversion.org.kie.kogito=${buildEnv.env.kogitoRuntime.version} `); diff --git a/packages/jbpm-quarkus-devui/package.json b/packages/jbpm-quarkus-devui/package.json index c6b62f532cc..82542ed873e 100644 --- a/packages/jbpm-quarkus-devui/package.json +++ b/packages/jbpm-quarkus-devui/package.json @@ -17,8 +17,8 @@ "build:dev:darwin:linux": "mvn clean install -DskipTests", "build:dev:win32": "pnpm powershell \"mvn clean install -DskipTests \"", "build:prod": "pnpm lint && run-script-os", - "build:prod:darwin:linux": "mvn clean install -DskipTests=$(build-env tests.run --not) -Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)", - "build:prod:win32": "pnpm powershell \"mvn clean install `-DskipTests `-Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)\"", + "build:prod:darwin:linux": "mvn clean deploy -DdeployAtEnd -DskipTests=$(build-env tests.run --not) -Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures) -Dmaven.deploy.skip=$(build-env maven.deploy.skip)", + "build:prod:win32": "pnpm powershell \"mvn clean deploy `-DdeployAtEnd `-DskipTests `-Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures) `-Dmaven.deploy.skip=$(build-env maven.deploy.skip)\"", "install": "node install.js", "lint": "echo 'Linting'", "powershell": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command", @@ -26,8 +26,10 @@ "quarkus:dev:darwin:linux": "mvn clean package quarkus:dev -DskipTests", "quarkus:dev:win32": "mvn clean package quarkus:dev -DskipTests" }, + "dependencies": { + "@kie-tools/maven-base": "workspace:*" + }, "devDependencies": { - "@kie-tools/maven-base": "workspace:*", "@kie-tools/maven-config-setup-helper": "workspace:*", "@kie-tools/root-env": "workspace:*", "@kie-tools/runtime-tools-process-dev-ui-webapp": "workspace:*", diff --git a/packages/jbpm-quarkus-devui/pom.xml b/packages/jbpm-quarkus-devui/pom.xml index 48c40bf1cdc..56fee1070c3 100644 --- a/packages/jbpm-quarkus-devui/pom.xml +++ b/packages/jbpm-quarkus-devui/pom.xml @@ -29,7 +29,7 @@ org.kie kie-tools-maven-base ${revision} - ../maven-base/pom.xml + ./node_modules/@kie-tools/maven-base/pom.xml 4.0.0 diff --git a/packages/keyboard-shortcuts/src/envelope/DefaultKeyboardShortcutsService.ts b/packages/keyboard-shortcuts/src/envelope/DefaultKeyboardShortcutsService.ts index 164621f12d9..1a68e012b5d 100644 --- a/packages/keyboard-shortcuts/src/envelope/DefaultKeyboardShortcutsService.ts +++ b/packages/keyboard-shortcuts/src/envelope/DefaultKeyboardShortcutsService.ts @@ -52,6 +52,7 @@ const KEY_CODES = new Map([ ["esc", "Escape"], ["delete", "Delete"], ["backspace", "Backspace"], + ["space", "Space"], ["right", "ArrowRight"], ["left", "ArrowLeft"], ["up", "ArrowUp"], diff --git a/packages/kie-sandbox-extended-services-image/package.json b/packages/kie-sandbox-extended-services-image/package.json index 6d40075a6d4..3deefc031b5 100644 --- a/packages/kie-sandbox-extended-services-image/package.json +++ b/packages/kie-sandbox-extended-services-image/package.json @@ -18,8 +18,8 @@ "cleanup": "rimraf dist-dev && mkdir dist-dev", "copy:assets": "pnpm copy:extended-services-java", "copy:extended-services-java": "run-script-os", - "copy:extended-services-java:linux:darwin": "cp -R ../extended-services-java/dist/extended-services-java ./dist-dev/kie_sandbox_extended_services", - "copy:extended-services-java:win32": "pnpm powershell \"Copy-Item ../extended-services-java/dist/extended-services-java ./dist-dev/kie_sandbox_extended_services\"", + "copy:extended-services-java:linux:darwin": "cp -R ./node_modules/@kie-tools/extended-services-java/dist/extended-services-java ./dist-dev/kie_sandbox_extended_services", + "copy:extended-services-java:win32": "pnpm powershell \"Copy-Item ./node_modules/@kie-tools/extended-services-java/dist/extended-services-java ./dist-dev/kie_sandbox_extended_services\"", "image:docker:build": "kie-tools--image-builder build -r \"$(build-env extendedServicesImage.registry)\" -a \"$(build-env extendedServicesImage.account)\" -n \"$(build-env extendedServicesImage.name)\" -t \"$(build-env extendedServicesImage.buildTags)\" --build-arg BUILDER_IMAGE_ARG=\"$(build-env extendedServicesImage.builderImage)\" --build-arg \"EXTENDED_SERVICES_DEFAULT_PORT=$(build-env extendedServicesImage.port)\" ", "image:podman:build": "kie-tools--image-builder build -r \"$(build-env extendedServicesImage.registry)\" -a \"$(build-env extendedServicesImage.account)\" -n \"$(build-env extendedServicesImage.name)\" -t \"$(build-env extendedServicesImage.buildTags)\" --build-arg BUILDER_IMAGE_ARG=\"$(build-env extendedServicesImage.builderImage)\" --build-arg \"EXTENDED_SERVICES_DEFAULT_PORT=$(build-env extendedServicesImage.port)\" -e podman" }, diff --git a/packages/kie-sandbox-image/Containerfile b/packages/kie-sandbox-image/Containerfile index 7083e360680..10b6b10317c 100644 --- a/packages/kie-sandbox-image/Containerfile +++ b/packages/kie-sandbox-image/Containerfile @@ -5,15 +5,15 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations -# under the License. +# under the License. FROM --platform=linux/amd64 registry.access.redhat.com/ubi9/ubi-minimal:9.3 @@ -21,7 +21,7 @@ ARG KIE_SANDBOX_DEFAULT_PORT=8080 COPY entrypoint.sh dist-dev/image-env-to-json-standalone dist-dev/EnvJson.schema.json /tmp/ -RUN microdnf --disableplugin=subscription-manager -y install httpd-2.4.57-5.el9.x86_64 \ +RUN microdnf --disableplugin=subscription-manager -y install httpd \ && microdnf --disableplugin=subscription-manager clean all \ && echo "Mutex posixsem" >> /etc/httpd/conf/httpd.conf \ && sed -i "s/Listen 80/Listen $KIE_SANDBOX_DEFAULT_PORT/g" /etc/httpd/conf/httpd.conf \ diff --git a/packages/kie-sandbox-image/package.json b/packages/kie-sandbox-image/package.json index 350ae39d4bf..1cc99a56ef2 100644 --- a/packages/kie-sandbox-image/package.json +++ b/packages/kie-sandbox-image/package.json @@ -18,11 +18,11 @@ "cleanup": "rimraf dist-dev && mkdir dist-dev", "copy:assets": "pnpm copy:online-editor && pnpm copy:image-env-to-json", "copy:image-env-to-json": "run-script-os", - "copy:image-env-to-json:linux:darwin": "cp ../image-env-to-json/dist/linux/image-env-to-json-standalone ./dist-dev/", - "copy:image-env-to-json:win32": "pnpm powershell \"Copy-Item ../image-env-to-json/dist/linux/image-env-to-json-standalone ./dist-dev/\"", + "copy:image-env-to-json:linux:darwin": "cp ./node_modules/@kie-tools/image-env-to-json/dist/linux/image-env-to-json-standalone ./dist-dev/", + "copy:image-env-to-json:win32": "pnpm powershell \"Copy-Item ./node_modules/@kie-tools/image-env-to-json/dist/linux/image-env-to-json-standalone ./dist-dev/\"", "copy:online-editor": "run-script-os", - "copy:online-editor:linux:darwin": "cp -R ../online-editor/dist ./dist-dev/online-editor", - "copy:online-editor:win32": "pnpm powershell \"Copy-Item -R ../online-editor/dist ./dist-dev/online-editor\"", + "copy:online-editor:linux:darwin": "cp -R ./node_modules/@kie-tools/online-editor/dist/ ./dist-dev/online-editor", + "copy:online-editor:win32": "pnpm powershell \"Copy-Item -R ./node_modules/@kie-tools/online-editor/dist/ ./dist-dev/online-editor\"", "env-json:schema:generate": "ts-json-schema-generator --path ./node_modules/@kie-tools/online-editor/src/env/EnvJson.ts --type EnvJson --id EnvJson --out ./dist-dev/EnvJson.schema.json", "image:docker:build": "kie-tools--image-builder build -r \"$(build-env kieSandbox.image.registry)\" -a \"$(build-env kieSandbox.image.account)\" -n \"$(build-env kieSandbox.image.name)\" -t \"$(build-env kieSandbox.image.buildTags)\" --build-arg \"KIE_SANDBOX_DEFAULT_PORT=$(build-env kieSandbox.image.port)\"", "image:podman:build": "kie-tools--image-builder build -r \"$(build-env kieSandbox.image.registry)\" -a \"$(build-env kieSandbox.image.account)\" -n \"$(build-env kieSandbox.image.name)\" -t \"$(build-env kieSandbox.image.buildTags)\" --build-arg \"KIE_SANDBOX_DEFAULT_PORT=$(build-env kieSandbox.image.port)\" -e podman" diff --git a/packages/kn-plugin-workflow/Makefile b/packages/kn-plugin-workflow/Makefile index 4373234ac5d..b5657d347a0 100644 --- a/packages/kn-plugin-workflow/Makefile +++ b/packages/kn-plugin-workflow/Makefile @@ -5,15 +5,15 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations -# under the License. +# under the License. BIN := kn-workflow BIN_DARWIN_AMD64 ?= $(BIN)-darwin-amd64 @@ -28,7 +28,7 @@ MAIN_PATH := cmd/main.go METADATA_PATH := github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/metadata SET_QUARKUS_PLATFORM_GROUP_ID := $(METADATA_PATH).QuarkusPlatformGroupId=$(QUARKUS_PLATFORM_GROUP_ID) SET_QUARKUS_VERSION := $(METADATA_PATH).QuarkusVersion=$(QUARKUS_VERSION) -SET_DEV_MODE_IMAGE := $(METADATA_PATH).DevModeImage=$(DEV_MODE_IMAGE) +SET_DEV_MODE_IMAGE := $(METADATA_PATH).DevModeImage=$(DEV_MODE_IMAGE_URL) SET_VERSION := $(METADATA_PATH).PluginVersion=$(PLUGIN_VERSION) SET_KOGITO_VERSION := $(METADATA_PATH).KogitoVersion=$(KOGITO_VERSION) LDFLAGS := "-X $(SET_QUARKUS_PLATFORM_GROUP_ID) -X $(SET_QUARKUS_VERSION) -X $(SET_VERSION) -X $(SET_DEV_MODE_IMAGE) -X $(SET_KOGITO_VERSION)" diff --git a/packages/kn-plugin-workflow/env/index.js b/packages/kn-plugin-workflow/env/index.js index 4773dc817e2..bdf6caf84b6 100644 --- a/packages/kn-plugin-workflow/env/index.js +++ b/packages/kn-plugin-workflow/env/index.js @@ -19,8 +19,10 @@ const { varsWithName, getOrDefault, composeEnv } = require("@kie-tools-scripts/build-env"); const packageJson = require("@kie-tools/kn-plugin-workflow/package.json"); +const rootEnv = require("@kie-tools/root-env/env"); +const kogitoSwfDevModeEnv = require("@kie-tools/kogito-swf-devmode/env"); -module.exports = composeEnv([require("@kie-tools/root-env/env")], { +module.exports = composeEnv([rootEnv, kogitoSwfDevModeEnv], { vars: varsWithName({ KN_PLUGIN_WORKFLOW__version: { name: "KN_PLUGIN_WORKFLOW__version", @@ -32,10 +34,9 @@ module.exports = composeEnv([require("@kie-tools/root-env/env")], { default: "io.quarkus.platform", description: "Quarkus group to be used when creating the SonataFlow project", }, - KN_PLUGIN_WORKFLOW__devModeImage: { - name: "KN_PLUGIN_WORKFLOW__devModeImage", - default: "quay.io/kiegroup/kogito-swf-devmode-nightly:999-20240417", - description: "SonataFlow dev mode image (used on cli run)", + KN_PLUGIN_WORKFLOW__devModeImageUrl: { + default: `${kogitoSwfDevModeEnv.env.kogitoSwfDevMode.registry}/${kogitoSwfDevModeEnv.env.kogitoSwfDevMode.account}/${kogitoSwfDevModeEnv.env.kogitoSwfDevMode.name}:${kogitoSwfDevModeEnv.env.kogitoSwfDevMode.tag}`, + description: "Kogito SWF DevMode image URL.", }, }), get env() { @@ -43,7 +44,7 @@ module.exports = composeEnv([require("@kie-tools/root-env/env")], { knPluginWorkflow: { version: getOrDefault(this.vars.KN_PLUGIN_WORKFLOW__version), quarkusPlatformGroupId: getOrDefault(this.vars.KN_PLUGIN_WORKFLOW__quarkusPlatformGroupId), - devModeImage: getOrDefault(this.vars.KN_PLUGIN_WORKFLOW__devModeImage), + devModeImageUrl: getOrDefault(this.vars.KN_PLUGIN_WORKFLOW__devModeImageUrl), }, }; }, diff --git a/packages/kn-plugin-workflow/go.mod b/packages/kn-plugin-workflow/go.mod index 6305a2625b1..e2fc64ec699 100644 --- a/packages/kn-plugin-workflow/go.mod +++ b/packages/kn-plugin-workflow/go.mod @@ -4,10 +4,12 @@ go 1.21 toolchain go1.21.6 -replace github.com/apache/incubator-kie-kogito-serverless-operator/api v0.0.0 => github.com/apache/incubator-kie-kogito-serverless-operator/api v0.0.0-20240126134605-2b5056d12bb9 +replace github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api v0.0.0 => ./node_modules/@kie-tools/kogito-serverless-operator/api + +replace github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj v0.0.0 => ./node_modules/@kie-tools/kogito-serverless-operator/workflowproj require ( - github.com/apache/incubator-kie-kogito-serverless-operator/workflowproj v0.0.0-20240122.0.20240219180504-5ebaf85efc66 + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj v0.0.0 github.com/beevik/etree v1.2.0 github.com/docker/docker v24.0.9+incompatible github.com/docker/go-connections v0.4.0 @@ -22,7 +24,7 @@ require ( require ( github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/apache/incubator-kie-kogito-serverless-operator/api v0.0.0 // indirect + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api v0.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect @@ -85,14 +87,14 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect - golang.org/x/crypto v0.17.0 // indirect + golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/mod v0.13.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/oauth2 v0.13.0 // indirect golang.org/x/sync v0.4.0 // indirect - golang.org/x/sys v0.15.0 // indirect - golang.org/x/term v0.15.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.14.0 // indirect diff --git a/packages/kn-plugin-workflow/go.sum b/packages/kn-plugin-workflow/go.sum index eac353d27e6..0cf4f136e98 100644 --- a/packages/kn-plugin-workflow/go.sum +++ b/packages/kn-plugin-workflow/go.sum @@ -43,10 +43,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/apache/incubator-kie-kogito-serverless-operator/api v0.0.0-20240126134605-2b5056d12bb9 h1:LrUW2+TRA8t0ttZTWjrDFW+gSWKaGWU2Led+RJiGUn8= -github.com/apache/incubator-kie-kogito-serverless-operator/api v0.0.0-20240126134605-2b5056d12bb9/go.mod h1:pve19HflUPuWGb8jzBaFqrZU8DWnRG2hpcRyo3w9shQ= -github.com/apache/incubator-kie-kogito-serverless-operator/workflowproj v0.0.0-20240122.0.20240219180504-5ebaf85efc66 h1:z7qKamBtG5Y2ZqWuW1O+MNBeOLndLoaYqW5ypDjcKZA= -github.com/apache/incubator-kie-kogito-serverless-operator/workflowproj v0.0.0-20240122.0.20240219180504-5ebaf85efc66/go.mod h1:Vw5jMxj6TmDe0TOrVkcVdlquOX1z8SP9rd+wzVMqmnY= github.com/beevik/etree v1.2.0 h1:l7WETslUG/T+xOPs47dtd6jov2Ii/8/OjCldk5fYfQw= github.com/beevik/etree v1.2.0/go.mod h1:aiPf89g/1k3AShMVAzriilpcE4R/Vuor90y83zVZWFc= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -396,8 +392,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -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.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= 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= @@ -473,8 +469,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 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= @@ -545,12 +541,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= 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= diff --git a/packages/kn-plugin-workflow/go.work b/packages/kn-plugin-workflow/go.work deleted file mode 100644 index f818bf29602..00000000000 --- a/packages/kn-plugin-workflow/go.work +++ /dev/null @@ -1,5 +0,0 @@ -go 1.21 - -toolchain go1.21 - -use . diff --git a/packages/kn-plugin-workflow/go.work.sum b/packages/kn-plugin-workflow/go.work.sum deleted file mode 100644 index ef7581b5d41..00000000000 --- a/packages/kn-plugin-workflow/go.work.sum +++ /dev/null @@ -1,823 +0,0 @@ -cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= -cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= -cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= -cloud.google.com/go v0.110.6/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= -cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= -cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= -cloud.google.com/go/accessapproval v1.7.1/go.mod h1:JYczztsHRMK7NTXb6Xw+dwbs/WnOJxbo/2mTI+Kgg68= -cloud.google.com/go/accesscontextmanager v1.8.1/go.mod h1:JFJHfvuaTC+++1iL1coPiG1eu5D24db2wXCDWDjIrxo= -cloud.google.com/go/aiplatform v1.50.0/go.mod h1:IRc2b8XAMTa9ZmfJV1BCCQbieWWvDnP1A8znyz5N7y4= -cloud.google.com/go/analytics v0.21.3/go.mod h1:U8dcUtmDmjrmUTnnnRnI4m6zKn/yaA5N9RlEkYFHpQo= -cloud.google.com/go/apigateway v1.6.1/go.mod h1:ufAS3wpbRjqfZrzpvLC2oh0MFlpRJm2E/ts25yyqmXA= -cloud.google.com/go/apigeeconnect v1.6.1/go.mod h1:C4awq7x0JpLtrlQCr8AzVIzAaYgngRqWf9S5Uhg+wWs= -cloud.google.com/go/apigeeregistry v0.7.1/go.mod h1:1XgyjZye4Mqtw7T9TsY4NW10U7BojBvG4RMD+vRDrIw= -cloud.google.com/go/appengine v1.8.1/go.mod h1:6NJXGLVhZCN9aQ/AEDvmfzKEfoYBlfB80/BHiKVputY= -cloud.google.com/go/area120 v0.8.1/go.mod h1:BVfZpGpB7KFVNxPiQBuHkX6Ed0rS51xIgmGyjrAfzsg= -cloud.google.com/go/artifactregistry v1.14.1/go.mod h1:nxVdG19jTaSTu7yA7+VbWL346r3rIdkZ142BSQqhn5E= -cloud.google.com/go/asset v1.14.1/go.mod h1:4bEJ3dnHCqWCDbWJ/6Vn7GVI9LerSi7Rfdi03hd+WTQ= -cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0= -cloud.google.com/go/automl v1.13.1/go.mod h1:1aowgAHWYZU27MybSCFiukPO7xnyawv7pt3zK4bheQE= -cloud.google.com/go/baremetalsolution v1.2.0/go.mod h1:68wi9AwPYkEWIUT4SvSGS9UJwKzNpshjHsH4lzk8iOw= -cloud.google.com/go/batch v1.4.1/go.mod h1:KdBmDD61K0ovcxoRHGrN6GmOBWeAOyCgKD0Mugx4Fkk= -cloud.google.com/go/beyondcorp v1.0.0/go.mod h1:YhxDWw946SCbmcWo3fAhw3V4XZMSpQ/VYfcKGAEU8/4= -cloud.google.com/go/bigquery v1.8.0 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA= -cloud.google.com/go/bigquery v1.55.0/go.mod h1:9Y5I3PN9kQWuid6183JFhOGOW3GcirA5LpsKCUn+2ec= -cloud.google.com/go/billing v1.17.0/go.mod h1:Z9+vZXEq+HwH7bhJkyI4OQcR6TSbeMrjlpEjO2vzY64= -cloud.google.com/go/binaryauthorization v1.7.0/go.mod h1:Zn+S6QqTMn6odcMU1zDZCJxPjU2tZPV1oDl45lWY154= -cloud.google.com/go/certificatemanager v1.7.1/go.mod h1:iW8J3nG6SaRYImIa+wXQ0g8IgoofDFRp5UMzaNk1UqI= -cloud.google.com/go/channel v1.17.0/go.mod h1:RpbhJsGi/lXWAUM1eF4IbQGbsfVlg2o8Iiy2/YLfVT0= -cloud.google.com/go/cloudbuild v1.14.0/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU= -cloud.google.com/go/clouddms v1.7.0/go.mod h1:MW1dC6SOtI/tPNCciTsXtsGNEM0i0OccykPvv3hiYeM= -cloud.google.com/go/cloudtasks v1.12.1/go.mod h1:a9udmnou9KO2iulGscKR0qBYjreuX8oHwpmFsKspEvM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -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/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -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/contactcenterinsights v1.10.0/go.mod h1:bsg/R7zGLYMVxFFzfh9ooLTruLRCG9fnzhH9KznHhbM= -cloud.google.com/go/container v1.26.0/go.mod h1:YJCmRet6+6jnYYRS000T6k0D0xUXQgBSaJ7VwI8FBj4= -cloud.google.com/go/containeranalysis v0.11.0/go.mod h1:4n2e99ZwpGxpNcz+YsFT1dfOHPQFGcAC8FN2M2/ne/U= -cloud.google.com/go/datacatalog v1.17.1/go.mod h1:nCSYFHgtxh2MiEktWIz71s/X+7ds/UT9kp0PC7waCzE= -cloud.google.com/go/dataflow v0.9.1/go.mod h1:Wp7s32QjYuQDWqJPFFlnBKhkAtiFpMTdg00qGbnIHVw= -cloud.google.com/go/dataform v0.8.1/go.mod h1:3BhPSiw8xmppbgzeBbmDvmSWlwouuJkXsXsb8UBih9M= -cloud.google.com/go/datafusion v1.7.1/go.mod h1:KpoTBbFmoToDExJUso/fcCiguGDk7MEzOWXUsJo0wsI= -cloud.google.com/go/datalabeling v0.8.1/go.mod h1:XS62LBSVPbYR54GfYQsPXZjTW8UxCK2fkDciSrpRFdY= -cloud.google.com/go/dataplex v1.9.1/go.mod h1:7TyrDT6BCdI8/38Uvp0/ZxBslOslP2X2MPDucliyvSE= -cloud.google.com/go/dataproc/v2 v2.2.0/go.mod h1:lZR7AQtwZPvmINx5J87DSOOpTfof9LVZju6/Qo4lmcY= -cloud.google.com/go/dataqna v0.8.1/go.mod h1:zxZM0Bl6liMePWsHA8RMGAfmTG34vJMapbHAxQ5+WA8= -cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ= -cloud.google.com/go/datastore v1.14.0/go.mod h1:GAeStMBIt9bPS7jMJA85kgkpsMkvseWWXiaHya9Jes8= -cloud.google.com/go/datastream v1.10.0/go.mod h1:hqnmr8kdUBmrnk65k5wNRoHSCYksvpdZIcZIEl8h43Q= -cloud.google.com/go/deploy v1.13.0/go.mod h1:tKuSUV5pXbn67KiubiUNUejqLs4f5cxxiCNCeyl0F2g= -cloud.google.com/go/dialogflow v1.43.0/go.mod h1:pDUJdi4elL0MFmt1REMvFkdsUTYSHq+rTCS8wg0S3+M= -cloud.google.com/go/dlp v1.10.1/go.mod h1:IM8BWz1iJd8njcNcG0+Kyd9OPnqnRNkDV8j42VT5KOI= -cloud.google.com/go/documentai v1.22.1/go.mod h1:LKs22aDHbJv7ufXuPypzRO7rG3ALLJxzdCXDPutw4Qc= -cloud.google.com/go/domains v0.9.1/go.mod h1:aOp1c0MbejQQ2Pjf1iJvnVyT+z6R6s8pX66KaCSDYfE= -cloud.google.com/go/edgecontainer v1.1.1/go.mod h1:O5bYcS//7MELQZs3+7mabRqoWQhXCzenBu0R8bz2rwk= -cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= -cloud.google.com/go/essentialcontacts v1.6.2/go.mod h1:T2tB6tX+TRak7i88Fb2N9Ok3PvY3UNbUsMag9/BARh4= -cloud.google.com/go/eventarc v1.13.0/go.mod h1:mAFCW6lukH5+IZjkvrEss+jmt2kOdYlN8aMx3sRJiAI= -cloud.google.com/go/filestore v1.7.1/go.mod h1:y10jsorq40JJnjR/lQ8AfFbbcGlw3g+Dp8oN7i7FjV4= -cloud.google.com/go/firestore v1.13.0/go.mod h1:QojqqOh8IntInDUSTAh0c8ZsPYAr68Ma8c5DWOy8xb8= -cloud.google.com/go/functions v1.15.1/go.mod h1:P5yNWUTkyU+LvW/S9O6V+V423VZooALQlqoXdoPz5AE= -cloud.google.com/go/gkebackup v1.3.1/go.mod h1:vUDOu++N0U5qs4IhG1pcOnD1Mac79xWy6GoBFlWCWBU= -cloud.google.com/go/gkeconnect v0.8.1/go.mod h1:KWiK1g9sDLZqhxB2xEuPV8V9NYzrqTUmQR9shJHpOZw= -cloud.google.com/go/gkehub v0.14.1/go.mod h1:VEXKIJZ2avzrbd7u+zeMtW00Y8ddk/4V9511C9CQGTY= -cloud.google.com/go/gkemulticloud v1.0.0/go.mod h1:kbZ3HKyTsiwqKX7Yw56+wUGwwNZViRnxWK2DVknXWfw= -cloud.google.com/go/gsuiteaddons v1.6.1/go.mod h1:CodrdOqRZcLp5WOwejHWYBjZvfY0kOphkAKpF/3qdZY= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= -cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk= -cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= -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/iap v1.9.0/go.mod h1:01OFxd1R+NFrg78S+hoPV5PxEzv22HXaNqUUlmNHFuY= -cloud.google.com/go/ids v1.4.1/go.mod h1:np41ed8YMU8zOgv53MMMoCntLTn2lF+SUzlM+O3u/jw= -cloud.google.com/go/iot v1.7.1/go.mod h1:46Mgw7ev1k9KqK1ao0ayW9h0lI+3hxeanz+L1zmbbbk= -cloud.google.com/go/kms v1.15.2/go.mod h1:3hopT4+7ooWRCjc2DxgnpESFxhIraaI2IpAVUEhbT/w= -cloud.google.com/go/language v1.11.0/go.mod h1:uDx+pFDdAKTY8ehpWbiXyQdz8tDSYLJbQcXsCkjYyvQ= -cloud.google.com/go/lifesciences v0.9.1/go.mod h1:hACAOd1fFbCGLr/+weUKRAJas82Y4vrL3O5326N//Wc= -cloud.google.com/go/logging v1.8.1/go.mod h1:TJjR+SimHwuC8MZ9cjByQulAMgni+RkXeI3wwctHJEI= -cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc= -cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= -cloud.google.com/go/managedidentities v1.6.1/go.mod h1:h/irGhTN2SkZ64F43tfGPMbHnypMbu4RB3yl8YcuEak= -cloud.google.com/go/maps v1.4.0/go.mod h1:6mWTUv+WhnOwAgjVsSW2QPPECmW+s3PcRyOa9vgG/5s= -cloud.google.com/go/mediatranslation v0.8.1/go.mod h1:L/7hBdEYbYHQJhX2sldtTO5SZZ1C1vkapubj0T2aGig= -cloud.google.com/go/memcache v1.10.1/go.mod h1:47YRQIarv4I3QS5+hoETgKO40InqzLP6kpNLvyXuyaA= -cloud.google.com/go/metastore v1.12.0/go.mod h1:uZuSo80U3Wd4zi6C22ZZliOUJ3XeM/MlYi/z5OAOWRA= -cloud.google.com/go/monitoring v1.16.0/go.mod h1:Ptp15HgAyM1fNICAojDMoNc/wUmn67mLHQfyqbw+poY= -cloud.google.com/go/networkconnectivity v1.13.0/go.mod h1:SAnGPes88pl7QRLUen2HmcBSE9AowVAcdug8c0RSBFk= -cloud.google.com/go/networkmanagement v1.9.0/go.mod h1:UTUaEU9YwbCAhhz3jEOHr+2/K/MrBk2XxOLS89LQzFw= -cloud.google.com/go/networksecurity v0.9.1/go.mod h1:MCMdxOKQ30wsBI1eI659f9kEp4wuuAueoC9AJKSPWZQ= -cloud.google.com/go/notebooks v1.10.0/go.mod h1:SOPYMZnttHxqot0SGSFSkRrwE29eqnKPBJFqgWmiK2k= -cloud.google.com/go/optimization v1.5.0/go.mod h1:evo1OvTxeBRBu6ydPlrIRizKY/LJKo/drDMMRKqGEUU= -cloud.google.com/go/orchestration v1.8.1/go.mod h1:4sluRF3wgbYVRqz7zJ1/EUNc90TTprliq9477fGobD8= -cloud.google.com/go/orgpolicy v1.11.1/go.mod h1:8+E3jQcpZJQliP+zaFfayC2Pg5bmhuLK755wKhIIUCE= -cloud.google.com/go/osconfig v1.12.1/go.mod h1:4CjBxND0gswz2gfYRCUoUzCm9zCABp91EeTtWXyz0tE= -cloud.google.com/go/oslogin v1.10.1/go.mod h1:x692z7yAue5nE7CsSnoG0aaMbNoRJRXO4sn73R+ZqAs= -cloud.google.com/go/phishingprotection v0.8.1/go.mod h1:AxonW7GovcA8qdEk13NfHq9hNx5KPtfxXNeUxTDxB6I= -cloud.google.com/go/policytroubleshooter v1.9.0/go.mod h1:+E2Lga7TycpeSTj2FsH4oXxTnrbHJGRlKhVZBLGgU64= -cloud.google.com/go/privatecatalog v0.9.1/go.mod h1:0XlDXW2unJXdf9zFz968Hp35gl/bhF4twwpXZAW50JA= -cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU= -cloud.google.com/go/pubsub v1.33.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc= -cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.2/go.mod h1:kR0KjsJS7Jt1YSyWFkseQ756D45kaYNTlDPPaRAvDBU= -cloud.google.com/go/recommendationengine v0.8.1/go.mod h1:MrZihWwtFYWDzE6Hz5nKcNz3gLizXVIDI/o3G1DLcrE= -cloud.google.com/go/recommender v1.11.0/go.mod h1:kPiRQhPyTJ9kyXPCG6u/dlPLbYfFlkwHNRwdzPVAoII= -cloud.google.com/go/redis v1.13.1/go.mod h1:VP7DGLpE91M6bcsDdMuyCm2hIpB6Vp2hI090Mfd1tcg= -cloud.google.com/go/resourcemanager v1.9.1/go.mod h1:dVCuosgrh1tINZ/RwBufr8lULmWGOkPS8gL5gqyjdT8= -cloud.google.com/go/resourcesettings v1.6.1/go.mod h1:M7mk9PIZrC5Fgsu1kZJci6mpgN8o0IUzVx3eJU3y4Jw= -cloud.google.com/go/retail v1.14.1/go.mod h1:y3Wv3Vr2k54dLNIrCzenyKG8g8dhvhncT2NcNjb/6gE= -cloud.google.com/go/run v1.2.0/go.mod h1:36V1IlDzQ0XxbQjUx6IYbw8H3TJnWvhii963WW3B/bo= -cloud.google.com/go/scheduler v1.10.1/go.mod h1:R63Ldltd47Bs4gnhQkmNDse5w8gBRrhObZ54PxgR2Oo= -cloud.google.com/go/secretmanager v1.11.1/go.mod h1:znq9JlXgTNdBeQk9TBW/FnR/W4uChEKGeqQWAJ8SXFw= -cloud.google.com/go/security v1.15.1/go.mod h1:MvTnnbsWnehoizHi09zoiZob0iCHVcL4AUBj76h9fXA= -cloud.google.com/go/securitycenter v1.23.0/go.mod h1:8pwQ4n+Y9WCWM278R8W3nF65QtY172h4S8aXyI9/hsQ= -cloud.google.com/go/servicedirectory v1.11.0/go.mod h1:Xv0YVH8s4pVOwfM/1eMTl0XJ6bzIOSLDt8f8eLaGOxQ= -cloud.google.com/go/shell v1.7.1/go.mod h1:u1RaM+huXFaTojTbW4g9P5emOrrmLE69KrxqQahKn4g= -cloud.google.com/go/spanner v1.49.0/go.mod h1:eGj9mQGK8+hkgSVbHNQ06pQ4oS+cyc4tXXd6Dif1KoM= -cloud.google.com/go/speech v1.19.0/go.mod h1:8rVNzU43tQvxDaGvqOhpDqgkJTFowBpDvCJ14kGlJYo= -cloud.google.com/go/storage v1.18.2/go.mod h1:AiIj7BWXyhO5gGVmYJ+S8tbkCx3yb0IMjua8Aw4naVM= -cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= -cloud.google.com/go/storage v1.32.0/go.mod h1:Hhh/dogNRGca7IWv1RC2YqEn0c0G77ctA/OxflYkiD8= -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/storagetransfer v1.10.0/go.mod h1:DM4sTlSmGiNczmV6iZyceIh2dbs+7z2Ayg6YAiQlYfA= -cloud.google.com/go/talent v1.6.2/go.mod h1:CbGvmKCG61mkdjcqTcLOkb2ZN1SrQI8MDyma2l7VD24= -cloud.google.com/go/texttospeech v1.7.1/go.mod h1:m7QfG5IXxeneGqTapXNxv2ItxP/FS0hCZBwXYqucgSk= -cloud.google.com/go/tpu v1.6.1/go.mod h1:sOdcHVIgDEEOKuqUoi6Fq53MKHJAtOwtz0GuKsWSH3E= -cloud.google.com/go/trace v1.10.1/go.mod h1:gbtL94KE5AJLH3y+WVpfWILmqgc6dXcqgNXdOPAQTYk= -cloud.google.com/go/translate v1.9.0/go.mod h1:d1ZH5aaOA0CNhWeXeC8ujd4tdCFw8XoNWRljklu5RHs= -cloud.google.com/go/video v1.20.0/go.mod h1:U3G3FTnsvAGqglq9LxgqzOiBc/Nt8zis8S+850N2DUM= -cloud.google.com/go/videointelligence v1.11.1/go.mod h1:76xn/8InyQHarjTWsBR058SmlPCwQjgcvoW0aZykOvo= -cloud.google.com/go/vision/v2 v2.7.2/go.mod h1:jKa8oSYBWhYiXarHPvP4USxYANYUEdEsQrloLjrSwJU= -cloud.google.com/go/vmmigration v1.7.1/go.mod h1:WD+5z7a/IpZ5bKK//YmT9E047AD+rjycCAvyMxGJbro= -cloud.google.com/go/vmwareengine v1.0.0/go.mod h1:Px64x+BvjPZwWuc4HdmVhoygcXqEkGHXoa7uyfTgSI0= -cloud.google.com/go/vpcaccess v1.7.1/go.mod h1:FogoD46/ZU+JUBX9D606X21EnxiszYi2tArQwLY4SXs= -cloud.google.com/go/webrisk v1.9.1/go.mod h1:4GCmXKcOa2BZcZPn6DCEvE7HypmEJcJkr4mtM+sqYPc= -cloud.google.com/go/websecurityscanner v1.6.1/go.mod h1:Njgaw3rttgRHXzwCB8kgCYqv5/rGpFCsBOvPbYgszpg= -cloud.google.com/go/workflows v1.12.0/go.mod h1:PYhSk2b6DhZ508tj8HXKaBh+OFe+xdl0dHF/tJdzPQM= -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.0/go.mod h1:o7cosnyfuPVK0tB8q0QmaQNhGnptITnPQB+z1+qeFB0= -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= -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= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -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/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 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= -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/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/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/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/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -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/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -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/census-instrumentation/opencensus-proto v0.3.0/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 v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= -github.com/cloudevents/sdk-go/sql/v2 v2.8.0/go.mod h1:u9acNJbhmi1wnDJro4PEAqbr4N1LTCyEUClErxbPS1A= -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.8.0/go.mod h1:GpCBmUj7DIRiDhVvsK5d6WCbgTWs8DxAWTRtAwQmIXs= -github.com/cloudevents/sdk-go/v2 v2.13.0 h1:2zxDS8RyY1/wVPULGGbdgniGXSzLaRJVl136fLXGsYw= -github.com/cloudevents/sdk-go/v2 v2.13.0/go.mod h1:xDmKfzNjM8gBvjaF8ijFjM1VYOVUEeUfapHMUX1T5To= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M= -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/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -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/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/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/dgryski/go-gk v0.0.0-20200319235926-a69029f61654/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -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.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad h1:EmNYJhPYy0pOFjCx2PrgtaBXmee0iUX9hLlxE1xHOJE= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= -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/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/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -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-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 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -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-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= -github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= -github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -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/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -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/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= -github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/cel-go v0.12.6/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw= -github.com/google/cel-go v0.16.0 h1:DG9YQ8nFCFXAs/FDDwBxmL1tpKNrdlGUM9U3537bX/Y= -github.com/google/cel-go v0.16.0/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= -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.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-containerregistry v0.8.1-0.20220414143355-892d7a808387/go.mod h1:eTLvLZaEe2FoQsb25t7BLxQQryyrwHTzFfwxN87mhAw= -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/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-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/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/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -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.1.0 h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= -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/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -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.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= -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/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -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/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8 h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -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/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= -github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/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.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -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 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjdKDqyr/2L+f6U12Fk= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -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 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI= -github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a/go.mod h1:9GkyshztGufsdPQWjH+ifgnIr3xNUL5syI70g2dzU1o= -github.com/influxdata/tdigest v0.0.1 h1:XpFptwYmnEKUqmkcDjrzffswZ3nvNeevbUSLPP/ZzIY= -github.com/influxdata/tdigest v0.0.1/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y= -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/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -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/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.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -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/kiegroup/kogito-serverless-operator/api v0.0.0-20230619124910-96f05158ba87 h1:RgW8XqqkibzzD4EXnqiFvKVxJ4BQFbF89GQLtDB1iWc= -github.com/kiegroup/kogito-serverless-operator/api v0.0.0-20230619124910-96f05158ba87/go.mod h1:5nAGodPBf6ebCjFtF7JKl40Ji0ptG0JwJNT/P0OupfE= -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/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/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -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/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -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-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 h1:rBhB9Rls+yb8kA4x5a/cWxOufWfXt24E+kq4YlbGj3g= -github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0/go.mod h1:fJ0UAZc1fx3xZhU4eSHQDJ1ApFmTVhp5VTpV9tm2ogg= -github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -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/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/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 h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= -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/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/ginkgo/v2 v2.9.4/go.mod h1:gCQYp2Q+kSoIj7ykSVb9nskRSsR6PUj4AiLywzIhbKM= -github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -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/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -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/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/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -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/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs= -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.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= -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.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -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/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.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/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= -github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= -github.com/prometheus/statsd_exporter v0.22.8 h1:Qo2D9ZzaQG+id9i5NYNGmbf1aa/KxKbB9aKfMS+Yib0= -github.com/prometheus/statsd_exporter v0.22.8/go.mod h1:/DzwbTEaFTE0Ojz5PqcSk6+PFHOPWGxdXVr6yC8eFOM= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rickb777/date v1.13.0/go.mod h1:GZf3LoGnxPWjX+/1TXOuzHefZFDovTyNLHDMd3qH70k= -github.com/rickb777/date v1.20.0 h1:oRGcq4b+ba12N/HnsVZuWSK/QJb/o/hnjOJEyRMGUT0= -github.com/rickb777/date v1.20.0/go.mod h1:8AR0TBrjDGUjwKToBI8L+RafzNg7gqlT0ox0cERCwEo= -github.com/rickb777/plural v1.2.1/go.mod h1:j058+3M5QQFgcZZ2oKIOekcygoZUL8gKW5yRO14BuAw= -github.com/rickb777/plural v1.4.1 h1:5MMLcbIaapLFmvDGRT5iPk8877hpTPt8Y9cdSKRw9sU= -github.com/rickb777/plural v1.4.1/go.mod h1:kdmXUpmKBJTS0FtG/TFumd//VBWsNTD7zOw7x4umxNw= -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.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -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/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -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/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -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/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= -github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU= -github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= -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/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= -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/vegeta/v12 v12.8.4/go.mod h1:ZiJtwLn/9M4fTPdMY7bdbIeyNeFVE8/AHbWFqCsUuho= -github.com/tsenart/vegeta/v12 v12.11.0/go.mod h1:YzY1ucY/V7QyR5ZVRqSMUkyuwgyqtXWQuEa2lVPzUeU= -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/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -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/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= -github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= -github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.etcd.io/etcd/api/v3 v3.5.7/go.mod h1:9qew1gCdDDLu+VwmeG+iFpL+QlpHTo7iubavdVDgCAA= -go.etcd.io/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs= -go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k= -go.etcd.io/etcd/client/pkg/v3 v3.5.7/go.mod h1:o0Abi1MK86iad3YrWhgUsbGx1pmTS+hrORWc2CamuhY= -go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE= -go.etcd.io/etcd/client/pkg/v3 v3.5.9/go.mod h1:y+CzeSmkMpWN2Jyu1npecjB9BBnABxGM4pN8cGuJeL4= -go.etcd.io/etcd/client/v2 v2.305.7/go.mod h1:GQGT5Z3TBuAQGvgPfhR7VPySu/SudxmEkRq9BgzFU6s= -go.etcd.io/etcd/client/v2 v2.305.9 h1:YZ2OLi0OvR0H75AcgSUajjd5uqKDKocQUqROTG11jIo= -go.etcd.io/etcd/client/v2 v2.305.9/go.mod h1:0NBdNx9wbxtEQLwAQtrDHwx58m02vXpDcgSYI2seohQ= -go.etcd.io/etcd/client/v3 v3.5.7/go.mod h1:sOWmj9DZUMyAngS7QQwCyAXXAL6WhgTOPLNS/NabQgw= -go.etcd.io/etcd/client/v3 v3.5.9 h1:r5xghnU7CwbUxD/fbUtRyJGaYNfDun8sp/gTr1hew6E= -go.etcd.io/etcd/client/v3 v3.5.9/go.mod h1:i/Eo5LrZ5IKqpbtpPDuaUnDOUv471oDg8cjQaUr2MbA= -go.etcd.io/etcd/pkg/v3 v3.5.7/go.mod h1:kcOfWt3Ov9zgYdOiJ/o1Y9zFfLhQjylTgL4Lru8opRo= -go.etcd.io/etcd/pkg/v3 v3.5.9 h1:6R2jg/aWd/zB9+9JxmijDKStGJAPFsX3e6BeJkMi6eQ= -go.etcd.io/etcd/pkg/v3 v3.5.9/go.mod h1:BZl0SAShQFk0IpLWR78T/+pyt8AruMHhTNNX73hkNVY= -go.etcd.io/etcd/raft/v3 v3.5.7/go.mod h1:TflkAb/8Uy6JFBxcRaH2Fr6Slm9mCPVdI2efzxY96yU= -go.etcd.io/etcd/raft/v3 v3.5.9 h1:ZZ1GIHoUlHsn0QVqiRysAm3/81Xx7+i2d7nSdWxlOiI= -go.etcd.io/etcd/raft/v3 v3.5.9/go.mod h1:WnFkqzFdZua4LVlVXQEGhmooLeyS7mqzS4Pf4BCVqXg= -go.etcd.io/etcd/server/v3 v3.5.7/go.mod h1:gxBgT84issUVBRpZ3XkW1T55NjOb4vZZRI4wVvNhf4A= -go.etcd.io/etcd/server/v3 v3.5.9 h1:vomEmmxeztLtS5OEH7d0hBAg4cjVIu9wXuNzUZx2ZA0= -go.etcd.io/etcd/server/v3 v3.5.9/go.mod h1:GgI1fQClQCFIzuVjlvdbMxNbnISt90gdfYyqiAIt65g= -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.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/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/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= -go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= -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/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/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/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/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpTNdY= -go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE= -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/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -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.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= -go.starlark.net v0.0.0-20220817180228-f738f5508c12 h1:xOBJXWGEDwU5xSDxH6macxO11Us0AH2fTa9rmsbbF7g= -go.starlark.net v0.0.0-20220817180228-f738f5508c12/go.mod h1:VZcBMdr3cT3PnBoWunTabuSEXwVAH+ZJ5zxfs3AdASk= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q= -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.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= -go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -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-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -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/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -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/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/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-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -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.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -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/sync v0.0.0-20210220032951-036812b2e83c/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.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/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-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/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-20210603081109-ebe580a85c40/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-20220114195835-da31bd327af9/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-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/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.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/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -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/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/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.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -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.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= -golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= -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= -gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -google.golang.org/api v0.25.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -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.132.0/go.mod h1:AeTBC6GpJnJSRJjktDcPX0QwtS8pGYZOV6MSuSCusw0= -google.golang.org/api v0.140.0/go.mod h1:aGbCiFgtwb2P6badchFbSBUurV6oR5d50Af4iNJtDdI= -google.golang.org/api v0.147.0 h1:Can3FaQo9LlVqxJCodNmeZW/ib3/qKAY3rFeXiHo5gc= -google.golang.org/api v0.147.0/go.mod h1:pQ/9j83DcmPd/5C9e2nFOdjjNkDZ1G+zkbK2uvdkJMs= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/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-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y= -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-20230920204549-e6e6cdab5c13/go.mod h1:CCviP9RmpZ1mxVr8MUjCnSiY09IbAXZxhLE6EhHIdPU= -google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= -google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= -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-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= -google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/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 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:itlFWGBbEyD32PUeJsTG8h8Wz7iJXfVK4gt1EJ+pAG0= -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-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -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-20230911183012-2d3300fd4832/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 h1:jHkCUWkseRf+W+edG5hMzr/Uh1xkDREY4caybAq4dpY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.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.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -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.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -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.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.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -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/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.1.0/go.mod h1:fHy7eyTmJFO5bQbUsEGQ1v4m2J3Jz9eWL54TP2/ZuYQ= -honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= -k8s.io/api v0.27.6/go.mod h1:AQYj0UsFCp3qJE7bOVnUuy4orCsXVkvHefnbYQiNWgk= -k8s.io/apiextensions-apiserver v0.27.6/go.mod h1:AVNlLYRrESG5Poo6ASRUhY2pvoKPcNt8y/IuZ4lx3o8= -k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE= -k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= -k8s.io/apimachinery v0.27.6/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= -k8s.io/apiserver v0.27.2/go.mod h1:EsOf39d75rMivgvvwjJ3OW/u9n1/BmUMK5otEOJrb1Y= -k8s.io/apiserver v0.28.1 h1:dw2/NKauDZCnOUAzIo2hFhtBRUo6gQK832NV8kuDbGM= -k8s.io/apiserver v0.28.1/go.mod h1:d8aizlSRB6yRgJ6PKfDkdwCy2DXt/d1FDR6iJN9kY1w= -k8s.io/cli-runtime v0.23.4/go.mod h1:7KywUNTUibmHPqmpDFuRO1kc9RhsufHv2lkjCm2YZyM= -k8s.io/cli-runtime v0.25.2 h1:XOx+SKRjBpYMLY/J292BHTkmyDffl/qOx3YSuFZkTuc= -k8s.io/cli-runtime v0.25.2/go.mod h1:OQx3+/0st6x5YpkkJQlEWLC73V0wHsOFMC1/roxV8Oc= -k8s.io/client-go v0.27.6/go.mod h1:PMsXcDKiJTW7PHJ64oEsIUJF319wm+EFlCj76oE5QXM= -k8s.io/code-generator v0.27.2/go.mod h1:DPung1sI5vBgn4AGKtlPRQAyagj/ir/4jI55ipZHVww= -k8s.io/code-generator v0.27.6/go.mod h1:DPung1sI5vBgn4AGKtlPRQAyagj/ir/4jI55ipZHVww= -k8s.io/code-generator v0.28.1 h1:o0WFcqtv80GEf1iaOAzLIlrKyny9HBd2jaspJfWb5sI= -k8s.io/code-generator v0.28.1/go.mod h1:ueeSJZJ61NHBa0ccWLey6mwawum25vX61nRZ6WOzN9A= -k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks= -k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.80.2-0.20221028030830-9ae4992afb54/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kms v0.27.2/go.mod h1:dahSqjI05J55Fo5qipzvHSRbm20d7llrSeQjjl86A7c= -k8s.io/kms v0.28.1 h1:QLNTIc0k7Yebkt9yobj9Y9qBoRCMB4dq+pFCxVXVBnY= -k8s.io/kms v0.28.1/go.mod h1:I2TwA8oerDRInHWWBOqSUzv1EJDC1+55FQKYkxaPxh0= -k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= -k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -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-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -knative.dev/eventing v0.31.0/go.mod h1:XgJY27IxyBjmu/mz53cVlz+oMPPzzRaVXlPmWKCqEd8= -knative.dev/eventing v0.38.1-0.20230808082134-e2555934d297 h1:gbSjy8pZz7MZ6dFpF/9tZzyacQJGF380vDPRtEe3zkA= -knative.dev/eventing v0.38.1-0.20230808082134-e2555934d297/go.mod h1:nikkNBn3jrJaccPQckf5CdNkWy2MkUId0cscbxKu+7Q= -knative.dev/hack v0.0.0-20230417170854-f591fea109b3/go.mod h1:yk2OjGDsbEnQjfxdm0/HJKS2WqTLEFg/N6nUs6Rqx3Q= -knative.dev/hack v0.0.0-20230818155117-9cc05a31e8c0/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/networking v0.0.0-20220412163509-1145ec58c8be/go.mod h1:6OZIUimxPelIIudzHWRd+Lc7ippC5t+DC8CsZKCOjcI= -knative.dev/networking v0.0.0-20230807014815-f25e82aa2005 h1:LyXnt3TI8wdh7+2T6GKOxFW8TmjtPfzOUkwf5Ujze40= -knative.dev/networking v0.0.0-20230807014815-f25e82aa2005/go.mod h1:wDDrwfgGSnn2NDcR169IUPBi96FzY9iSBS4Q05hOTX0= -knative.dev/serving v0.31.0/go.mod h1:ObA3YEL77+M60xu4T3cUSpD+AX5eZN6Ww0pHg8iA6NE= -knative.dev/serving v0.38.1-0.20230808044033-241a1e94dc43 h1:wn+X1yfyjwnjKGb/9osk5k6mygFHeQA82y6ZDOAIus4= -knative.dev/serving v0.38.1-0.20230808044033-241a1e94dc43/go.mod h1:Ph7Ucv0pNchTPsgOsR+vLrKytTyN3V7x0PYDQEoA06M= -rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= -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.1.2 h1:trsWhjU5jZrx6UvFu4WzQDrN7Pga4a7Qg+zcfcj64PA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2/go.mod h1:+qG7ISXqCDVVcyO8hLn12AKVYYUjM7ftlqsqmrhMZE0= -sigs.k8s.io/controller-runtime v0.14.4/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.10.1/go.mod h1:2FigT1QN6xKdcnGS2Ppp1uIWrtWN28Ms8A3OZUZhwr8= -sigs.k8s.io/kustomize/api v0.12.1 h1:7YM7gW3kYBwtKvoY216ZzY+8hM+lV53LUayghNRJ0vM= -sigs.k8s.io/kustomize/api v0.12.1/go.mod h1:y3JUhimkZkR6sbLNwfJHxvo1TCLwuwm14sCYnkH6S1s= -sigs.k8s.io/kustomize/kyaml v0.13.0/go.mod h1:FTJxEZ86ScK184NpGSAQcfEqee0nul8oLCK30D47m4E= -sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk= -sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/packages/kn-plugin-workflow/package.json b/packages/kn-plugin-workflow/package.json index a5595cd3e00..b29e43b21b2 100644 --- a/packages/kn-plugin-workflow/package.json +++ b/packages/kn-plugin-workflow/package.json @@ -39,8 +39,8 @@ "go:test:report": "go run github.com/jstemmer/go-junit-report/v2 -set-exit-code -in ./dist-tests/go-test-output.txt -out ./dist-tests/junit-report.xml", "install": "go mod tidy", "powershell": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command", - "setup:env": "cross-env QUARKUS_PLATFORM_GROUP_ID=$(build-env knPluginWorkflow.quarkusPlatformGroupId) QUARKUS_VERSION=$(build-env quarkusPlatform.version) PLUGIN_VERSION=$(build-env knPluginWorkflow.version) DEV_MODE_IMAGE=$(build-env knPluginWorkflow.devModeImage) KOGITO_VERSION=$(build-env kogitoRuntime.version)", - "setup:env:win32": "pnpm powershell \"cross-env QUARKUS_PLATFORM_GROUP_ID=$(build-env knPluginWorkflow.quarkusPlatformGroupId) QUARKUS_VERSION=$(build-env quarkusPlatform.version) DEV_MODE_IMAGE=$(build-env knPluginWorkflow.devModeImage) KOGITO_VERSION=$(build-env kogitoRuntime.version) PLUGIN_VERSION=$(build-env knPluginWorkflow.version)\"", + "setup:env": "cross-env QUARKUS_PLATFORM_GROUP_ID=$(build-env knPluginWorkflow.quarkusPlatformGroupId) QUARKUS_VERSION=$(build-env quarkusPlatform.version) PLUGIN_VERSION=$(build-env knPluginWorkflow.version) DEV_MODE_IMAGE_URL=$(build-env knPluginWorkflow.devModeImageUrl) KOGITO_VERSION=$(build-env kogitoRuntime.version)", + "setup:env:win32": "pnpm powershell \"cross-env QUARKUS_PLATFORM_GROUP_ID=$(build-env knPluginWorkflow.quarkusPlatformGroupId) QUARKUS_VERSION=$(build-env quarkusPlatform.version) DEV_MODE_IMAGE_URL=$(build-env knPluginWorkflow.devModeImageUrl) KOGITO_VERSION=$(build-env kogitoRuntime.version) PLUGIN_VERSION=$(build-env knPluginWorkflow.version)\"", "test": "run-script-if --ignore-errors \"$(build-env tests.ignoreFailures)\" --bool \"$(build-env tests.run)\" --then \"pnpm go:test\" \"pnpm go:test:report\"", "test:e2e": "run-script-if --ignore-errors \"$(build-env endToEndTests.ignoreFailures)\" --bool \"$(build-env endToEndTests.run)\" --then \"pnpm go:test:e2e\" \"pnpm go:test:e2e:report\"", "test:e2e:logs": "run-script-if --ignore-errors \"$(build-env endToEndTests.ignoreFailures)\" --bool \"$(build-env endToEndTests.run)\" --then \"pnpm go:test:e2e:logs\" \"pnpm go:test:e2e:report\"", @@ -50,6 +50,8 @@ "test:e2e:quarkus:logs": "run-script-if --ignore-errors \"$(build-env endToEndTests.ignoreFailures)\" --bool \"$(build-env endToEndTests.run)\" --then \"pnpm go:test:e2e:quarkus:logs\" \"pnpm go:test:e2e:report\"" }, "devDependencies": { + "@kie-tools/kogito-serverless-operator": "workspace:*", + "@kie-tools/kogito-swf-devmode": "workspace:*", "@kie-tools/root-env": "workspace:*", "cross-env": "^7.0.3", "rimraf": "^3.0.2", diff --git a/packages/kn-plugin-workflow/pkg/command/deploy_undeploy_common.go b/packages/kn-plugin-workflow/pkg/command/deploy_undeploy_common.go index 599fc01a24c..23cc79ffd17 100644 --- a/packages/kn-plugin-workflow/pkg/command/deploy_undeploy_common.go +++ b/packages/kn-plugin-workflow/pkg/command/deploy_undeploy_common.go @@ -24,9 +24,9 @@ import ( "os" "path/filepath" - "github.com/apache/incubator-kie-kogito-serverless-operator/workflowproj" "github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/common" "github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/metadata" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj" ) type DeployUndeployCmdConfig struct { diff --git a/packages/kogito-management-console/Containerfile b/packages/kogito-management-console/Containerfile index 2a83181caac..52ab30dd1fc 100644 --- a/packages/kogito-management-console/Containerfile +++ b/packages/kogito-management-console/Containerfile @@ -23,7 +23,7 @@ ENV RUNTIME_TOOLS_MANAGEMENT_CONSOLE_KOGITO_ENV_MODE="PROD" COPY entrypoint.sh dist-dev/image-env-to-json-standalone dist-dev/EnvJson.schema.json /tmp/ -RUN microdnf --disableplugin=subscription-manager -y install httpd-2.4.57-5.el9.x86_64 \ +RUN microdnf --disableplugin=subscription-manager -y install httpd \ && microdnf --disableplugin=subscription-manager clean all \ && echo "Mutex posixsem" >> /etc/httpd/conf/httpd.conf \ && sed -i -e "/#ServerName www.example.com:80/aHeader set Content-Security-Policy \"frame-ancestors 'self';\"" /etc/httpd/conf/httpd.conf \ diff --git a/packages/kogito-management-console/package.json b/packages/kogito-management-console/package.json index 9fcfcf43737..791e01fa38e 100644 --- a/packages/kogito-management-console/package.json +++ b/packages/kogito-management-console/package.json @@ -18,11 +18,11 @@ "cleanup": "rimraf dist-dev && mkdir dist-dev", "copy:assets": "pnpm copy:webapp-assets && pnpm copy:image-env-to-json", "copy:image-env-to-json": "run-script-os", - "copy:image-env-to-json:linux:darwin": "cp ../image-env-to-json/dist/linux/image-env-to-json-standalone ./dist-dev/", - "copy:image-env-to-json:win32": "pnpm powershell \"Copy-Item ../image-env-to-json/dist/linux/image-env-to-json-standalone ./dist-dev/\"", + "copy:image-env-to-json:linux:darwin": "cp ./node_modules/@kie-tools/image-env-to-json/dist/linux/image-env-to-json-standalone ./dist-dev/", + "copy:image-env-to-json:win32": "pnpm powershell \"Copy-Item ./node_modules/@kie-tools/image-env-to-json/dist/linux/image-env-to-json-standalone ./dist-dev/\"", "copy:webapp-assets": "run-script-os", - "copy:webapp-assets:linux:darwin": "cp -R ../runtime-tools-management-console-webapp/dist ./dist-dev/runtime-tools-management-console-webapp", - "copy:webapp-assets:win32": "pnpm powershell \"Copy-Item -R ../runtime-tools-management-console-webapp/dist ./dist-dev/runtime-tools-management-console-webapp\"", + "copy:webapp-assets:linux:darwin": "cp -R ./node_modules/@kie-tools/runtime-tools-management-console-webapp/dist/ ./dist-dev/runtime-tools-management-console-webapp", + "copy:webapp-assets:win32": "pnpm powershell \"Copy-Item -R ./node_modules/@kie-tools/runtime-tools-management-console-webapp/dist/ ./dist-dev/runtime-tools-management-console-webapp\"", "env-json:schema:generate": "ts-json-schema-generator --tsconfig ./node_modules/@kie-tools/runtime-tools-management-console-webapp/tsconfig.json --path ./node_modules/@kie-tools/runtime-tools-management-console-webapp/src/env/EnvJson.ts --type EnvJson --id EnvJson --out ./dist-dev/EnvJson.schema.json", "image:docker:build": "kie-tools--image-builder build -r \"$(build-env kogitoManagementConsole.registry)\" -a \"$(build-env kogitoManagementConsole.account)\" -n \"$(build-env kogitoManagementConsole.name)\" -t \"$(build-env kogitoManagementConsole.tags)\" --build-arg KOGITO_MANAGEMENT_CONSOLE_PORT=\"$(build-env kogitoManagementConsole.port)\"", "image:podman:build": "kie-tools--image-builder build -r \"$(build-env kogitoManagementConsole.registry)\" -a \"$(build-env kogitoManagementConsole.account)\" -n \"$(build-env kogitoManagementConsole.name)\" -t \"$(build-env kogitoManagementConsole.tags)\" --build-arg KOGITO_MANAGEMENT_CONSOLE_PORT=\"$(build-env kogitoManagementConsole.port)\" -e podman" diff --git a/packages/kogito-serverless-operator/LICENSE b/packages/kogito-serverless-operator/LICENSE new file mode 100644 index 00000000000..261eeb9e9f8 --- /dev/null +++ b/packages/kogito-serverless-operator/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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/packages/kogito-serverless-operator/Makefile b/packages/kogito-serverless-operator/Makefile new file mode 100644 index 00000000000..0e7c5ca56b4 --- /dev/null +++ b/packages/kogito-serverless-operator/Makefile @@ -0,0 +1,362 @@ +# 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 ?= 0.0.0 +REDUCED_VERSION ?= latest + +# 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") +# To re-generate a bundle for other specific channels without changing the standard setup, you can: +# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable) +# - use environment variables to overwrite this value (e.g export CHANNELS="candidate,fast,stable") +ifneq ($(origin CHANNELS), undefined) +BUNDLE_CHANNELS := --channels=$(CHANNELS) +endif + +# DEFAULT_CHANNEL defines the default channel used in the bundle. +# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") +# To re-generate a bundle for any other default channel without changing the default setup, you can: +# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) +# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") +ifneq ($(origin DEFAULT_CHANNEL), undefined) +BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) +endif +BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) + +# 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 +# kiegroup.org/kogito-serverless-operator-bundle:$VERSION and kiegroup.org/kogito-serverless-operator-catalog:$VERSION. +IMAGE_TAG_BASE ?= quay.io/kiegroup/kogito-serverless-operator-nightly + +# 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:v$(REDUCED_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 + +# 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 +USE_IMAGE_DIGESTS ?= false +ifeq ($(USE_IMAGE_DIGESTS), true) + BUNDLE_GEN_FLAGS += --use-image-digests +endif + +# Image URL to use all building/pushing image targets +IMG ?= $(IMAGE_TAG_BASE):$(REDUCED_VERSION) +# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. +ENVTEST_K8S_VERSION = 1.24 + +OPERATOR_SDK_VERSION ?= 1.25.0 + +# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) +ifeq (,$(shell go env GOBIN)) +GOBIN=$(shell go env GOPATH)/bin +else +GOBIN=$(shell go env GOBIN) +endif + +# 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 + +.PHONY: all +all: build + +##@ General + +# 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 +# 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. +# More info on the usage of ANSI control characters for terminal formatting: +# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters +# More info on the awk command: +# http://linuxcommand.org/lc3_adv_awk.php + +.PHONY: help +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +##@ Development + +.PHONY: manifests +manifests: generate ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. + $(CONTROLLER_GEN) rbac:roleName=manager-role crd:allowDangerousTypes=true webhook paths="./api/..." paths="./controllers/..." output:crd:artifacts:config=config/crd/bases + +.PHONY: generate +generate: controller-gen fmt ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. + $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./api/..." paths="./container-builder/api/..." + +.PHONY: fmt +fmt: ## Run go fmt against code. + ./hack/goimports.sh + go work sync + go mod tidy + go fmt ./... + +.PHONY: vet +vet: ## Run go vet against code. + go vet ./... + +.PHONY: test +test: manifests generate envtest vet fmt test-api test-workflowproj test-container-builder ## Run tests. + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $(shell go list ./... | grep -v /test/) -coverprofile cover.out + +.PHONY: test-api +test-api: + cd api && make test + +###### +# 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 + +##@ Build + +.PHONY: build +build: generate-all ## Build manager binary. + CGO_ENABLED=0 go build -trimpath -ldflags=-buildid= -o bin/manager 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 main.go + +.PHONY: run +run: manifests generate ## Run a controller from your host. + go run ./main.go + +.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 + +# This is currently done directly into the CI +# PLATFORMS defines the target platforms for the manager image be build 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. +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 + # 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 + rm Dockerfile.cross + +.PHONY: container-build +container-build: ## Build the container image + cekit -v --descriptor images/manager.yaml build ${build_options} $(BUILDER) --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} + +##@ Deployment + +ifndef ignore-not-found + ignore-not-found = false +endif + +.PHONY: install +install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. + $(KUSTOMIZE) build config/crd | kubectl create -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 - + +.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: generate-deploy +generate-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 > operator.yaml + +.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 - + +##@ Build Dependencies + +## Location to install dependencies to +LOCALBIN ?= $(shell pwd)/bin +$(LOCALBIN): + mkdir -p $(LOCALBIN) + +## Tool Binaries +KUSTOMIZE ?= $(LOCALBIN)/kustomize +CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen +ENVTEST ?= $(LOCALBIN)/setup-envtest + +## Tool Versions +KUSTOMIZE_VERSION ?= v4.5.2 +CONTROLLER_TOOLS_VERSION ?= v0.9.2 +KIND_VERSION ?= v0.20.0 + +KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" +.PHONY: kustomize +kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. +$(KUSTOMIZE): $(LOCALBIN) + test -s $(LOCALBIN)/kustomize || GO111MODULE=on GOBIN=$(LOCALBIN) go install sigs.k8s.io/kustomize/kustomize/v4@$(KUSTOMIZE_VERSION) + +.PHONY: controller-gen +controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. +$(CONTROLLER_GEN): $(LOCALBIN) + test -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION) + +.PHONY: envtest +envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. +$(ENVTEST): $(LOCALBIN) + test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest + +.PHONY: bundle +bundle: manifests kustomize install-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-build: ## Build the bundle image + cekit -v --descriptor images/bundle.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-bundle:latest $(BUNDLE_IMG) +endif + +.PHONY: bundle-push +bundle-push: ## Push the bundle image. + $(MAKE) container-push IMG=$(BUNDLE_IMG) + +.PHONY: opm +OPM = ./bin/opm +opm: ## Download opm locally if necessary. +ifeq (,$(wildcard $(OPM))) +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 ;\ + chmod +x $(OPM) ;\ + } +else +OPM = $(shell which opm) +endif +endif + +# A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0). +# These images MUST exist in a registry and be pull-able. +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: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 + +# 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) + +# 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 = "" +snapshot = "" +bump-version: + ./hack/bump-version.sh $(new_version) $(snapshot) + +install-operator-sdk: + ./hack/ci/install-operator-sdk.sh + +align-osl-config: + ./hack/align-osl-config.sh + +.PHONY: addheaders +addheaders: + ./hack/addheaders.sh + +.PHONY: generate-all +generate-all: generate generate-deploy bundle addheaders vet fmt + +.PHONY: test-e2e # You will need to have a Minikube/Kind cluster up in running to run this target, and run container-builder before the test +test-e2e: + go test ./test/e2e/* -v -ginkgo.v -ginkgo.no-color -ginkgo.junit-report=./e2e-test-report.xml -timeout 60m + +.PHONY: before-pr +before-pr: test generate-all + + +.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/ci/create-kind-cluster-with-registry.sh + +.PHONY: delete-cluster +delete-cluster: install-kind + kind delete cluster && docker rm -f kind-registry + +.PHONY: load-docker-image +load-docker-image: install-kind + kind load docker-image $(IMG) + +.PHONY: full-test-e2e +full-test-e2e: create-cluster load-docker-image deploy + kubectl wait pod -A -l control-plane=sonataflow-operator --for condition=Ready --timeout 120s + go test ./test/e2e/* -v -ginkgo.v -ginkgo.no-color -ginkgo.junit-report=./e2e-test-report.xml -timeout 60m diff --git a/packages/kogito-serverless-operator/PROJECT b/packages/kogito-serverless-operator/PROJECT new file mode 100644 index 00000000000..8ade5763c63 --- /dev/null +++ b/packages/kogito-serverless-operator/PROJECT @@ -0,0 +1,45 @@ +domain: org +layout: +- go.kubebuilder.io/v3 +plugins: + manifests.sdk.operatorframework.io/v2: {} + scorecard.sdk.operatorframework.io/v2: {} +projectName: sonataflow-operator +repo: github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator +resources: +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: org + group: sonataflow + kind: SonataFlow + path: github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08 + version: v1alpha08 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: org + group: sonataflow + kind: SonataFlowBuild + path: github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08 + version: v1alpha08 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: org + group: sonataflow + kind: SonataFlowPlatform + path: github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08 + version: v1alpha08 +- api: + crdVersion: v1 + controller: true + domain: org + group: sonataflow + kind: SonataFlowClusterPlatform + path: github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08 + version: v1alpha08 +version: "3" diff --git a/packages/kogito-serverless-operator/README.md b/packages/kogito-serverless-operator/README.md new file mode 100644 index 00000000000..da2266d7f6e --- /dev/null +++ b/packages/kogito-serverless-operator/README.md @@ -0,0 +1,54 @@ +# SonataFlow Operator + +The SonataFlow Operator defines a set +of [Kubernetes Custom Resources](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) +to help users to deploy SonataFlow projects on Kubernetes and OpenShift. + +Please [visit our official documentation](https://kiegroup.github.io/kogito-docs/serverlessworkflow/latest/cloud/operator/install-serverless-operator.html) +to know more. + +## Available modules for integrations + +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. + +### SonataFlow Operator Types (api) + +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: + +```shell +go get github.com/kiegroup/kogito-serverless-workflow/api +``` + +Then you can create any type programmatically, for example: + +```go +workflow := &v1alpha08.SonataFlow{ +ObjectMeta: metav1.ObjectMeta{Name: w.name, Namespace: w.namespace}, +Spec: v1alpha08.SonataFlowSpec{Flow: *myWorkflowDef>} +} +``` + +You can use the [Kubernetes client-go library](https://github.com/kubernetes/client-go) to manipulate these objects in +the cluster. + +You might need to register our schemes: + +```go + s := scheme.Scheme +utilruntime.Must(v1alpha08.AddToScheme(s)) +``` + +### Container Builder (container-builder) + +Please see the module's [README file](container-builder/README.md). + +### Workflow Project Handler (workflowproj) + +Please see the module's [README file](workflowproj/README.md). + +## Development and Contributions + +Contributing is easy, just take a look at our [contributors](docs/CONTRIBUTING.md)'guide. diff --git a/packages/kogito-serverless-operator/api/Makefile b/packages/kogito-serverless-operator/api/Makefile new file mode 100644 index 00000000000..00c73d81848 --- /dev/null +++ b/packages/kogito-serverless-operator/api/Makefile @@ -0,0 +1,3 @@ +.PHONY: test +test: + go test $(shell go list ./... | grep -v /test/) -coverprofile cover.out diff --git a/packages/kogito-serverless-operator/api/condition_types.go b/packages/kogito-serverless-operator/api/condition_types.go new file mode 100644 index 00000000000..69b6e3be424 --- /dev/null +++ b/packages/kogito-serverless-operator/api/condition_types.go @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// Conditions ... +// +kubebuilder:object:generate=true +type Conditions []Condition + +type ConditionType string + +const ( + // RunningConditionType describes the readiness condition of a "live" resource, like the workflow application + RunningConditionType ConditionType = "Running" + // SucceedConditionType describes the readiness condition of a static resource, like a platform, a builder, a configuration, etc. + SucceedConditionType ConditionType = "Succeed" + // BuiltConditionType describes the condition of a resource that needs to be build. + BuiltConditionType ConditionType = "Built" +) + +const ( + WaitingForDeploymentReason = "WaitingForDeployment" + ExternalResourcesNotFoundReason = "ExternalResourcesNotFound" + DeploymentFailureReason = "DeploymentFailure" + DeploymentUnavailableReason = "DeploymentIsUnavailable" + RedeploymentExhaustedReason = "AttemptToRedeployFailed" + WaitingForPlatformReason = "WaitingForPlatform" + BuildFailedReason = "BuildFailedReason" + WaitingForBuildReason = "WaitingForBuild" + BuildIsRunningReason = "BuildIsRunning" + BuildSkippedReason = "BuildSkipped" + BuildSuccessfulReason = "BuildSuccessful" + BuildMarkedToRestartReason = "BuildMarkedToRestart" +) + +// Condition describes the common structure for conditions in our types +// +kubebuilder:object:generate=true +type Condition struct { + // Type condition for the given object + // +required + Type ConditionType `json:"type"` + // Status of the condition, one of True, False, Unknown. + // +required + Status v1.ConditionStatus `json:"status"` + // The last time this condition was updated. + LastUpdateTime metav1.Time `json:"lastUpdateTime,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"` +} + +// IsTrue is true if the condition is True +func (c *Condition) IsTrue() bool { + if c == nil { + return false + } + return c.Status == v1.ConditionTrue +} + +// IsFalse is true if the condition is False +func (c *Condition) IsFalse() bool { + if c == nil { + return false + } + return c.Status == v1.ConditionFalse +} + +// IsUnknown is true if the condition is Unknown +func (c *Condition) IsUnknown() bool { + if c == nil { + return true + } + return c.Status == v1.ConditionUnknown +} + +// GetReason returns a nil save string of Reason +func (c *Condition) GetReason() string { + if c == nil { + return "" + } + return c.Reason +} + +// GetMessage returns a nil save string of Message +func (c *Condition) GetMessage() string { + if c == nil { + return "" + } + return c.Message +} + +func (c *Condition) String() string { + if c == nil { + return "" + } + str := fmt.Sprintf("Condition %s status is %s", c.Type, c.Status) + if len(c.Reason) > 0 { + str += fmt.Sprintf(". [Reason] %s", c.Reason) + } + if len(c.Message) > 0 { + str += fmt.Sprintf(". [Message] %s", c.Message) + } + return str +} diff --git a/packages/kogito-serverless-operator/api/go.mod b/packages/kogito-serverless-operator/api/go.mod new file mode 100644 index 00000000000..7e4096c6f34 --- /dev/null +++ b/packages/kogito-serverless-operator/api/go.mod @@ -0,0 +1,79 @@ +module github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api + +go 1.21 + +require ( + github.com/serverlessworkflow/sdk-go/v2 v2.2.5 + k8s.io/api v0.27.6 + k8s.io/apimachinery v0.27.6 + knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c + sigs.k8s.io/controller-runtime v0.15.0 + sigs.k8s.io/yaml v1.3.0 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.10.2 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.7.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-logr/logr v1.2.4 // 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.0 // indirect + github.com/go-playground/universal-translator v0.18.0 // indirect + github.com/go-playground/validator/v10 v10.11.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.3 // indirect + github.com/google/gnostic v0.6.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 // indirect + github.com/google/uuid v1.3.1 // 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.2.1 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // 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/v2 v2.13.0 // indirect + github.com/onsi/gomega v1.30.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.11.1 // indirect + github.com/relvacode/iso8601 v1.3.0 // indirect + github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 // indirect + github.com/spf13/pflag v1.0.5 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.3.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.33.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.27.6 // indirect + k8s.io/client-go v0.27.6 // indirect + k8s.io/component-base v0.27.6 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 // indirect + k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect +) diff --git a/packages/kogito-serverless-operator/api/go.sum b/packages/kogito-serverless-operator/api/go.sum new file mode 100644 index 00000000000..4f6bbea5070 --- /dev/null +++ b/packages/kogito-serverless-operator/api/go.sum @@ -0,0 +1,305 @@ +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= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +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/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +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.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +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/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +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-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +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-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/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.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/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +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.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.5.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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +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-20230705174524-200ffdc848b8 h1:n6vlPhxsA+BW/XsS5+uqi7GyzaLa5MH7qlSLBZtRdiA= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +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.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +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.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +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/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.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +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/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/relvacode/iso8601 v1.3.0 h1:HguUjsGpIMh/zsTczGN3DVJFxTU/GX+MMmzcKoMO7ko= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 h1:Dz0HrI1AtNSGCE8LXLLqoZU4iuOJXPWndenCsZfstA8= +github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46/go.mod h1:is8FVkzSi7PYLWEXT5MgWhglFsyyiW8ffxAoJqfuFZo= +github.com/serverlessworkflow/sdk-go/v2 v2.2.5 h1:/TFqBBni0hDpTA0bKadGTWbyBRiQ0o2ppz2ScY6DdTM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +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/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/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.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +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/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +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.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +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-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-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +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-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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +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-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.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-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-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/text v0.3.0/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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +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-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +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.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +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= +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.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +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.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +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/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.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.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.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/api v0.27.6 h1:PBWu/lywJe2qQcshMjubzcBg7+XDZOo7O8JJAWuYtUo= +k8s.io/apiextensions-apiserver v0.27.6 h1:mOwSBJtThZhpJr+8gEkc3wFDIjq87E3JspR5mtZxIg8= +k8s.io/apimachinery v0.27.6 h1:mGU8jmBq5o8mWBov+mLjdTBcU+etTE19waies4AQ6NE= +k8s.io/client-go v0.27.6 h1:vzI8804gpUtpMCNaFjIFyJrifH7u//LJCJPy8fQuYQg= +k8s.io/component-base v0.27.6 h1:hF5WxX7Tpi9/dXAbLjPVkIA6CA6Pi6r9JOHyo0uCDYI= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 h1:OmK1d0WrkD3IPfkskvroRykOulHVHf0s0ZIFRjyt+UI= +k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc= +knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c h1:xyPoEToTWeBdn6tinhLxXfnhJhTNQt5WzHiTNiFphRw= +sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= +sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +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.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/packages/kogito-serverless-operator/api/metadata/annotations.go b/packages/kogito-serverless-operator/api/metadata/annotations.go new file mode 100644 index 00000000000..a0980ab94a2 --- /dev/null +++ b/packages/kogito-serverless-operator/api/metadata/annotations.go @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + 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" +) diff --git a/packages/kogito-serverless-operator/api/status_types.go b/packages/kogito-serverless-operator/api/status_types.go new file mode 100644 index 00000000000..b3d24224427 --- /dev/null +++ b/packages/kogito-serverless-operator/api/status_types.go @@ -0,0 +1,328 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + "reflect" + "sort" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// Based on https://github.com/knative/pkg/blob/980a33719a10024f45e44320316c5bd35cef18d6/apis/condition_set.go + +// Status ... +// +kubebuilder:object:generate=true +type Status struct { + // The latest available observations of a resource's current state. + // +optional + // +patchMergeKey=type + // +patchStrategy=merge + Conditions Conditions `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` + // The generation observed by the deployment controller. + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` +} + +func (s *Status) GetConditions() Conditions { + return s.Conditions +} + +// GetCondition finds and returns the Condition that matches the ConditionType +// previously set on Conditions. +func (s *Status) GetCondition(t ConditionType) *Condition { + for _, c := range s.Conditions { + if c.Type == t { + return &c + } + } + return nil +} + +func (s *Status) String() string { + str := "" + for _, c := range s.Conditions { + str += c.String() + "\n" + } + return str +} + +func (s *Status) setConditions(c Conditions) { + s.Conditions = c +} + +// ConditionsReader gives read capability to Conditions. +type ConditionsReader interface { + GetConditions() Conditions + GetCondition(t ConditionType) *Condition + // setConditions overwrite the conditions in the Status instance. + // Private to not expose to client code. Writing to the conditions should be done via ConditionsManager + setConditions(c Conditions) +} + +// ConditionsAccessor describes access methods that every Status based struct implements. +type ConditionsAccessor interface { + ConditionsReader + GetTopLevelConditionType() ConditionType + IsReady() bool + GetTopLevelCondition() *Condition +} + +type ConditionsManager interface { + ClearCondition(t ConditionType) error + MarkTrue(t ConditionType) + MarkTrueWithReason(t ConditionType, reason, messageFormat string, messageA ...interface{}) + MarkUnknown(t ConditionType, reason, messageFormat string, messageA ...interface{}) + MarkFalse(t ConditionType, reason, messageFormat string, messageA ...interface{}) + InitializeConditions() +} + +var _ ConditionsManager = &conditionManager{} + +type conditionManager struct { + reader ConditionsReader + ready ConditionType + dependents []ConditionType +} + +func NewConditionManager(accessor ConditionsReader, ready ConditionType, dependents ...ConditionType) ConditionsManager { + return &conditionManager{ + reader: accessor, + ready: ready, + dependents: dependents, + } +} + +// setCondition sets or updates the Condition on Conditions for Condition.Type. +// If there is an update, Conditions are stored back sorted. +func (s *conditionManager) setCondition(cond Condition) { + if s.reader == nil { + return + } + t := cond.Type + var conditions Conditions + for _, c := range s.reader.GetConditions() { + if c.Type != t { + conditions = append(conditions, c) + } else { + // If we'd only update the LastTransitionTime, then return. + cond.LastUpdateTime = c.LastUpdateTime + if reflect.DeepEqual(cond, c) { + return + } + } + } + cond.LastUpdateTime = metav1.NewTime(time.Now()) + conditions = append(conditions, cond) + // Sorted for convenience of the consumer, i.e. kubectl. + sort.Slice(conditions, func(i, j int) bool { return conditions[i].Type < conditions[j].Type }) + s.reader.setConditions(conditions) +} + +func (s *conditionManager) isTerminal(t ConditionType) bool { + for _, cond := range s.dependents { + if cond == t { + return true + } + } + return t == s.ready +} + +// ClearCondition removes the non-terminal condition that matches the ConditionType +// Not implemented for terminal conditions +func (s *conditionManager) ClearCondition(t ConditionType) error { + var conditions Conditions + + if s.reader == nil { + return nil + } + // Terminal conditions are not handled as they can't be nil + if s.isTerminal(t) { + return fmt.Errorf("clearing terminal conditions not implemented") + } + cond := s.reader.GetCondition(t) + if cond == nil { + return nil + } + for _, c := range s.reader.GetConditions() { + if c.Type != t { + conditions = append(conditions, c) + } + } + + // Sorted for convenience of the consumer, i.e. kubectl. + sort.Slice(conditions, func(i, j int) bool { return conditions[i].Type < conditions[j].Type }) + s.reader.setConditions(conditions) + + return nil +} + +// MarkTrue sets the status of t to true +func (s *conditionManager) MarkTrue(t ConditionType) { + // Set the specified condition. + s.setCondition(Condition{ + Type: t, + Status: corev1.ConditionTrue, + }) +} + +// MarkTrueWithReason sets the status of t to true with the reason +func (s *conditionManager) MarkTrueWithReason(t ConditionType, reason, messageFormat string, messageA ...interface{}) { + // set the specified condition + s.setCondition(Condition{ + Type: t, + Status: corev1.ConditionTrue, + Reason: reason, + Message: fmt.Sprintf(messageFormat, messageA...), + }) +} + +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, messageFormat string, messageA ...interface{}) { + // set the specified condition + s.setCondition(Condition{ + Type: t, + Status: corev1.ConditionUnknown, + Reason: reason, + Message: fmt.Sprintf(messageFormat, messageA...), + }) + + // check the dependents. + isDependent := false + for _, cond := range s.dependents { + c := s.reader.GetCondition(cond) + // Failed conditions trump Unknown conditions + if c.IsFalse() { + // Double check that the ready condition is also false. + ready := s.reader.GetCondition(s.ready) + if !ready.IsFalse() { + s.MarkFalse(s.ready, reason, messageFormat, messageA...) + } + return + } + if cond == t { + isDependent = true + } + } + + if isDependent { + // set the ready condition, if it is one of our dependent subconditions. + s.setCondition(Condition{ + Type: s.ready, + Status: corev1.ConditionUnknown, + Reason: reason, + Message: fmt.Sprintf(messageFormat, messageA...), + }) + } +} + +// MarkFalse sets the status of t and the ready condition to False. +func (s *conditionManager) MarkFalse(t ConditionType, reason, messageFormat string, messageA ...interface{}) { + s.setCondition(Condition{ + Type: t, + Status: corev1.ConditionFalse, + Reason: reason, + Message: fmt.Sprintf(messageFormat, messageA...), + }) +} + +// InitializeConditions updates all Conditions in the ConditionSet to Unknown +// if not set. +func (s *conditionManager) InitializeConditions() { + ready := s.reader.GetCondition(s.ready) + if ready == nil { + ready = &Condition{ + Type: s.ready, + Status: corev1.ConditionUnknown, + } + s.setCondition(*ready) + } + // If the ready state is true, it implies that all of the terminal + // subconditions must be true, so initialize any unset conditions to + // true if our ready condition is true, otherwise unknown. + status := corev1.ConditionUnknown + if ready.Status == corev1.ConditionTrue { + status = corev1.ConditionTrue + } + for _, t := range s.dependents { + s.initializeTerminalCondition(t, status) + } +} + +// initializeTerminalCondition initializes a Condition to the given status if unset. +func (s *conditionManager) initializeTerminalCondition(t ConditionType, status corev1.ConditionStatus) *Condition { + if c := s.reader.GetCondition(t); c != nil { + return c + } + c := Condition{ + Type: t, + Status: status, + } + s.setCondition(c) + return &c +} diff --git a/packages/kogito-serverless-operator/api/v1alpha08/conversion.go b/packages/kogito-serverless-operator/api/v1alpha08/conversion.go new file mode 100644 index 00000000000..b4544fe5bac --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/conversion.go @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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 + cncfWorkflow.Key = workflowCR.ObjectMeta.Annotations[metadata.Key] + cncfWorkflow.Description = workflowCR.ObjectMeta.Annotations[metadata.Description] + cncfWorkflow.Version = workflowCR.ObjectMeta.Annotations[metadata.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/packages/kogito-serverless-operator/api/v1alpha08/conversion_test.go b/packages/kogito-serverless-operator/api/v1alpha08/conversion_test.go new file mode 100644 index 00000000000..01c295ca6d9 --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/conversion_test.go @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/api/v1alpha08/groupversion_info.go b/packages/kogito-serverless-operator/api/v1alpha08/groupversion_info.go new file mode 100644 index 00000000000..fc6f85b0cbb --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/groupversion_info.go @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/api/v1alpha08/sonataflow_persistence_types.go b/packages/kogito-serverless-operator/api/v1alpha08/sonataflow_persistence_types.go new file mode 100644 index 00000000000..d0b08e46799 --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/sonataflow_persistence_types.go @@ -0,0 +1,102 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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 + +// 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=1 +type PersistenceOptionsSpec struct { + // Connect configured services to a postgresql database. + // +optional + PostgreSQL *PersistencePostgreSQL `json:"postgresql,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/packages/kogito-serverless-operator/api/v1alpha08/sonataflow_types.go b/packages/kogito-serverless-operator/api/v1alpha08/sonataflow_types.go new file mode 100644 index 00000000000..429bd5fc6f0 --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/sonataflow_types.go @@ -0,0 +1,781 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" +) + +const DefaultContainerName = "workflow" + +// 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, + } +} + +// PodTemplateSpec describes the desired custom Kubernetes PodTemplate definition for the deployed flow or service. +// +// The ContainerSpec describes the container where the actual flow or 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"` +} + +// 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 PodTemplateSpec `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"` +} + +// 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"` +} + +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 +} + +// 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: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,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"}} +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) 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/packages/kogito-serverless-operator/api/v1alpha08/sonataflowbuild_types.go b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowbuild_types.go new file mode 100644 index 00000000000..deb905e5c2b --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowbuild_types.go @@ -0,0 +1,168 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +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"}} +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/packages/kogito-serverless-operator/api/v1alpha08/sonataflowclusterplatform_types.go b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowclusterplatform_types.go new file mode 100644 index 00000000000..04d53cfe347 --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowclusterplatform_types.go @@ -0,0 +1,115 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +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"}} +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/packages/kogito-serverless-operator/api/v1alpha08/sonataflowclusterplatform_types_support.go b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowclusterplatform_types_support.go new file mode 100644 index 00000000000..8c126555de6 --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowclusterplatform_types_support.go @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_build_types.go b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_build_types.go new file mode 100644 index 00000000000..289c96cf6eb --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_build_types.go @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_devmode_types.go b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_devmode_types.go new file mode 100644 index 00000000000..ef5ced33fa3 --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_devmode_types.go @@ -0,0 +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. + */ + +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/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_property_types.go b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_property_types.go new file mode 100644 index 00000000000..d138ac40c06 --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_property_types.go @@ -0,0 +1,53 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_services_types.go b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_services_types.go new file mode 100644 index 00000000000..a16bc278281 --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_services_types.go @@ -0,0 +1,39 @@ +// Copyright 2023 Red Hat, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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 + +// 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 *ServiceSpec `json:"dataIndex,omitempty"` + // Deploys the Job service for use by workflows without the `sonataflow.org/profile: dev` annotation. + // +optional + JobService *ServiceSpec `json:"jobService,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/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_types.go b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_types.go new file mode 100644 index 00000000000..6cca6060fed --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_types.go @@ -0,0 +1,193 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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"` + // 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"` +} + +// 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" +) + +// 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 build + //+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"` +} + +// 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 +// +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"}} +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/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_types_support.go b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_types_support.go new file mode 100644 index 00000000000..5c058e7b46c --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/sonataflowplatform_types_support.go @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/api/v1alpha08/testdata/camel.sw.json b/packages/kogito-serverless-operator/api/v1alpha08/testdata/camel.sw.json new file mode 100644 index 00000000000..b54ecda62b1 --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/testdata/camel.sw.json @@ -0,0 +1,34 @@ +{ + "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/packages/kogito-serverless-operator/api/v1alpha08/testdata/foreach.sw.json b/packages/kogito-serverless-operator/api/v1alpha08/testdata/foreach.sw.json new file mode 100644 index 00000000000..2d4b6933e0f --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/testdata/foreach.sw.json @@ -0,0 +1,49 @@ +{ + "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/packages/kogito-serverless-operator/api/v1alpha08/testdata/invalid.sw.json b/packages/kogito-serverless-operator/api/v1alpha08/testdata/invalid.sw.json new file mode 100644 index 00000000000..d72e2d4f377 --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/testdata/invalid.sw.json @@ -0,0 +1,6 @@ +{ + "id": "invalid", + "version": "1.0", + "specVersion": "0.8", + "description": "A valid workflow should have states." +} diff --git a/packages/kogito-serverless-operator/api/v1alpha08/testdata/sonataflow-camel.yaml b/packages/kogito-serverless-operator/api/v1alpha08/testdata/sonataflow-camel.yaml new file mode 100644 index 00000000000..588fe97a913 --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/testdata/sonataflow-camel.yaml @@ -0,0 +1,44 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/api/v1alpha08/testdata/sonataflow-foreach.yaml b/packages/kogito-serverless-operator/api/v1alpha08/testdata/sonataflow-foreach.yaml new file mode 100644 index 00000000000..b6eb81a4f9e --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/testdata/sonataflow-foreach.yaml @@ -0,0 +1,53 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/api/v1alpha08/testdata/sonataflow-invalid.yaml b/packages/kogito-serverless-operator/api/v1alpha08/testdata/sonataflow-invalid.yaml new file mode 100644 index 00000000000..23fffd80bfd --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/testdata/sonataflow-invalid.yaml @@ -0,0 +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. + +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/packages/kogito-serverless-operator/api/v1alpha08/zz_generated.deepcopy.go b/packages/kogito-serverless-operator/api/v1alpha08/zz_generated.deepcopy.go new file mode 100644 index 00000000000..ad0a2d06b8f --- /dev/null +++ b/packages/kogito-serverless-operator/api/v1alpha08/zz_generated.deepcopy.go @@ -0,0 +1,1313 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT 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" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "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 *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) + **out = **in + } + 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 *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 *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 *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 + } +} + +// 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(ServiceSpec) + (*in).DeepCopyInto(*out) + } + if in.JobService != nil { + in, out := &in.JobService, &out.JobService + *out = new(ServiceSpec) + (*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 *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.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) + } +} + +// 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) + } +} + +// 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 *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) + } +} + +// 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) + } +} + +// 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 *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/packages/kogito-serverless-operator/api/zz_generated.deepcopy.go b/packages/kogito-serverless-operator/api/zz_generated.deepcopy.go new file mode 100644 index 00000000000..b68499c7bee --- /dev/null +++ b/packages/kogito-serverless-operator/api/zz_generated.deepcopy.go @@ -0,0 +1,82 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT 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 + in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition. +func (in *Condition) DeepCopy() *Condition { + if in == nil { + return nil + } + out := new(Condition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in Conditions) DeepCopyInto(out *Conditions) { + { + in := &in + *out = make(Conditions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Conditions. +func (in Conditions) DeepCopy() Conditions { + if in == nil { + return nil + } + out := new(Conditions) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Status) DeepCopyInto(out *Status) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make(Conditions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. +func (in *Status) DeepCopy() *Status { + if in == nil { + return nil + } + out := new(Status) + in.DeepCopyInto(out) + return out +} diff --git a/packages/kogito-serverless-operator/bddframework/Makefile b/packages/kogito-serverless-operator/bddframework/Makefile new file mode 100644 index 00000000000..1e37c1e4b2f --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/Makefile @@ -0,0 +1,17 @@ +.PHONY: all +all: test + +##@ Development + +.PHONY: fmt +fmt: ## Run go fmt against code. + go mod tidy + go fmt ./... + +.PHONY: vet +vet: ## Run go vet against code. + go vet ./... + +.PHONY: test +test: fmt vet ## Run tests. + go test ./... -v diff --git a/packages/kogito-serverless-operator/bddframework/go.mod b/packages/kogito-serverless-operator/bddframework/go.mod new file mode 100644 index 00000000000..d08f6c19c7e --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/go.mod @@ -0,0 +1,128 @@ +module github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework + +go 1.21 + +toolchain go1.21.6 + +// Internal dependencies +replace github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator v0.0.0 => ../ + +require ( + github.com/cucumber/gherkin-go/v19 v19.0.3 + github.com/cucumber/godog v0.12.5 + github.com/cucumber/messages-go/v16 v16.0.1 + github.com/go-logr/logr v1.2.4 + github.com/go-logr/zapr v1.2.4 + github.com/machinebox/graphql v0.2.2 + github.com/matryer/is v1.4.0 // indirect + github.com/openshift/api v0.0.0-20230522130544-0eef84f63102 + github.com/operator-framework/operator-lifecycle-manager v0.0.0-20200321030439-57b580e57e88 + github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.55.1 + github.com/spf13/pflag v1.0.5 + go.uber.org/zap v1.26.0 + gopkg.in/src-d/go-git.v4 v4.13.1 + gopkg.in/yaml.v2 v2.4.0 + k8s.io/api v0.27.6 + k8s.io/apiextensions-apiserver v0.27.6 + k8s.io/apimachinery v0.27.6 + k8s.io/client-go v0.27.6 + knative.dev/eventing v0.26.0 + knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c + sigs.k8s.io/controller-runtime v0.15.0 +) + +require ( + github.com/RHsyseng/operator-utils v1.4.13 + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator v0.0.0 + github.com/google/uuid v1.3.1 + github.com/openshift/client-go v0.0.0-20230503144108-75015d2347cb + github.com/stretchr/testify v1.8.4 +) + +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/beorn7/perks v1.0.1 // indirect + github.com/blang/semver v3.5.1+incompatible // indirect + github.com/blendle/zapdriver v1.3.1 // indirect + github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cloudevents/sdk-go/v2 v2.15.2 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.10.2 // indirect + github.com/emirpasic/gods v1.12.0 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.7.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // 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/gofrs/uuid v4.0.0+incompatible // 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.3 // indirect + github.com/google/gnostic v0.6.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-memdb v1.3.0 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/imdario/mergo v0.3.16 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kelseyhightower/envconfig v1.4.0 // indirect + github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/go-homedir v1.1.0 // 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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/statsd_exporter v0.22.7 // 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/sergi/go-diff v1.1.0 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect + github.com/src-d/gcfg v1.4.0 // indirect + github.com/xanzy/ssh-agent v0.2.1 // indirect + go.opencensus.io v0.24.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/sync v0.4.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.3.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + google.golang.org/api v0.147.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect + google.golang.org/grpc v1.58.3 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/component-base v0.27.6 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 // indirect + k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/packages/kogito-serverless-operator/bddframework/go.sum b/packages/kogito-serverless-operator/bddframework/go.sum new file mode 100644 index 00000000000..fa1eb9ad91d --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/go.sum @@ -0,0 +1,1563 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg= +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.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= +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 v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +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.0/go.mod h1:o7cosnyfuPVK0tB8q0QmaQNhGnptITnPQB+z1+qeFB0= +contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= +contrib.go.opencensus.io/exporter/zipkin v0.1.2/go.mod h1:mP5xM3rrgOjpn79MM8fZbj3gsxcuytSqtH0dxSWW1RE= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +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/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig/v3 v3.0.2/go.mod h1:oesJ8kPONMONaZgtiHNzUShJbksypC5kWczhZAf6+aU= +github.com/Masterminds/vcs v1.13.1/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/RHsyseng/operator-utils v1.4.13 h1:kCsvBXm1Y3AEfzjioUvk/RmOigM/+czd/U5YQ3SZXx8= +github.com/RHsyseng/operator-utils v1.4.13/go.mod h1:f+GrcLNALoHBPonk3P6KCwPK5kYyHhkqj4vuCP2Eijc= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/ahmetb/gen-crd-api-reference-docs v0.3.1-0.20210420163308-c1402a70e2f1/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= +github.com/alecthomas/jsonschema v0.0.0-20180308105923-f2c93856175a/go.mod h1:qpebaTNSsyUn5rPSJMsfqEtDw71TTggXM6stUDI16HA= +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/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +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/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +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/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/c2h5oh/datasize v0.0.0-20171227191756-4eba002a5eae/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= +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/conformance v0.2.0/go.mod h1:rHKDwylBH89Rns6U3wL9ww8bg9/4GbwRCDNuyoC6bcc= +github.com/cloudevents/sdk-go/observability/opencensus/v2 v2.4.1/go.mod h1:lhEpxMrIUkeu9rVRgoAbyqZ8GR8Hd3DUy+thHUxAHoI= +github.com/cloudevents/sdk-go/v2 v2.4.1/go.mod h1:MZiMwmAh5tGj+fPFvtHv9hKurKqXtdB9haJYMJ/7GJY= +github.com/cloudevents/sdk-go/v2 v2.15.2 h1:54+I5xQEnI73RBhWHxbI1XJcqOFOVJN85vb41+8mHUc= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200107194136-26c1120b8d41/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cucumber/gherkin-go/v19 v19.0.3 h1:mMSKu1077ffLbTJULUfM5HPokgeBcIGboyeNUof1MdE= +github.com/cucumber/gherkin-go/v19 v19.0.3/go.mod h1:jY/NP6jUtRSArQQJ5h1FXOUgk5fZK24qtE7vKi776Vw= +github.com/cucumber/godog v0.12.5 h1:FZIy6VCfMbmGHts9qd6UjBMT9abctws/pQYO/ZcwOVs= +github.com/cucumber/godog v0.12.5/go.mod h1:u6SD7IXC49dLpPN35kal0oYEjsXZWee4pW6Tm9t5pIc= +github.com/cucumber/messages-go/v16 v16.0.0/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK30BGjtYotDKpwQ0v6g= +github.com/cucumber/messages-go/v16 v16.0.1 h1:fvkpwsLgnIm0qugftrw2YwNlio+ABe2Iu94Ap8GMYIY= +github.com/cucumber/messages-go/v16 v16.0.1/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK30BGjtYotDKpwQ0v6g= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= +github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg= +github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= +github.com/cznic/internal v0.0.0-20180608152220-f44710a21d00/go.mod h1:olo7eAdKwJdXxb55TKGLiJ6xt1H0/tiiRCWKVLmtjY4= +github.com/cznic/lldb v1.1.0/go.mod h1:FIZVUmYUVhPwRiPzL8nD/mpFcJ/G7SSXjjXYG4uRI3A= +github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= +github.com/cznic/ql v1.2.0/go.mod h1:FbpzhyZrqr0PVlK6ury+PoW3T0ODUV22OeWIxcaOrSE= +github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ= +github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= +github.com/cznic/zappy v0.0.0-20160723133515-2533cb5b45cc/go.mod h1:Y1SNZ4dRUOKXshKUbwUapqNncRrho4mkjQebgEHZLj8= +github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= +github.com/deislabs/oras v0.8.1/go.mod h1:Mx0rMSbBNaNfY9hjpccEnxkOqJL6KGjtxNHPLC4G4As= +github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-gk v0.0.0-20140819190930-201884a44051/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E= +github.com/dgryski/go-gk v0.0.0-20200319235926-a69029f61654/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E= +github.com/dgryski/go-lttb v0.0.0-20180810165845-318fcdf10a77/go.mod h1:Va5MyIzkU0rAM92tn3hb3Anb7oz7KcnixF49+2wOMe4= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= +github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v0.7.3-0.20190103212154-2b7e084dc98b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v0.7.3-0.20190817195342-4760db040282/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE= +github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +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.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= +github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= +github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +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.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= +github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +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-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +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.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-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.4.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.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= +github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= +github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +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/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= +github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= +github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= +github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= +github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= +github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +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/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= +github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= +github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/gobuffalo/flect v0.1.5/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= +github.com/gobuffalo/flect v0.2.3/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcrg45ZL7LDBMW3WGJL0= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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 v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +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/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= +github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8= +github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= +github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= +github.com/gonum/diff v0.0.0-20181124234638-500114f11e71/go.mod h1:22dM4PLscQl+Nzf64qNBurVJvfyvZELT0iRW2l/NN70= +github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= +github.com/gonum/integrate v0.0.0-20181209220457-a422b5c0fdf2/go.mod h1:pDgmNM6seYpwvPos3q+zxlXMsbve6mOIPucUnUOrI7Y= +github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks= +github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A= +github.com/gonum/mathext v0.0.0-20181121095525-8a4bf007ea55/go.mod h1:fmo8aiSEWkJeiGXUJf+sPvuDgEFgqIoZSs843ePKrGg= +github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= +github.com/gonum/stat v0.0.0-20181125101827-41a0da705a5b/go.mod h1:Z4GIJBJO3Wa4gD4vbwQxXXZ+WHmW6E9ixmNrwvs0iZs= +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 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.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.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-github/v27 v27.0.6/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.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/mako v0.0.0-20190821191249-122f8dcef9e3/go.mod h1:YzLcVlL+NqWnmUEPuhS1LxDDwGO9WNbVlEXaF4IH35g= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/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-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 h1:n6vlPhxsA+BW/XsS5+uqi7GyzaLa5MH7qlSLBZtRdiA= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= +github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-health-probe v0.2.1-0.20181220223928-2bf0a5b182db/go.mod h1:uBKkC2RbarFsvS5jMJHpVhTLvGlGQj9JJwkaePE3FWI= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-memdb v1.3.0 h1:xdXq34gBOMEloa9rlGStLxmfX/dyIK8htOv36dQUwHU= +github.com/hashicorp/go-memdb v1.3.0/go.mod h1:Mluclgwib3R93Hk5fxEfiRhB+6Dar64wWh71LpNSe3g= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +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 v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= +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.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a/go.mod h1:9GkyshztGufsdPQWjH+ifgnIr3xNUL5syI70g2dzU1o= +github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= +github.com/influxdata/tdigest v0.0.0-20191024211133-5d87a7585faa/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y= +github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= +github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +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/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +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/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/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +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/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= +github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= +github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +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.2/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.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +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/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac/go.mod h1:Frd2bnT3w5FB5q49ENTfVlztJES+1k/7lyWX2+9gq/M= +github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/machinebox/graphql v0.2.2 h1:dWKpJligYKhYKO5A2gvNhkJdQMNZeChZYyBbrZkBZfo= +github.com/machinebox/graphql v0.2.2/go.mod h1:F+kbVMHuwrQ5tYgU9JXlnskM8nOaFxCAEolaQybkjWA= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-shellwords v1.0.9/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +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/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/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/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.17/go.mod h1:WgzbA6oji13JREwiNsRDNfl7jYdPnmz+VEuLrA+/48M= +github.com/mikefarah/yaml/v2 v2.4.0/go.mod h1:ahVqZF4n1W4NqwvVnZzC4es67xsW9uR/RRf2RRxieJU= +github.com/mikefarah/yq/v2 v2.4.1/go.mod h1:i8SYf1XdgUvY2OFwSqGAtWOOgimD2McJ6iutoxRm4k0= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +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/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= +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-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +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/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +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/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M= +github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +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.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/openshift/api v0.0.0-20200205133042-34f0ec8dab87/go.mod h1:fT6U/JfG8uZzemTRwZA2kBDJP5nWz7v05UHnty/D+pk= +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/client-go v0.0.0-20190923180330-3b6373338c9b/go.mod h1:6rzn+JTr7+WYS2E1TExP4gByoABxMznR6y2SnUIkmxk= +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/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= +github.com/operator-framework/api v0.1.1/go.mod h1:yzNYR7qyJqRGOOp+bT6Z/iYSbSPNxeh3Si93Gx/3OBY= +github.com/operator-framework/operator-lifecycle-manager v0.0.0-20200321030439-57b580e57e88 h1:ByKBik0i2aTEr7iKdSCmUGULydHwr6hA0h4INv9LkSA= +github.com/operator-framework/operator-lifecycle-manager v0.0.0-20200321030439-57b580e57e88/go.mod h1:7Ut8p9jJ8C6RZyyhZfZypmlibCIJwK5Wcc+WZDgLkOA= +github.com/operator-framework/operator-registry v1.5.3/go.mod h1:agrQlkWOo1q8U1SAaLSS2WQ+Z9vswNT2M2HFib9iuLY= +github.com/operator-framework/operator-registry v1.6.1/go.mod h1:sx4wWMiZtYhlUiaKscg3QQUPPM/c1bkrAs4n4KipDb4= +github.com/otiai10/copy v1.0.1/go.mod h1:8bMCJrAqOtN/d9oyh5HR7HhLQMvcGMpGdwRDYsfOCHc= +github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776/go.mod h1:3HNVkVOU7vZeFXocWuvtcS0XSFLcf2XUSDHkq9t1jU4= +github.com/otiai10/mint v1.2.3/go.mod h1:YnfyPNhBvnY8bW4SGQHCs/aAFhkgySlMZbrF5U0bOVw= +github.com/otiai10/mint v1.2.4/go.mod h1:d+b7n/0R3tdyUYYylALXpWQ/kTN+QobSq/4SRGBkR3M= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml/v2 v2.0.0-beta.2/go.mod h1:+X+aW6gUj6Hda43TeYHVCIvYNG/jqY/8ZFXAeXXHl+Q= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +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.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= +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.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/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.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +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.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= +github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +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 v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +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.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +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/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +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/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +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/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +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/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518/go.mod h1:CKI4AZ4XmGV240rTHfO0hfE83S6/a3/Q1siZJ/vXf7A= +github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= +github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU= +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.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +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 v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/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.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tsenart/go-tsz v0.0.0-20180814232043-cdeb9e1e981e/go.mod h1:SWZznP1z5Ki7hDT2ioqiFKEse8K9tU2OUvaRI0NeGQo= +github.com/tsenart/vegeta/v12 v12.8.4/go.mod h1:ZiJtwLn/9M4fTPdMY7bdbIeyNeFVE8/AHbWFqCsUuho= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +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/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/wavesoftware/go-ensure v1.0.0/go.mod h1:K2UAFSwMTvpiRGay/M3aEYYuurcR8S4A6HkQlJPV8k4= +github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= +github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= +github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opentelemetry.io/otel v0.16.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/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-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +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-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +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/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/lint v0.0.0-20201208152925-83fdc39ff7b5/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.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +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-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181108082009-03003ca0c849/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/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-20190619014844-b5b0513f8c1b/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-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/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-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/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-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/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-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +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-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/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-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/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-20190321052220-f7bb7a8bee54/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-20190426135247-a129542de9ae/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-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/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-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/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-20191210023423-ac6580df4449/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-20200519105757-fe76b779f299/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-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/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-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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +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.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/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-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/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-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190617190820-da514acc4774/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-20190624222133-a101b041ded4/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-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/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-20190920225731-5eefd052ad72/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-20191030203535-5e247c9ad0a0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/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-20200115044656-831fdb1e1868/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-20200505023115-26f46d2f7ef8/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-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +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.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= +gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +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.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.147.0 h1:Can3FaQo9LlVqxJCodNmeZW/ib3/qKAY3rFeXiHo5gc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= +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-20190404172233-64821d5d2107/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 v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210416161957-9910b6c460de/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c h1:jHkCUWkseRf+W+edG5hMzr/Uh1xkDREY4caybAq4dpY= +google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +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.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +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.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/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-20200227125254-8fa46927fb4f/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/imdario/mergo.v0 v0.3.7/go.mod h1:9qPP6AGrlC1G2PTNXko614FwGZvorN7MiBU0Eppok+U= +gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= +gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= +gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= +gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= +gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= +gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +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-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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 v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +helm.sh/helm/v3 v3.1.2/go.mod h1:WYsFJuMASa/4XUqLyv54s0U/f3mlAaRErGmyy4z921g= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +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.0.0-20190918155943-95b840bb6a1f/go.mod h1:uWuOHnjmNrtQomJrvEBg0c0HRNyQ+8KTEERVsK0PW48= +k8s.io/api v0.16.7/go.mod h1:oUAiGRgo4t+5yqcxjOu5LoHT3wJ8JSbgczkaFYS5L7I= +k8s.io/api v0.17.1/go.mod h1:zxiAc5y8Ngn4fmhWUtSxuUlkfz1ixT7j9wESokELzOg= +k8s.io/api v0.17.2/go.mod h1:BS9fjjLc4CMuqfSO8vgbHPKMt5+SF0ET6u/RVDihTo4= +k8s.io/api v0.17.3/go.mod h1:YZ0OTkuw7ipbe305fMpIdf3GLXZKRigjtZaV5gzC2J0= +k8s.io/api v0.21.4/go.mod h1:fTVGP+M4D8+00FN2cMnJqk/eb/GH53bvmNs2SVTmpFk= +k8s.io/api v0.27.6 h1:PBWu/lywJe2qQcshMjubzcBg7+XDZOo7O8JJAWuYtUo= +k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783/go.mod h1:xvae1SZB3E17UpV59AWc271W/Ph25N+bjPyR63X6tPY= +k8s.io/apiextensions-apiserver v0.16.7/go.mod h1:6xYRp4trGp6eT5WZ6tPi/TB2nfWQCzwUvBlpg8iswe0= +k8s.io/apiextensions-apiserver v0.17.2/go.mod h1:4KdMpjkEjjDI2pPfBA15OscyNldHWdBCfsWMDWAmSTs= +k8s.io/apiextensions-apiserver v0.17.3/go.mod h1:CJbCyMfkKftAd/X/V6OTHYhVn7zXnDdnkUjS1h0GTeY= +k8s.io/apiextensions-apiserver v0.21.4/go.mod h1:OoC8LhI9LnV+wKjZkXIBbLUwtnOGJiTRE33qctH5CIk= +k8s.io/apiextensions-apiserver v0.27.6 h1:mOwSBJtThZhpJr+8gEkc3wFDIjq87E3JspR5mtZxIg8= +k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655/go.mod h1:nL6pwRT8NgfF8TT68DBI8uEePRt89cSvoXUVqbkWHq4= +k8s.io/apimachinery v0.16.7/go.mod h1:Xk2vD2TRRpuWYLQNM6lT9R7DSFZUYG03SarNkbGrnKE= +k8s.io/apimachinery v0.17.1/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= +k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= +k8s.io/apimachinery v0.17.3/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g= +k8s.io/apimachinery v0.19.7/go.mod h1:6sRbGRAVY5DOCuZwB5XkqguBqpqLU6q/kOaOdk29z6Q= +k8s.io/apimachinery v0.21.4/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI= +k8s.io/apimachinery v0.27.6 h1:mGU8jmBq5o8mWBov+mLjdTBcU+etTE19waies4AQ6NE= +k8s.io/apiserver v0.0.0-20190918160949-bfa5e2e684ad/go.mod h1:XPCXEwhjaFN29a8NldXA901ElnKeKLrLtREO9ZhFyhg= +k8s.io/apiserver v0.16.7/go.mod h1:/5zSatF30/L9zYfMTl55jzzOnx7r/gGv5a5wtRp8yAw= +k8s.io/apiserver v0.17.2/go.mod h1:lBmw/TtQdtxvrTk0e2cgtOxHizXI+d0mmGQURIHQZlo= +k8s.io/apiserver v0.17.3/go.mod h1:iJtsPpu1ZpEnHaNawpSV0nYTGBhhX2dUlnn7/QS7QiY= +k8s.io/apiserver v0.21.4/go.mod h1:SErUuFBBPZUcD2nsUU8hItxoYheqyYr2o/pCINEPW8g= +k8s.io/cli-runtime v0.17.2/go.mod h1:aa8t9ziyQdbkuizkNLAw3qe3srSyWh9zlSB7zTqRNPI= +k8s.io/cli-runtime v0.17.3/go.mod h1:X7idckYphH4SZflgNpOOViSxetiMj6xI0viMAjM81TA= +k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53q3Uz5OSfgsv4uxpScmmyYOOlk= +k8s.io/client-go v0.16.7/go.mod h1:9kEMEeuy2LdsHHXoU2Skqh+SDso+Yhkxd/0tltvswDE= +k8s.io/client-go v0.17.2/go.mod h1:QAzRgsa0C2xl4/eVpeVAZMvikCn8Nm81yqVx3Kk9XYI= +k8s.io/client-go v0.17.3/go.mod h1:cLXlTMtWHkuK4tD360KpWz2gG2KtdWEr/OT02i3emRQ= +k8s.io/client-go v0.21.4/go.mod h1:t0/eMKyUAq/DoQ7vW8NVVA00/nomlwC+eInsS8PxSew= +k8s.io/client-go v0.27.6 h1:vzI8804gpUtpMCNaFjIFyJrifH7u//LJCJPy8fQuYQg= +k8s.io/code-generator v0.0.0-20190912054826-cd179ad6a269/go.mod h1:V5BD6M4CyaN5m+VthcclXWsVcT1Hu+glwa1bi3MIsyE= +k8s.io/code-generator v0.16.7/go.mod h1:wFdrXdVi/UC+xIfLi+4l9elsTT/uEF61IfcN2wOLULQ= +k8s.io/code-generator v0.17.1/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= +k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= +k8s.io/code-generator v0.17.3/go.mod h1:l8BLVwASXQZTo2xamW5mQNFCe1XPiAesVq7Y1t7PiQQ= +k8s.io/code-generator v0.21.4/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo= +k8s.io/component-base v0.0.0-20190918160511-547f6c5d7090/go.mod h1:933PBGtQFJky3TEwYx4aEPZ4IxqhWh3R6DCmzqIn1hA= +k8s.io/component-base v0.16.7/go.mod h1:ikdyfezOFMu5O0qJjy/Y9eXwj+fV3pVwdmt0ulVcIR0= +k8s.io/component-base v0.17.2/go.mod h1:zMPW3g5aH7cHJpKYQ/ZsGMcgbsA/VyhEugF3QT1awLs= +k8s.io/component-base v0.17.3/go.mod h1:GeQf4BrgelWm64PXkIXiPh/XS0hnO42d9gx9BtbZRp8= +k8s.io/component-base v0.21.4/go.mod h1:ZKG0eHVX+tUDcaoIGpU3Vtk4TIjMddN9uhEWDmW6Nyg= +k8s.io/component-base v0.27.6 h1:hF5WxX7Tpi9/dXAbLjPVkIA6CA6Pi6r9JOHyo0uCDYI= +k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20210203185629-de9496dff47b/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-aggregator v0.17.3/go.mod h1:1dMwMFQbmH76RKF0614L7dNenMl3dwnUJuOOyZ3GMXA= +k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= +k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= +k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= +k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 h1:OmK1d0WrkD3IPfkskvroRykOulHVHf0s0ZIFRjyt+UI= +k8s.io/kubectl v0.17.2/go.mod h1:y4rfLV0n6aPmvbRCqZQjvOp3ezxsFgpqL+zF5jH/lxk= +k8s.io/kubectl v0.17.3/go.mod h1:NUn4IBY7f7yCMwSop2HCXlw/MVYP4HJBiUmOR3n9w28= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +k8s.io/metrics v0.17.2/go.mod h1:3TkNHET4ROd+NfzNxkjoVfQ0Ob4iZnaHmSEA4vYpwLw= +k8s.io/metrics v0.17.3/go.mod h1:HEJGy1fhHOjHggW9rMDBJBD3YuGroH3Y1pnIRw9FFaI= +k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc= +knative.dev/eventing v0.26.0 h1:osDUdav7S0FuChN0onfwL5cEcsdb54Kee2hjAPMpY7o= +knative.dev/eventing v0.26.0/go.mod h1:6tTam0lsPtBSJHJ63/195obj2VAHlTZZB7TLiBSeqk0= +knative.dev/hack v0.0.0-20210806075220-815cd312d65c/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= +knative.dev/hack/schema v0.0.0-20210806075220-815cd312d65c/go.mod h1:ffjwmdcrH5vN3mPhO8RrF2KfNnbHeCE2C60A+2cv3U0= +knative.dev/pkg v0.0.0-20210914164111-4857ab6939e3/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8= +knative.dev/pkg v0.0.0-20210919202233-5ae482141474/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8= +knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c h1:xyPoEToTWeBdn6tinhLxXfnhJhTNQt5WzHiTNiFphRw= +knative.dev/reconciler-test v0.0.0-20210915181908-49fac7555086/go.mod h1:6yDmb26SINSmgw6wVy9qQwgRMewiW8ddkkwGLR0ZvOY= +modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= +modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= +modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= +modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= +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/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= +sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +sigs.k8s.io/controller-tools v0.2.4/go.mod h1:m/ztfQNocGYBgTTCmFdnK94uVvgxeZeE3LtJvd/jIzA= +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/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= +sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= +sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= +sigs.k8s.io/structured-merge-diff v1.0.2/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI= diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/groupversion_info.go b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/groupversion_info.go new file mode 100644 index 00000000000..41dad162afc --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/groupversion_info.go @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// Package v1beta1 contains API Schema definitions for the app v1beta1 API group +// +kubebuilder:object:generate=true +// +groupName=app.kiegroup.org +package v1beta1 + +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: "app.kiegroup.org", Version: "v1beta1"} + + // 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 + + // SchemeGroupVersion is a alias for the generated clientset + SchemeGroupVersion = GroupVersion +) + +// Resource takes an unqualified resource and returns a Group qualified GroupResource. Required for clientset +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/kogitoservices.go b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/kogitoservices.go new file mode 100644 index 00000000000..3168c10280c --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/kogitoservices.go @@ -0,0 +1,452 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1beta1 + +import ( + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api" +) + +// KogitoServiceStatus is the basic structure for any Kogito Service status. +type KogitoServiceStatus struct { + // +listType=atomic + // History of conditions for the resource + // +operator-sdk:csv:customresourcedefinitions:type=status + // +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:io.kubernetes.conditions" + Conditions *[]metav1.Condition `json:"conditions"` + // General conditions for the Kogito Service deployment. + // +operator-sdk:csv:customresourcedefinitions:type=status + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Deployment Conditions" + // +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:io.kubernetes.conditions" + DeploymentConditions []appsv1.DeploymentCondition `json:"deploymentConditions,omitempty"` + // General conditions for the Kogito Service route. + // +operator-sdk:csv:customresourcedefinitions:type=status + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Route Conditions" + // +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:io.kubernetes.conditions" + RouteConditions *[]metav1.Condition `json:"routeConditions,omitempty"` + // Image is the resolved image for this service. + // +operator-sdk:csv:customresourcedefinitions:type=status + Image string `json:"image,omitempty"` + // URI is where the service is exposed. + // +operator-sdk:csv:customresourcedefinitions:type=status + // +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors="urn:alm:descriptor:org.w3:link" + ExternalURI string `json:"externalURI,omitempty"` + // Describes the CloudEvents that this instance can consume or produce + // +operator-sdk:csv:customresourcedefinitions:type=status + CloudEvents KogitoCloudEventsStatus `json:"cloudEvents,omitempty"` +} + +// GetConditions ... +func (k *KogitoServiceStatus) GetConditions() *[]metav1.Condition { + return k.Conditions +} + +// SetConditions ... +func (k *KogitoServiceStatus) SetConditions(conditions *[]metav1.Condition) { + k.Conditions = conditions +} + +// GetDeploymentConditions gets the deployment conditions for the service. +func (k *KogitoServiceStatus) GetDeploymentConditions() []appsv1.DeploymentCondition { + return k.DeploymentConditions +} + +// SetDeploymentConditions sets the deployment conditions for the service. +func (k *KogitoServiceStatus) SetDeploymentConditions(deploymentConditions []appsv1.DeploymentCondition) { + k.DeploymentConditions = deploymentConditions +} + +// GetRouteConditions gets the deployment conditions for the service. +func (k *KogitoServiceStatus) GetRouteConditions() *[]metav1.Condition { + return k.RouteConditions +} + +// SetRouteConditions sets the deployment conditions for the service. +func (k *KogitoServiceStatus) SetRouteConditions(conditions *[]metav1.Condition) { + k.RouteConditions = conditions +} + +// GetImage ... +func (k *KogitoServiceStatus) GetImage() string { return k.Image } + +// SetImage ... +func (k *KogitoServiceStatus) SetImage(image string) { k.Image = image } + +// GetExternalURI ... +func (k *KogitoServiceStatus) GetExternalURI() string { return k.ExternalURI } + +// SetExternalURI ... +func (k *KogitoServiceStatus) SetExternalURI(uri string) { k.ExternalURI = uri } + +// GetCloudEvents ... +func (k *KogitoServiceStatus) GetCloudEvents() api.KogitoCloudEventsStatusInterface { + return &k.CloudEvents +} + +// SetCloudEvents ... +func (k *KogitoServiceStatus) SetCloudEvents(cloudEvents api.KogitoCloudEventsStatusInterface) { + if newCloudEvents, ok := cloudEvents.(*KogitoCloudEventsStatus); ok { + k.CloudEvents = *newCloudEvents + } +} + +// KogitoCloudEventsStatus describes the CloudEvents that can be produced or consumed by this Kogito Service instance +type KogitoCloudEventsStatus struct { + // +optional + // +listType=atomic + // +operator-sdk:csv:customresourcedefinitions:type=status + Consumes []KogitoCloudEventInfo `json:"consumes,omitempty"` + // +optional + // +listType=atomic + // +operator-sdk:csv:customresourcedefinitions:type=status + Produces []KogitoCloudEventInfo `json:"produces,omitempty"` +} + +// GetConsumes ... +func (k *KogitoCloudEventsStatus) GetConsumes() []api.KogitoCloudEventInfoInterface { + consumes := make([]api.KogitoCloudEventInfoInterface, len(k.Consumes)) + for i, v := range k.Consumes { + consumes[i] = api.KogitoCloudEventInfoInterface(v) + } + return consumes +} + +// SetConsumes ... +func (k *KogitoCloudEventsStatus) SetConsumes(consumes []api.KogitoCloudEventInfoInterface) { + var newConsumes []KogitoCloudEventInfo + for _, consume := range consumes { + if newConsume, ok := consume.(KogitoCloudEventInfo); ok { + newConsumes = append(newConsumes, newConsume) + } + } + k.Consumes = newConsumes +} + +// GetProduces ... +func (k *KogitoCloudEventsStatus) GetProduces() []api.KogitoCloudEventInfoInterface { + produces := make([]api.KogitoCloudEventInfoInterface, len(k.Produces)) + for i, v := range k.Produces { + produces[i] = api.KogitoCloudEventInfoInterface(v) + } + return produces +} + +// SetProduces ... +func (k *KogitoCloudEventsStatus) SetProduces(produces []api.KogitoCloudEventInfoInterface) { + var newProduces []KogitoCloudEventInfo + for _, produce := range produces { + if newProduce, ok := produce.(KogitoCloudEventInfo); ok { + newProduces = append(newProduces, newProduce) + } + } + k.Produces = newProduces +} + +// KogitoCloudEventInfo describes the CloudEvent information based on the specification +type KogitoCloudEventInfo struct { + // +operator-sdk:csv:customresourcedefinitions:type=status + Type string `json:"type"` + // +operator-sdk:csv:customresourcedefinitions:type=status + Source string `json:"source,omitempty"` +} + +// GetType ... +func (k KogitoCloudEventInfo) GetType() string { + return k.Type +} + +// GetSource ... +func (k KogitoCloudEventInfo) GetSource() string { + return k.Source +} + +// KogitoServiceSpec is the basic structure for the Kogito Service specification. +type KogitoServiceSpec struct { + + // Number of replicas that the service will have deployed in the cluster. + // + // Default value: 1. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Replicas" + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:com.tectonic.ui:podCount" + // +kubebuilder:validation:Minimum=0 + Replicas *int32 `json:"replicas,omitempty"` + + // +optional + // +listType=atomic + // Environment variables to be added to the runtime container. Keys must be a C_IDENTIFIER. + // +operator-sdk:csv:customresourcedefinitions:type=spec + Env []corev1.EnvVar `json:"env,omitempty"` + + // +optional + // Image definition for the service. Example: "quay.io/kiegroup/kogito-service:latest". + // + // On OpenShift an ImageStream will be created in the current namespace pointing to the given image. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:com.tectonic.ui:text" + Image string `json:"image,omitempty"` + + // +optional + // A flag indicating that image streams created by Kogito Operator should be configured to allow pulling from insecure registries. + // Usable just on OpenShift. + // + // Defaults to 'false'. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Insecure Image Registry" + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch" + InsecureImageRegistry bool `json:"insecureImageRegistry,omitempty"` + + // Defined compute resource requirements for the deployed service. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:com.tectonic.ui:resourceRequirements" + Resources corev1.ResourceRequirements `json:"resources,omitempty"` + + // Additional labels to be added to the Deployment and Pods managed by the operator. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Additional Deployment Labels" + DeploymentLabels map[string]string `json:"deploymentLabels,omitempty"` + + // Additional labels to be added to the Service managed by the operator. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Additional Service Labels" + ServiceLabels map[string]string `json:"serviceLabels,omitempty"` + + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="ConfigMap Properties" + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:io.kubernetes:ConfigMap" + // Custom ConfigMap with application.properties file to be mounted for the Kogito service. + // + // The ConfigMap must be created in the same namespace. + // + // Use this property if you need custom properties to be mounted before the application deployment. + // + // If left empty, one will be created for you. Later it can be updated to add any custom properties to apply to the service. + PropertiesConfigMap string `json:"propertiesConfigMap,omitempty"` + + // Infra provides list of dependent KogitoInfra objects. + // +optional + Infra []string `json:"infra,omitempty"` + + // Create Service monitor instance to connect with Monitoring service + // +optional + Monitoring Monitoring `json:"monitoring,omitempty"` + + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Configs" + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:com.tectonic.ui:text" + // Application properties that will be set to the service. For example 'MY_VAR: my_value'. + Config map[string]string `json:"config,omitempty"` + + // Configure liveness, readiness and startup probes for containers + // +optional + Probes KogitoProbe `json:"probes,omitempty"` + + // Custom JKS TrustStore that will be used by this service to make calls to TLS endpoints. + // + // It's expected that the secret has two keys: `keyStorePassword` containing the password for the KeyStore + // and `cacerts` containing the binary data of the given KeyStore. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:io.kubernetes:Secret" + TrustStoreSecret string `json:"trustStoreSecret,omitempty"` + + // A flag indicating that routes are disabled. Usable just on OpenShift. + // + // If not provided, defaults to 'false'. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="DisableRoute" + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch" + DisableRoute bool `json:"disableRoute,omitempty"` +} + +// GetReplicas ... +func (k *KogitoServiceSpec) GetReplicas() *int32 { return k.Replicas } + +// SetReplicas ... +func (k *KogitoServiceSpec) SetReplicas(replicas int32) { k.Replicas = &replicas } + +// GetEnvs ... +func (k *KogitoServiceSpec) GetEnvs() []corev1.EnvVar { return k.Env } + +// SetEnvs ... +func (k *KogitoServiceSpec) SetEnvs(envs []corev1.EnvVar) { k.Env = envs } + +// GetImage ... +func (k *KogitoServiceSpec) GetImage() string { return k.Image } + +// SetImage ... +func (k *KogitoServiceSpec) SetImage(image string) { k.Image = image } + +// GetResources ... +func (k *KogitoServiceSpec) GetResources() corev1.ResourceRequirements { return k.Resources } + +// SetResources ... +func (k *KogitoServiceSpec) SetResources(resources corev1.ResourceRequirements) { + k.Resources = resources +} + +// AddEnvironmentVariable adds new environment variable to service environment variables. +func (k *KogitoServiceSpec) AddEnvironmentVariable(name, value string) { + env := corev1.EnvVar{ + Name: name, + Value: value, + } + k.Env = append(k.Env, env) +} + +// AddEnvironmentVariableFromSecret adds a new environment variable from the secret under the key. +func (k *KogitoServiceSpec) AddEnvironmentVariableFromSecret(variableName, secretName, secretKey string) { + env := corev1.EnvVar{ + Name: variableName, + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: secretName, + }, + Key: secretKey, + }, + }, + } + k.Env = append(k.Env, env) +} + +// AddResourceRequest adds new resource request. Works also on uninitialized Requests field. +func (k *KogitoServiceSpec) AddResourceRequest(name, value string) { + if k.Resources.Requests == nil { + k.Resources.Requests = corev1.ResourceList{} + } + + k.Resources.Requests[corev1.ResourceName(name)] = resource.MustParse(value) +} + +// AddResourceLimit adds new resource limit. Works also on uninitialized Limits field. +func (k *KogitoServiceSpec) AddResourceLimit(name, value string) { + if k.Resources.Limits == nil { + k.Resources.Limits = corev1.ResourceList{} + } + + k.Resources.Limits[corev1.ResourceName(name)] = resource.MustParse(value) +} + +// GetDeploymentLabels ... +func (k *KogitoServiceSpec) GetDeploymentLabels() map[string]string { return k.DeploymentLabels } + +// SetDeploymentLabels ... +func (k *KogitoServiceSpec) SetDeploymentLabels(labels map[string]string) { + k.DeploymentLabels = labels +} + +// AddDeploymentLabel adds new deployment label. Works also on uninitialized DeploymentLabels field. +func (k *KogitoServiceSpec) AddDeploymentLabel(name, value string) { + if k.DeploymentLabels == nil { + k.DeploymentLabels = make(map[string]string) + } + + k.DeploymentLabels[name] = value +} + +// GetServiceLabels ... +func (k *KogitoServiceSpec) GetServiceLabels() map[string]string { return k.ServiceLabels } + +// SetServiceLabels ... +func (k *KogitoServiceSpec) SetServiceLabels(labels map[string]string) { k.ServiceLabels = labels } + +// AddServiceLabel adds new service label. Works also on uninitialized ServiceLabels field. +func (k *KogitoServiceSpec) AddServiceLabel(name, value string) { + if k.ServiceLabels == nil { + k.ServiceLabels = make(map[string]string) + } + + k.ServiceLabels[name] = value +} + +// IsInsecureImageRegistry ... +func (k *KogitoServiceSpec) IsInsecureImageRegistry() bool { return k.InsecureImageRegistry } + +// GetPropertiesConfigMap ... +func (k *KogitoServiceSpec) GetPropertiesConfigMap() string { + return k.PropertiesConfigMap +} + +// GetInfra ... +func (k *KogitoServiceSpec) GetInfra() []string { return k.Infra } + +// AddInfra ... +func (k *KogitoServiceSpec) AddInfra(name string) { + k.Infra = append(k.Infra, name) +} + +// GetMonitoring ... +func (k *KogitoServiceSpec) GetMonitoring() api.MonitoringInterface { + return &k.Monitoring +} + +// SetMonitoring ... +func (k *KogitoServiceSpec) SetMonitoring(monitoring api.MonitoringInterface) { + if newMonitoring, ok := monitoring.(*Monitoring); ok { + k.Monitoring = *newMonitoring + } +} + +// GetConfig ... +func (k *KogitoServiceSpec) GetConfig() map[string]string { + return k.Config +} + +// GetProbes ... +func (k *KogitoServiceSpec) GetProbes() api.KogitoProbeInterface { + return &k.Probes +} + +// SetProbes ... +func (k *KogitoServiceSpec) SetProbes(probes api.KogitoProbeInterface) { + if newProbes, ok := probes.(*KogitoProbe); ok { + k.Probes = *newProbes + } +} + +// GetTrustStoreSecret ... +func (k *KogitoServiceSpec) GetTrustStoreSecret() string { + return k.TrustStoreSecret +} + +// SetTrustStoreSecret ... +func (k *KogitoServiceSpec) SetTrustStoreSecret(trustStoreSecret string) { + k.TrustStoreSecret = trustStoreSecret +} + +// IsRouteDisabled ... +func (k *KogitoServiceSpec) IsRouteDisabled() bool { + return k.DisableRoute +} + +// SetDisableRoute ... +func (k *KogitoServiceSpec) SetDisableRoute(disableRoute bool) { + k.DisableRoute = disableRoute +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/kogitosupportingservice_types.go b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/kogitosupportingservice_types.go new file mode 100644 index 00000000000..36e8b893703 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/kogitosupportingservice_types.go @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api" +) + +// KogitoSupportingServiceSpec defines the desired state of KogitoSupportingService. +// +k8s:openapi-gen=true +type KogitoSupportingServiceSpec struct { + KogitoServiceSpec `json:",inline"` + + // Defines the type for the supporting service, eg: DataIndex, JobsService + // Default value: JobsService + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Service Type" + // +kubebuilder:validation:Required + // +kubebuilder:validation:Enum=DataIndex;Explainability;JobsService;MgmtConsole;TaskConsole;TrustyAI;TrustyUI + ServiceType api.ServiceType `json:"serviceType"` +} + +// GetRuntime ... +func (k *KogitoSupportingServiceSpec) GetRuntime() api.RuntimeType { + return api.QuarkusRuntimeType +} + +// GetServiceType ... +func (k *KogitoSupportingServiceSpec) GetServiceType() api.ServiceType { + return k.ServiceType +} + +// SetServiceType ... +func (k *KogitoSupportingServiceSpec) SetServiceType(serviceType api.ServiceType) { + k.ServiceType = serviceType +} + +// KogitoSupportingServiceStatus defines the observed state of KogitoSupportingService. +// +k8s:openapi-gen=true +type KogitoSupportingServiceStatus struct { + KogitoServiceStatus `json:",inline"` +} + +// +kubebuilder:object:root=true +// +k8s:openapi-gen=true +// +genclient +// +kubebuilder:resource:path=kogitosupportingservices,scope=Namespaced +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Replicas",type="integer",JSONPath=".spec.replicas",description="Number of replicas set for this service" +// +kubebuilder:printcolumn:name="Image",type="string",JSONPath=".status.image",description="Base image for this service" +// +kubebuilder:printcolumn:name="Endpoint",type="string",JSONPath=".status.externalURI",description="External URI to access this service" +// +kubebuilder:printcolumn:name="Service Type",type="string",JSONPath=".spec.serviceType",description="Supporting Service Type" +// +operator-sdk:csv:customresourcedefinitions:displayName="Kogito Supporting Service" +// +operator-sdk:csv:customresourcedefinitions:resources={{Deployment,apps/v1,"A Kubernetes Deployment"}} +// +operator-sdk:csv:customresourcedefinitions:resources={{Service,v1,"A Kubernetes Service"}} +// +operator-sdk:csv:customresourcedefinitions:resources={{ImageStream,image.openshift.io/v1,"A Openshift ImageStream"}} +// +operator-sdk:csv:customresourcedefinitions:resources={{Route,route.openshift.io/v1,"A Openshift Route"}} + +// KogitoSupportingService deploys the Supporting service in the given namespace. +type KogitoSupportingService struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KogitoSupportingServiceSpec `json:"spec,omitempty"` + Status KogitoSupportingServiceStatus `json:"status,omitempty"` +} + +// GetSpec ... +func (k *KogitoSupportingService) GetSpec() api.KogitoServiceSpecInterface { + return &k.Spec +} + +// GetStatus ... +func (k *KogitoSupportingService) GetStatus() api.KogitoServiceStatusInterface { + return &k.Status +} + +// GetSupportingServiceSpec ... +func (k *KogitoSupportingService) GetSupportingServiceSpec() api.KogitoSupportingServiceSpecInterface { + return &k.Spec +} + +// GetSupportingServiceStatus ... +func (k *KogitoSupportingService) GetSupportingServiceStatus() api.KogitoSupportingServiceStatusInterface { + return &k.Status +} + +// +kubebuilder:object:root=true + +// KogitoSupportingServiceList contains a list of KogitoSupportingService. +type KogitoSupportingServiceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []KogitoSupportingService `json:"items"` +} + +// GetItems ... +func (k *KogitoSupportingServiceList) GetItems() []api.KogitoSupportingServiceInterface { + models := make([]api.KogitoSupportingServiceInterface, len(k.Items)) + for i, v := range k.Items { + item := v + models[i] = &item + } + return models +} + +func init() { + SchemeBuilder.Register(&KogitoSupportingService{}, &KogitoSupportingServiceList{}) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/kogitosupportingservice_types_test.go b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/kogitosupportingservice_types_test.go new file mode 100644 index 00000000000..2a50fe2919e --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/kogitosupportingservice_types_test.go @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1beta1 + +import ( + "testing" + + "github.com/stretchr/testify/assert" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api" +) + +func TestGetItems(t *testing.T) { + kogitoSupportingServiceList := &KogitoSupportingServiceList{ + Items: []KogitoSupportingService{ + { + ObjectMeta: v1.ObjectMeta{ + Name: "data-index", + }, + Spec: KogitoSupportingServiceSpec{ + ServiceType: api.DataIndex, + }, + }, + { + ObjectMeta: v1.ObjectMeta{ + Name: "mgmt-console", + }, + Spec: KogitoSupportingServiceSpec{ + ServiceType: api.MgmtConsole, + }, + }, + }, + } + + kogitoSupportingServiceInterface := kogitoSupportingServiceList.GetItems() + assert.Equal(t, 2, len(kogitoSupportingServiceInterface)) + + assert.Equal(t, "data-index", kogitoSupportingServiceInterface[0].GetName()) + assert.Equal(t, api.DataIndex, kogitoSupportingServiceInterface[0].GetSupportingServiceSpec().GetServiceType()) + + assert.Equal(t, "mgmt-console", kogitoSupportingServiceInterface[1].GetName()) + assert.Equal(t, api.MgmtConsole, kogitoSupportingServiceInterface[1].GetSupportingServiceSpec().GetServiceType()) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/monitoring.go b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/monitoring.go new file mode 100644 index 00000000000..80742f5fe49 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/monitoring.go @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1beta1 + +// Monitoring properties to connect with Monitoring service +type Monitoring struct { + // HTTP scheme to use for scraping. + // +optional + Scheme string `json:"scheme,omitempty"` + + // HTTP path to scrape for metrics. + // +optional + Path string `json:"path,omitempty"` +} + +// GetScheme ... +func (m *Monitoring) GetScheme() string { + return m.Scheme +} + +// SetScheme ... +func (m *Monitoring) SetScheme(scheme string) { + m.Scheme = scheme +} + +// GetPath ... +func (m *Monitoring) GetPath() string { + return m.Path +} + +// SetPath ... +func (m *Monitoring) SetPath(path string) { + m.Path = path +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/probe.go b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/probe.go new file mode 100644 index 00000000000..55483941b42 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/probe.go @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1beta1 + +import corev1 "k8s.io/api/core/v1" + +// KogitoProbe configure liveness, readiness and startup probes for containers +type KogitoProbe struct { + // LivenessProbe describes how the Kogito container liveness probe should work + // + + // +optional + LivenessProbe corev1.Probe `json:"livenessProbe,omitempty"` + + // ReadinessProbe describes how the Kogito container readiness probe should work + // + + // +optional + ReadinessProbe corev1.Probe `json:"readinessProbe,omitempty"` + + // StartupProbe describes how the Kogito container startup probe should work + // + + // +optional + StartupProbe corev1.Probe `json:"startupProbe,omitempty"` +} + +// GetLivenessProbe ... +func (p *KogitoProbe) GetLivenessProbe() corev1.Probe { + return p.LivenessProbe +} + +// SetLivenessProbe ... +func (p *KogitoProbe) SetLivenessProbe(livenessProbe corev1.Probe) { + p.LivenessProbe = livenessProbe +} + +// GetReadinessProbe ... +func (p *KogitoProbe) GetReadinessProbe() corev1.Probe { + return p.ReadinessProbe +} + +// SetReadinessProbe ... +func (p *KogitoProbe) SetReadinessProbe(readinessProbe corev1.Probe) { + p.ReadinessProbe = readinessProbe +} + +// GetStartupProbe ... +func (p *KogitoProbe) GetStartupProbe() corev1.Probe { + return p.StartupProbe +} + +// SetStartupProbe ... +func (p *KogitoProbe) SetStartupProbe(startupProbe corev1.Probe) { + p.StartupProbe = startupProbe +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/webhook.go b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/webhook.go new file mode 100644 index 00000000000..a61dba6a814 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/webhook.go @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1beta1 + +import "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api" + +// WebHookSecret Secret to use for a given webHook. +// +k8s:openapi-gen=true +type WebHookSecret struct { + // WebHook type, either GitHub or Generic. + // +kubebuilder:validation:Enum=GitHub;Generic + Type api.WebHookType `json:"type,omitempty"` + // Secret value for webHook + Secret string `json:"secret,omitempty"` +} + +// GetType ... +func (w WebHookSecret) GetType() api.WebHookType { + return w.Type +} + +// GetSecret ... +func (w WebHookSecret) GetSecret() string { + return w.Secret +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/zz_generated.deepcopy.go b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..52be5722e74 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,292 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright 2021 Red Hat, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 v1beta1 + +import ( + appsv1 "k8s.io/api/apps/v1" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KogitoCloudEventInfo) DeepCopyInto(out *KogitoCloudEventInfo) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KogitoCloudEventInfo. +func (in *KogitoCloudEventInfo) DeepCopy() *KogitoCloudEventInfo { + if in == nil { + return nil + } + out := new(KogitoCloudEventInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KogitoCloudEventsStatus) DeepCopyInto(out *KogitoCloudEventsStatus) { + *out = *in + if in.Consumes != nil { + in, out := &in.Consumes, &out.Consumes + *out = make([]KogitoCloudEventInfo, len(*in)) + copy(*out, *in) + } + if in.Produces != nil { + in, out := &in.Produces, &out.Produces + *out = make([]KogitoCloudEventInfo, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KogitoCloudEventsStatus. +func (in *KogitoCloudEventsStatus) DeepCopy() *KogitoCloudEventsStatus { + if in == nil { + return nil + } + out := new(KogitoCloudEventsStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KogitoProbe) DeepCopyInto(out *KogitoProbe) { + *out = *in + in.LivenessProbe.DeepCopyInto(&out.LivenessProbe) + in.ReadinessProbe.DeepCopyInto(&out.ReadinessProbe) + in.StartupProbe.DeepCopyInto(&out.StartupProbe) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KogitoProbe. +func (in *KogitoProbe) DeepCopy() *KogitoProbe { + if in == nil { + return nil + } + out := new(KogitoProbe) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KogitoServiceSpec) DeepCopyInto(out *KogitoServiceSpec) { + *out = *in + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } + 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.DeploymentLabels != nil { + in, out := &in.DeploymentLabels, &out.DeploymentLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.ServiceLabels != nil { + in, out := &in.ServiceLabels, &out.ServiceLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Infra != nil { + in, out := &in.Infra, &out.Infra + *out = make([]string, len(*in)) + copy(*out, *in) + } + out.Monitoring = in.Monitoring + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + in.Probes.DeepCopyInto(&out.Probes) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KogitoServiceSpec. +func (in *KogitoServiceSpec) DeepCopy() *KogitoServiceSpec { + if in == nil { + return nil + } + out := new(KogitoServiceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KogitoServiceStatus) DeepCopyInto(out *KogitoServiceStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = new([]metav1.Condition) + if **in != nil { + in, out := *in, *out + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + } + if in.DeploymentConditions != nil { + in, out := &in.DeploymentConditions, &out.DeploymentConditions + *out = make([]appsv1.DeploymentCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.RouteConditions != nil { + in, out := &in.RouteConditions, &out.RouteConditions + *out = new([]metav1.Condition) + if **in != nil { + in, out := *in, *out + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + } + in.CloudEvents.DeepCopyInto(&out.CloudEvents) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KogitoServiceStatus. +func (in *KogitoServiceStatus) DeepCopy() *KogitoServiceStatus { + if in == nil { + return nil + } + out := new(KogitoServiceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KogitoSupportingService) DeepCopyInto(out *KogitoSupportingService) { + *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 KogitoSupportingService. +func (in *KogitoSupportingService) DeepCopy() *KogitoSupportingService { + if in == nil { + return nil + } + out := new(KogitoSupportingService) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KogitoSupportingService) 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 *KogitoSupportingServiceList) DeepCopyInto(out *KogitoSupportingServiceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KogitoSupportingService, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KogitoSupportingServiceList. +func (in *KogitoSupportingServiceList) DeepCopy() *KogitoSupportingServiceList { + if in == nil { + return nil + } + out := new(KogitoSupportingServiceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KogitoSupportingServiceList) 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 *KogitoSupportingServiceSpec) DeepCopyInto(out *KogitoSupportingServiceSpec) { + *out = *in + in.KogitoServiceSpec.DeepCopyInto(&out.KogitoServiceSpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KogitoSupportingServiceSpec. +func (in *KogitoSupportingServiceSpec) DeepCopy() *KogitoSupportingServiceSpec { + if in == nil { + return nil + } + out := new(KogitoSupportingServiceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KogitoSupportingServiceStatus) DeepCopyInto(out *KogitoSupportingServiceStatus) { + *out = *in + in.KogitoServiceStatus.DeepCopyInto(&out.KogitoServiceStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KogitoSupportingServiceStatus. +func (in *KogitoSupportingServiceStatus) DeepCopy() *KogitoSupportingServiceStatus { + if in == nil { + return nil + } + out := new(KogitoSupportingServiceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Monitoring) DeepCopyInto(out *Monitoring) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Monitoring. +func (in *Monitoring) DeepCopy() *Monitoring { + if in == nil { + return nil + } + out := new(Monitoring) + in.DeepCopyInto(out) + return out +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2/groupversion_info.go b/packages/kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2/groupversion_info.go new file mode 100644 index 00000000000..3f379903825 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright 2021. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1alpha2 contains API Schema definitions for the v1alpha2 API group +// +kubebuilder:object:generate=true +// +groupName=hyperfoil.io +package v1alpha2 + +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: "hyperfoil.io", Version: "v1alpha2"} + + // 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/packages/kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2/hyperfoil_types.go b/packages/kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2/hyperfoil_types.go new file mode 100644 index 00000000000..87dc265e4ed --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2/hyperfoil_types.go @@ -0,0 +1,110 @@ +/* +Copyright 2021. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// HyperfoilSpec Configures Hyperfoil Controller and related resources. +type HyperfoilSpec struct { + // Controller image. If 'version' is defined, too, the tag is replaced (or appended). Defaults to 'quay.io/hyperfoil/hyperfoil' + Image string `json:"image,omitempty"` + // Tag for controller image. Defaults to version matching the operator version. + Version string `json:"version,omitempty"` + // Specification of the exposed route. + Route RouteSpec `json:"route,omitempty"` + // Authentication/authorization settings. + Auth AuthSpec `json:"auth,omitempty"` + // Name of the config map and optionally its entry (separated by '/': e.g myconfigmap/log4j2-superverbose.xml) storing Log4j2 configuration file. By default the Controller uses its embedded configuration. + Log string `json:"log,omitempty"` + // Deploy timeout for agents, in milliseconds. + AgentDeployTimeout int `json:"agentDeployTimeout,omitempty"` + // If this is set the controller does not start benchmark run right away after hitting + // /benchmark/my-benchmark/start ; instead it responds with status 301 and header Location + // set to concatenation of this string and 'BENCHMARK=my-benchmark&RUN_ID=xxxx'. + // CLI interprets that response as a request to hit CI instance on this URL, assuming that + // CI will trigger a new job that will eventually call /benchmark/my-benchmark/start?runId=xxxx + // with header 'x-trigger-job'. This is useful if the the CI has to synchronize Hyperfoil + // to other benchmarks that don't use this controller instance. + TriggerURL string `json:"triggerUrl,omitempty"` + // Names of config maps and optionally keys (separated by '/') holding hooks that run before the run starts. + PreHooks []string `json:"preHooks,omitempty"` + // Names of config maps and optionally keys (separated by '/') holding hooks that run after the run finishes. + PostHooks []string `json:"postHooks,omitempty"` + // Name of the PVC hyperfoil should mount for its workdir. + PersistentVolumeClaim string `json:"persistentVolumeClaim,omitempty"` + // List of secrets in this namespace; each entry from those secrets will be mapped + // as environment variable, using the key as variable name. + SecretEnvVars []string `json:"secretEnvVars,omitempty"` +} + +// RouteSpec defines the route for external access. +type RouteSpec struct { + // Host for the route leading to Controller REST endpoint. Example: hyperfoil.apps.cloud.example.com + Host string `json:"host,omitempty"` + // Either 'http' (for plain-text routes - not recommended), 'edge', 'reencrypt' or 'passthrough' + Type string `json:"type,omitempty"` + // Optional for edge and reencrypt routes, required for passthrough; Name of the secret hosting `tls.crt`, `tls.key` and optionally `ca.crt` + TLS string `json:"tls,omitempty"` +} + +// AuthSpec defines authentication/authorization settings. +type AuthSpec struct { + // Optional; Name of secret used for basic authentication. Must contain key 'password'. + Secret string `json:"secret,omitempty"` +} + +// HyperfoilStatus defines the observed state of Hyperfoil +type HyperfoilStatus struct { + // "One of: 'Ready', 'Pending' or 'Error'" + Status string `json:"status,omitempty"` + // RFC 3339 date and time of the last update. + LastUpdate metav1.Time `json:"lastUpdate,omitempty"` + // Human readable explanation for the status. + Reason string `json:"reason,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:resource:categories=all;hyperfoil,shortName=hf +//+kubebuilder:subresource:status +//+kubebuilder:printcolumn:name="Version",type=string,JSONPath=`.spec.version` +//+kubebuilder:printcolumn:name="Route",type=string,JSONPath=`.spec.route.host` +//+kubebuilder:printcolumn:name="PVC",type=string,JSONPath=`.spec.persistentVolumeClaim` +//+kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.status` + +// Hyperfoil is the Schema for the hyperfoils API +type Hyperfoil struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec HyperfoilSpec `json:"spec,omitempty"` + Status HyperfoilStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// HyperfoilList contains a list of Hyperfoil +type HyperfoilList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Hyperfoil `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Hyperfoil{}, &HyperfoilList{}) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2/zz_generated.deepcopy.go b/packages/kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2/zz_generated.deepcopy.go new file mode 100644 index 00000000000..23680c575ad --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2/zz_generated.deepcopy.go @@ -0,0 +1,163 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2021. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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 v1alpha2 + +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 *AuthSpec) DeepCopyInto(out *AuthSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthSpec. +func (in *AuthSpec) DeepCopy() *AuthSpec { + if in == nil { + return nil + } + out := new(AuthSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Hyperfoil) DeepCopyInto(out *Hyperfoil) { + *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 Hyperfoil. +func (in *Hyperfoil) DeepCopy() *Hyperfoil { + if in == nil { + return nil + } + out := new(Hyperfoil) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Hyperfoil) 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 *HyperfoilList) DeepCopyInto(out *HyperfoilList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Hyperfoil, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HyperfoilList. +func (in *HyperfoilList) DeepCopy() *HyperfoilList { + if in == nil { + return nil + } + out := new(HyperfoilList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HyperfoilList) 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 *HyperfoilSpec) DeepCopyInto(out *HyperfoilSpec) { + *out = *in + out.Route = in.Route + out.Auth = in.Auth + if in.PreHooks != nil { + in, out := &in.PreHooks, &out.PreHooks + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.PostHooks != nil { + in, out := &in.PostHooks, &out.PostHooks + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.SecretEnvVars != nil { + in, out := &in.SecretEnvVars, &out.SecretEnvVars + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HyperfoilSpec. +func (in *HyperfoilSpec) DeepCopy() *HyperfoilSpec { + if in == nil { + return nil + } + out := new(HyperfoilSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HyperfoilStatus) DeepCopyInto(out *HyperfoilStatus) { + *out = *in + in.LastUpdate.DeepCopyInto(&out.LastUpdate) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HyperfoilStatus. +func (in *HyperfoilStatus) DeepCopy() *HyperfoilStatus { + if in == nil { + return nil + } + out := new(HyperfoilStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteSpec) DeepCopyInto(out *RouteSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteSpec. +func (in *RouteSpec) DeepCopy() *RouteSpec { + if in == nil { + return nil + } + out := new(RouteSpec) + in.DeepCopyInto(out) + return out +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/image.go b/packages/kogito-serverless-operator/bddframework/pkg/api/image.go new file mode 100644 index 00000000000..2ce40a11158 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/image.go @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + +// Image is a definition of a Docker image. +type Image struct { + Domain string `json:"domain,omitempty"` + Name string `json:"name,omitempty"` + Tag string `json:"tag,omitempty"` +} + +// IsEmpty verifies if this Image instance is empty. +func (i *Image) IsEmpty() bool { + return len(i.Domain) == 0 && + len(i.Name) == 0 && + len(i.Tag) == 0 +} + +// String representation of this Image. +func (i *Image) String() string { + if i.IsEmpty() { + return "" + } + return fmt.Sprintf("%s/%s:%s", i.Domain, i.Name, i.Tag) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/kogitoservices_types.go b/packages/kogito-serverless-operator/bddframework/pkg/api/kogitoservices_types.go new file mode 100644 index 00000000000..c6ea42d014f --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/kogitoservices_types.go @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// KogitoServiceConditionType is the type of condition +type KogitoServiceConditionType string + +const ( + // DeployedConditionType - The KogitoService is deployed + DeployedConditionType KogitoServiceConditionType = "Deployed" + // ProvisioningConditionType - The KogitoService is being provisioned + ProvisioningConditionType KogitoServiceConditionType = "Provisioning" + // FailedConditionType - The KogitoService is in a failed state + FailedConditionType KogitoServiceConditionType = "Failed" +) + +// KogitoService defines the interface for any Kogito service that the operator can handle, e.g. Data Index, Jobs Service, Runtimes, etc. +type KogitoService interface { + client.Object + // GetSpec gets the Kogito Service specification structure. + GetSpec() KogitoServiceSpecInterface + // GetStatus gets the Kogito Service Status structure. + GetStatus() KogitoServiceStatusInterface +} + +// KogitoServiceList defines a base interface for Kogito Service list. +type KogitoServiceList interface { + runtime.Object + // GetItems get all items + GetItems() []KogitoService +} + +// KogitoServiceSpecInterface defines the interface for the Kogito service specification, it's the basic structure for any Kogito service. +type KogitoServiceSpecInterface interface { + GetReplicas() *int32 + SetReplicas(replicas int32) + GetEnvs() []corev1.EnvVar + SetEnvs(envs []corev1.EnvVar) + AddEnvironmentVariable(name, value string) + AddEnvironmentVariableFromSecret(variableName, secretName, secretKey string) + GetImage() string + SetImage(image string) + GetResources() corev1.ResourceRequirements + SetResources(resources corev1.ResourceRequirements) + AddResourceRequest(name, value string) + AddResourceLimit(name, value string) + GetDeploymentLabels() map[string]string + SetDeploymentLabels(labels map[string]string) + AddDeploymentLabel(name, value string) + GetServiceLabels() map[string]string + SetServiceLabels(labels map[string]string) + AddServiceLabel(name, value string) + GetRuntime() RuntimeType + IsRouteDisabled() bool + SetDisableRoute(disableRoute bool) + IsInsecureImageRegistry() bool + GetPropertiesConfigMap() string + GetInfra() []string + AddInfra(name string) + GetMonitoring() MonitoringInterface + SetMonitoring(monitoring MonitoringInterface) + GetConfig() map[string]string + GetProbes() KogitoProbeInterface + SetProbes(probes KogitoProbeInterface) + GetTrustStoreSecret() string + SetTrustStoreSecret(trustStore string) +} + +// KogitoServiceStatusInterface defines the basic interface for the Kogito Service status. +type KogitoServiceStatusInterface interface { + GetConditions() *[]metav1.Condition + SetConditions(conditions *[]metav1.Condition) + GetDeploymentConditions() []appsv1.DeploymentCondition + SetDeploymentConditions(deploymentConditions []appsv1.DeploymentCondition) + GetRouteConditions() *[]metav1.Condition + SetRouteConditions(conditions *[]metav1.Condition) + GetImage() string + SetImage(image string) + GetExternalURI() string + SetExternalURI(uri string) + GetCloudEvents() KogitoCloudEventsStatusInterface + SetCloudEvents(cloudEvents KogitoCloudEventsStatusInterface) +} + +// KogitoCloudEventsStatusInterface ... +type KogitoCloudEventsStatusInterface interface { + GetConsumes() []KogitoCloudEventInfoInterface + SetConsumes(consumes []KogitoCloudEventInfoInterface) + GetProduces() []KogitoCloudEventInfoInterface + SetProduces(produces []KogitoCloudEventInfoInterface) +} + +// KogitoCloudEventInfoInterface ... +type KogitoCloudEventInfoInterface interface { + GetType() string + GetSource() string +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/kogitosupportingservice_types.go b/packages/kogito-serverless-operator/bddframework/pkg/api/kogitosupportingservice_types.go new file mode 100644 index 00000000000..6c90fb24e2c --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/kogitosupportingservice_types.go @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/runtime" +) + +// ServiceType define resource type of supporting service +type ServiceType string + +const ( + // DataIndex supporting service resource type + DataIndex ServiceType = "DataIndex" + // Explainability supporting service resource type + Explainability ServiceType = "Explainability" + // JobsService supporting service resource type + JobsService ServiceType = "JobsService" + // MgmtConsole supporting service resource type + MgmtConsole ServiceType = "MgmtConsole" + // TaskConsole supporting service resource type + TaskConsole ServiceType = "TaskConsole" + // TrustyAI supporting service resource type + TrustyAI ServiceType = "TrustyAI" + // TrustyUI supporting service resource type + TrustyUI ServiceType = "TrustyUI" +) + +// KogitoSupportingServiceInterface ... +type KogitoSupportingServiceInterface interface { + KogitoService + // GetSpec gets the Kogito Service specification structure. + GetSupportingServiceSpec() KogitoSupportingServiceSpecInterface + // GetStatus gets the Kogito Service Status structure. + GetSupportingServiceStatus() KogitoSupportingServiceStatusInterface +} + +// KogitoSupportingServiceSpecInterface ... +type KogitoSupportingServiceSpecInterface interface { + KogitoServiceSpecInterface + GetServiceType() ServiceType + SetServiceType(serviceType ServiceType) +} + +// KogitoSupportingServiceStatusInterface ... +type KogitoSupportingServiceStatusInterface interface { + KogitoServiceStatusInterface +} + +// KogitoSupportingServiceListInterface ... +type KogitoSupportingServiceListInterface interface { + runtime.Object + // GetItems gets all items + GetItems() []KogitoSupportingServiceInterface +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/monitoring.go b/packages/kogito-serverless-operator/bddframework/pkg/api/monitoring.go new file mode 100644 index 00000000000..1bb5a091218 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/monitoring.go @@ -0,0 +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. + */ + +package api + +const ( + + // MonitoringDefaultPathQuarkus default path + MonitoringDefaultPathQuarkus = "/q/metrics" + + // MonitoringDefaultPathSpringboot default path + MonitoringDefaultPathSpringboot = "/actuator/prometheus" + + // MonitoringDefaultScheme default scheme + MonitoringDefaultScheme = "http" +) + +// MonitoringInterface ... +type MonitoringInterface interface { + GetScheme() string + SetScheme(scheme string) + GetPath() string + SetPath(path string) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/probe.go b/packages/kogito-serverless-operator/bddframework/pkg/api/probe.go new file mode 100644 index 00000000000..e6c1141ba81 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/probe.go @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 corev1 "k8s.io/api/core/v1" + +// KogitoProbeInterface ... +type KogitoProbeInterface interface { + GetLivenessProbe() corev1.Probe + SetLivenessProbe(livenessProbe corev1.Probe) + GetReadinessProbe() corev1.Probe + SetReadinessProbe(readinessProbe corev1.Probe) + GetStartupProbe() corev1.Probe + SetStartupProbe(startupProbe corev1.Probe) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/runtimetype.go b/packages/kogito-serverless-operator/bddframework/pkg/api/runtimetype.go new file mode 100644 index 00000000000..b47223ad053 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/runtimetype.go @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 + +// RuntimeType - type of condition. +type RuntimeType string + +const ( + // QuarkusRuntimeType Runtime for quarkus application + QuarkusRuntimeType RuntimeType = "quarkus" + // SpringBootRuntimeType Runtime for springboot application + SpringBootRuntimeType RuntimeType = "springboot" +) diff --git a/packages/kogito-serverless-operator/bddframework/pkg/api/webhook.go b/packages/kogito-serverless-operator/bddframework/pkg/api/webhook.go new file mode 100644 index 00000000000..bdb2889641b --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/api/webhook.go @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 + +// WebHookType literal type to distinguish between different types of webHooks. +type WebHookType string + +const ( + // GitHubWebHook GitHub webHook. + GitHubWebHook WebHookType = "GitHub" + // GenericWebHook Generic webHook. + GenericWebHook WebHookType = "Generic" +) + +// WebHookSecretInterface ... +type WebHookSecretInterface interface { + GetType() WebHookType + GetSecret() string +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/config/config.go b/packages/kogito-serverless-operator/bddframework/pkg/config/config.go new file mode 100644 index 00000000000..f2de702cb22 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/config/config.go @@ -0,0 +1,513 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package config + +import ( + "fmt" + "path/filepath" + + flag "github.com/spf13/pflag" +) + +// TestConfig contains the information about the tests environment +type TestConfig struct { + // tests configuration + smoke bool + performance bool + loadFactor int + ciName string + crDeploymentOnly bool + containerEngine string + domainSuffix string + imageCacheMode string + httpRetryNumber int + olmNamespace string + + // operator information + operatorImageTag string + operatorInstallationSource string + operatorCatalogImage string + useProductOperator bool + + // profiling + operatorProfiling bool + operatorProfilingDataAccessYamlURI string + operatorProfilingOutputFileURI string + + // files/binaries + operatorYamlURI string + rhpamOperatorYamlURI string + cliPath string + + // runtime + servicesImageTags imageTags + servicesImageRegistry string + servicesImageNameSuffix string + servicesImageVersion string + runtimeApplicationImageRegistry string + runtimeApplicationImageNamePrefix string + runtimeApplicationImageNameSuffix string + runtimeApplicationImageVersion string + + // build + customMavenRepoURL string + customMavenRepoReplaceDefault bool + mavenMirrorURL string + quarkusPlatformMavenMirrorURL string + mavenIgnoreSelfSignedCertificate bool + buildBuilderImageTag string + buildRuntimeJVMImageTag string + buildRuntimeNativeImageTag string + disableMavenNativeBuildInContainer bool + nativeBuilderImage string + + // examples repository + examplesRepositoryURI string + examplesRepositoryRef string + examplesRepositoryIgnoreSSL bool + + // Infinispan + infinispanInstallationSource string + infinispanStorageClass string + + // Hyperfoil + hyperfoilOutputDirectory string + hyperfoilControllerImageVersion string + + // dev options + showScenarios bool + showSteps bool + dryRun bool + keepNamespace bool + namespaceName string + localCluster bool + localTests bool +} + +const ( + defaultOperatorYamlURI = "../operator.yaml" + defaultRhpamOperatorYamlURI = "../rhpam-operator.yaml" + defaultCliPath = "../build/_output/bin/kogito" + + defaultOperatorProfilingDataAccessYamlURI = "../profiling/kogito-operator-profiling-data-access.yaml" + defaultOperatorProfilingOutputFileURI = "./bdd-cover.out" + + defaultKogitoExamplesURI = "https://github.com/kiegroup/kogito-examples" + + defaultLoadFactor = 1 + defaultHTTPRetryNumber = 3 + + defaultContainerEngine = "podman" + + installationSourceOlm = "olm" + installationSourceYaml = "yaml" +) + +var ( + env = TestConfig{} +) + +// BindFlags binds BDD tests env flags to given flag set +func BindFlags(set *flag.FlagSet) { + prefix := "tests." + developmentOptionsPrefix := prefix + "dev." + + // tests configuration + set.BoolVar(&env.smoke, prefix+"smoke", false, "Launch only smoke tests") + set.BoolVar(&env.performance, prefix+"performance", false, "Launch performance tests") + set.IntVar(&env.loadFactor, prefix+"load_factor", defaultLoadFactor, "Set the tests load factor. Useful for the tests to take into account that the cluster can be overloaded, for example for the calculation of timeouts. Default value is 1.") + set.BoolVar(&env.localTests, prefix+"local_execution", false, "If tests are launch on local machine using either a local or remote cluster") + set.StringVar(&env.ciName, prefix+"ci", "", "If tests are launch on ci machine, give the CI name") + set.BoolVar(&env.crDeploymentOnly, prefix+"cr_deployment_only", false, "Use this option if you have no CLI to test against. It will use only direct CR deployments.") + set.StringVar(&env.containerEngine, prefix+"container_engine", defaultContainerEngine, "Engine used to interact with images and local containers.") + set.StringVar(&env.domainSuffix, prefix+"domain_suffix", "", "Set the domain suffix for exposed services. Ignored when running tests on Openshift.") + set.StringVar(&env.imageCacheMode, prefix+"image_cache_mode", "if-available", "Use this option to specify whether you want to use image cache for runtime images. Available options are 'always', 'never' or 'if-available'(default).") + set.IntVar(&env.httpRetryNumber, prefix+"http_retry_nb", defaultHTTPRetryNumber, "Set the retry number for all HTTP calls in case it fails (and response code != 500). Default value is 3.") + set.StringVar(&env.olmNamespace, prefix+"olm_namespace", "", "Set the namespace which is used for cluster scope operators. Default is 'openshift-operators'.") + + // operator information + set.StringVar(&env.operatorImageTag, prefix+"operator_image_tag", "", "Operator image full tag") + set.StringVar(&env.operatorInstallationSource, prefix+"operator_installation_source", installationSourceYaml, "Operator installation source") + set.StringVar(&env.operatorCatalogImage, prefix+"operator_catalog_image", "", "Operator catalog image") + set.BoolVar(&env.useProductOperator, prefix+"use_product_operator", false, "Set to true to deploy RHPAM Kogito operator, false for using Kogito operator. Default is false.") + + // operator profiling + set.BoolVar(&env.operatorProfiling, prefix+"operator_profiling_enabled", false, "Enable the profiling of the operator. If enabled, operator will be automatically deployed with yaml files.") + set.StringVar(&env.operatorProfilingDataAccessYamlURI, prefix+"operator_profiling_data_access_yaml_uri", defaultOperatorProfilingDataAccessYamlURI, "Url or Path to kogito-operator-profiling-data-access.yaml file.") + set.StringVar(&env.operatorProfilingOutputFileURI, prefix+"operator_profiling_output_file_uri", defaultOperatorProfilingOutputFileURI, "Url or Path where to store the profiling outputs.") + + // files/binaries + set.StringVar(&env.operatorYamlURI, prefix+"operator_yaml_uri", defaultOperatorYamlURI, "Url or Path to kogito-operator.yaml file") + set.StringVar(&env.rhpamOperatorYamlURI, prefix+"rhpam_operator_yaml_uri", defaultRhpamOperatorYamlURI, "Url or Path to kogito-operator.yaml file") + set.StringVar(&env.cliPath, prefix+"cli_path", defaultCliPath, "Path to built CLI to test") + + // runtime + addAllPersistenceTypesImageTagFlags(set, &env.servicesImageTags, prefix+"services") + set.StringVar(&env.servicesImageRegistry, prefix+"services_image_registry", "", "Set the global services image registry") + set.StringVar(&env.servicesImageNameSuffix, prefix+"services_image_name_suffix", "", "Set the global services image name suffix") + set.StringVar(&env.servicesImageVersion, prefix+"services_image_version", "", "Set the global services image version") + set.StringVar(&env.runtimeApplicationImageRegistry, prefix+"runtime_application_image_registry", "", "Set the runtime application (built Kogito application image) image registry") + set.StringVar(&env.runtimeApplicationImageNamePrefix, prefix+"runtime_application_image_name_prefix", "", "Set the runtime application (built Kogito application image) image name prefix") + set.StringVar(&env.runtimeApplicationImageNameSuffix, prefix+"runtime_application_image_name_suffix", "", "Set the runtime application (built Kogito application image) image name suffix") + set.StringVar(&env.runtimeApplicationImageVersion, prefix+"runtime_application_image_version", "", "Set the runtime application (built Kogito application image) image version") + + // build + set.StringVar(&env.customMavenRepoURL, prefix+"custom_maven_repo_url", "", "Set a custom Maven repository url for S2I builds, in case your artifacts are in a specific repository. See https://github.com/kiegroup/kogito-images/README.md for more information") + set.BoolVar(&env.customMavenRepoReplaceDefault, prefix+"custom_maven_repo_replace_default", false, "If you specified the option 'tests.custom_maven_repo_url' and you want that one to replace the main Apache repository (useful with snapshots).") + set.StringVar(&env.mavenMirrorURL, prefix+"maven_mirror_url", "", "Maven mirror url to be used when building app in the tests") + set.StringVar(&env.quarkusPlatformMavenMirrorURL, prefix+"quarkusPlatformMavenMirrorURL", "", "Maven mirror url to be used when building app from source files with Quarkus, using the quarkus maven plugin.") + set.BoolVar(&env.mavenIgnoreSelfSignedCertificate, prefix+"maven_ignore_self_signed_certificate", false, "Set to true if maven build need to ignore self-signed certificate. This could happen when using internal maven mirror url.") + set.StringVar(&env.buildBuilderImageTag, prefix+"build_builder_image_tag", "", "Set the S2I build image full tag") + set.StringVar(&env.buildRuntimeJVMImageTag, prefix+"build_runtime_jvm_image_tag", "", "Set the Runtime build image full tag") + set.StringVar(&env.buildRuntimeNativeImageTag, prefix+"build_runtime_native_image_tag", "", "Set the Runtime build image full tag") + set.BoolVar(&env.disableMavenNativeBuildInContainer, prefix+"disable_maven_native_build_container", false, "By default, Maven native builds are done in container (via container engine). Possibility to disable it.") + set.StringVar(&env.nativeBuilderImage, prefix+"native_builder_image", "", "Force the native builder image.") + + // examples repository + set.StringVar(&env.examplesRepositoryURI, prefix+"examples_uri", defaultKogitoExamplesURI, "Set the URI for the kogito-examples repository") + set.StringVar(&env.examplesRepositoryRef, prefix+"examples_ref", "", "Set the branch for the kogito-examples repository") + set.BoolVar(&env.examplesRepositoryIgnoreSSL, prefix+"examples_ignore_ssl", false, "Set to true to ignore SSL check when checking out examples repository") + + // Infinispan + set.StringVar(&env.infinispanInstallationSource, prefix+"infinispan_installation_source", installationSourceOlm, "Infinispan operator installation source") + set.StringVar(&env.infinispanStorageClass, prefix+"infinispan_storage_class", "", "Defines storage class for Infinispan PVC to be used.") + + // Hyperfoil + set.StringVar(&env.hyperfoilOutputDirectory, prefix+"hyperfoil_output_directory", "..", "Defines output directory to store Hyperfoil run statistics. Default is Kogito operator base folder.") + set.StringVar(&env.hyperfoilControllerImageVersion, prefix+"hyperfoil_controller_image_version", "", "Set the Hyperfoil controller image version") + + // dev options + set.BoolVar(&env.showScenarios, prefix+"show_scenarios", false, "Show all scenarios which will be executed.") + set.BoolVar(&env.showSteps, prefix+"show_steps", false, "Show all scenarios and their steps which will be executed.") + set.BoolVar(&env.dryRun, prefix+"dry_run", false, "Dry Run the tests.") + set.BoolVar(&env.keepNamespace, prefix+"keep_namespace", false, "Do not delete namespace(s) after scenario run (WARNING: can be resources consuming ...)") + set.StringVar(&env.namespaceName, developmentOptionsPrefix+"namespace_name", "", "Use the specified namespace for scenarios, don't generate random namespace.") + set.BoolVar(&env.localCluster, developmentOptionsPrefix+"local_cluster", false, "If tests are launch using a local cluster") +} + +func addAllPersistenceTypesImageTagFlags(set *flag.FlagSet, imageTags *imageTags, keyPrefix string) { + for imageType, persistenceTypes := range imageTypePersistenceMapping { + for _, persistenceType := range persistenceTypes { + addPersistenceTypeImageTagFlags(set, imageTags, imageType, persistenceType, keyPrefix) + } + } +} + +func addPersistenceTypeImageTagFlags(set *flag.FlagSet, imageTags *imageTags, imageType ImageType, persistenceType ImagePersistenceType, keyPrefix string) { + key := fmt.Sprintf("%s_%s", keyPrefix, imageType) + description := fmt.Sprintf("Set the %s image tag", imageType) + if len(persistenceType) > 0 { + key = fmt.Sprintf("%s_%s", key, persistenceType) + description = fmt.Sprintf("%s with %s persistence type. This overrides the `services_image_*` parameters.", description, persistenceType) + } + key = fmt.Sprintf("%s_image_tag", key) + + set.StringVar(imageTags.GetImageTagPointerFromPersistenceType(imageType, persistenceType), key, "", description) +} + +// tests configuration + +// IsSmokeTests return whether smoke tests should be executed +func IsSmokeTests() bool { + return env.smoke +} + +// IsPerformanceTests return whether performance tests should be executed +func IsPerformanceTests() bool { + return env.performance +} + +// GetLoadFactor return the load factor of the cluster +func GetLoadFactor() int { + return env.loadFactor +} + +// IsLocalTests return whether tests are executed in local +func IsLocalTests() bool { + return env.localTests +} + +// GetCiName return the CI name that executes the tests, if any +func GetCiName() string { + return env.ciName +} + +// IsCrDeploymentOnly returns whether the deployment should be done only with CR +func IsCrDeploymentOnly() bool { + return env.crDeploymentOnly +} + +// GetContainerEngine returns engine used to interact with images and local containers +func GetContainerEngine() string { + return env.containerEngine +} + +// GetDomainSuffix returns the domain suffix for exposed services +func GetDomainSuffix() string { + return env.domainSuffix +} + +// GetImageCacheMode returns image cache mode +func GetImageCacheMode() ImageCacheMode { + return ImageCacheMode(env.imageCacheMode) +} + +// GetHTTPRetryNumber return the number of retries to be applied for http calls +func GetHTTPRetryNumber() int { + return env.httpRetryNumber +} + +// GetOlmNamespace returns namespace which is used for cluster scope operators +func GetOlmNamespace() string { + return env.olmNamespace +} + +// operator information + +// GetOperatorImageTag return the image tag for the operator +func GetOperatorImageTag() string { + return env.operatorImageTag +} + +// IsOperatorInstalledByOlm return true if Kogito operator is installed using OLM +func IsOperatorInstalledByOlm() bool { + return env.operatorInstallationSource == installationSourceOlm +} + +// IsOperatorInstalledByYaml return true if Kogito operator is installed using YAML files +func IsOperatorInstalledByYaml() bool { + return env.operatorInstallationSource == installationSourceYaml +} + +// GetOperatorCatalogImage return the image tag for the Kogito operator catalog +func GetOperatorCatalogImage() string { + return env.operatorCatalogImage +} + +// UseProductOperator return true if RHPAM Kogito operator should be used, false for Kogito operator +func UseProductOperator() bool { + return env.useProductOperator +} + +// operator profiling + +// IsOperatorProfiling returns whether the operator profiling is activated +func IsOperatorProfiling() bool { + return env.operatorProfiling +} + +// GetOperatorProfilingDataAccessYamlURI return the uri for kogito-operator-profiling-data-access.yaml file +func GetOperatorProfilingDataAccessYamlURI() string { + return env.operatorProfilingDataAccessYamlURI +} + +// GetOperatorProfilingOutputFileURI return the uri for the profiling data output file +func GetOperatorProfilingOutputFileURI() string { + return env.operatorProfilingOutputFileURI +} + +// files/binaries + +// GetOperatorYamlURI return the uri for kogito-operator.yaml file +func GetOperatorYamlURI() string { + return env.operatorYamlURI +} + +// GetRhpamOperatorYamlURI return the uri for rhpam-kogito-operator.yaml file +func GetRhpamOperatorYamlURI() string { + return env.rhpamOperatorYamlURI +} + +// GetOperatorCliPath return the path to the kogito CLI binary +func GetOperatorCliPath() (string, error) { + return filepath.Abs(env.cliPath) +} + +// runtime + +// GetServiceImageTag returns the image tag based on the image type and the persistence type +func GetServiceImageTag(ImageType ImageType, persistenceType ImagePersistenceType) string { + return *env.servicesImageTags.GetImageTagPointerFromPersistenceType(ImageType, persistenceType) +} + +// GetServicesImageRegistry return the registry for the services images +func GetServicesImageRegistry() string { + return env.servicesImageRegistry +} + +// GetServicesImageNameSuffix return the name suffix for the services images +func GetServicesImageNameSuffix() string { + return env.servicesImageNameSuffix +} + +// GetServicesImageVersion return the version for the services images +func GetServicesImageVersion() string { + return env.servicesImageVersion +} + +// GetRuntimeApplicationImageRegistry return the registry for the runtime application images +func GetRuntimeApplicationImageRegistry() string { + return env.runtimeApplicationImageRegistry +} + +// GetRuntimeApplicationImageNamePrefix return the name prefix for runtime application images +func GetRuntimeApplicationImageNamePrefix() string { + return env.runtimeApplicationImageNamePrefix +} + +// GetRuntimeApplicationImageNameSuffix return the name suffix for runtime application images +func GetRuntimeApplicationImageNameSuffix() string { + return env.runtimeApplicationImageNameSuffix +} + +// GetRuntimeApplicationImageVersion return the version for runtime application images +func GetRuntimeApplicationImageVersion() string { + return env.runtimeApplicationImageVersion +} + +// build + +// GetCustomMavenRepoURL return the custom maven repository url used by S2I builds +func GetCustomMavenRepoURL() string { + return env.customMavenRepoURL +} + +// IsCustomMavenRepoReplaceDefault return whether custom maven repo should replace the default JBoss repository +func IsCustomMavenRepoReplaceDefault() bool { + return env.customMavenRepoReplaceDefault +} + +// GetMavenMirrorURL return the maven mirror url used for building applications +func GetMavenMirrorURL() string { + return env.mavenMirrorURL +} + +// GetQuarkusPlatformMavenMirrorURL return the maven mirror url used for building applications from assets with quarkus platform +func GetQuarkusPlatformMavenMirrorURL() string { + return env.quarkusPlatformMavenMirrorURL +} + +// IsMavenIgnoreSelfSignedCertificate return whether self-signed certficate should be ignored +func IsMavenIgnoreSelfSignedCertificate() bool { + return env.mavenIgnoreSelfSignedCertificate +} + +// GetBuildBuilderImageStreamTag return the tag for the builder image +func GetBuildBuilderImageStreamTag() string { + return env.buildBuilderImageTag +} + +// GetBuildRuntimeJVMImageStreamTag return the tag for the runtime JVM image +func GetBuildRuntimeJVMImageStreamTag() string { + return env.buildRuntimeJVMImageTag +} + +// GetBuildRuntimeNativeImageStreamTag return the tag for the runtime native image +func GetBuildRuntimeNativeImageStreamTag() string { + return env.buildRuntimeNativeImageTag +} + +// IsDisableMavenNativeBuildInContainer return whether Maven native build in container should be disabled +func IsDisableMavenNativeBuildInContainer() bool { + return env.disableMavenNativeBuildInContainer +} + +// GetNativeBuilderImage return the native builder image for Maven native builds +func GetNativeBuilderImage() string { + return env.nativeBuilderImage +} + +// examples repository + +// GetExamplesRepositoryURI return the uri for the examples repository +func GetExamplesRepositoryURI() string { + return env.examplesRepositoryURI +} + +// GetExamplesRepositoryRef return the branch for the examples repository +func GetExamplesRepositoryRef() string { + return env.examplesRepositoryRef +} + +// IsExamplesRepositoryIgnoreSSL return whether SSL should be ignored on Git checkout +func IsExamplesRepositoryIgnoreSSL() bool { + return env.examplesRepositoryIgnoreSSL +} + +// Infinispan + +// IsInfinispanInstalledByOlm return true if Infinispan operator is installed using OLM +func IsInfinispanInstalledByOlm() bool { + return env.infinispanInstallationSource == installationSourceOlm +} + +// IsInfinispanInstalledByYaml return true if Infinispan operator is installed using YAML files +func IsInfinispanInstalledByYaml() bool { + return env.infinispanInstallationSource == installationSourceYaml +} + +// GetInfinispanStorageClass return the Infinispan storage class +func GetInfinispanStorageClass() string { + return env.infinispanStorageClass +} + +// Hyperfoil + +// GetHyperfoilOutputDirectory returns directory to store Hyperfoil run results +func GetHyperfoilOutputDirectory() string { + return env.hyperfoilOutputDirectory +} + +// GetHyperfoilControllerImageVersion returns the Hyperfoil controller image version +func GetHyperfoilControllerImageVersion() string { + return env.hyperfoilControllerImageVersion +} + +// dev options + +// IsShowScenarios return whether we should display scenarios +func IsShowScenarios() bool { + return env.showScenarios +} + +// IsShowSteps return whether we should display scenarios's steps +func IsShowSteps() bool { + return env.showSteps +} + +// IsDryRun return whether we should do a dry run +func IsDryRun() bool { + return env.dryRun +} + +// IsKeepNamespace return whether we should keep namespace after scenario run +func IsKeepNamespace() bool { + return env.keepNamespace +} + +// GetNamespaceName return namespace name if it was defined +func GetNamespaceName() string { + return env.namespaceName +} + +// IsLocalCluster return whether tests are executed using a local cluster +func IsLocalCluster() bool { + return env.localCluster +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/config/image_cache_mode.go b/packages/kogito-serverless-operator/bddframework/pkg/config/image_cache_mode.go new file mode 100644 index 00000000000..167bbd25354 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/config/image_cache_mode.go @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package config + +// ImageCacheMode defines whether image cache should be used for runtime image or images should be rather built manually. +type ImageCacheMode string + +var ( + // UseImageCacheAlways Always use image cache + UseImageCacheAlways = ImageCacheMode("always") + // UseImageCacheNever don't use image cache, build always manually + UseImageCacheNever = ImageCacheMode("never") + // UseImageCacheIfAvailable use image cache if image is available there, otherwise build locally + UseImageCacheIfAvailable = ImageCacheMode("if-available") +) + +// IsValid returns true if image cache mode value is one of valid expected modes +func (imageCacheMode ImageCacheMode) IsValid() bool { + switch imageCacheMode { + case UseImageCacheAlways, UseImageCacheNever, UseImageCacheIfAvailable: + return true + } + return false +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/config/image_tags.go b/packages/kogito-serverless-operator/bddframework/pkg/config/image_tags.go new file mode 100644 index 00000000000..e69233b82a3 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/config/image_tags.go @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package config + +// ImageType represents the image base image name +type ImageType string + +const ( + // DataIndexImageType ... + DataIndexImageType ImageType = "data-index" + // ExplainabilityImageType ... + ExplainabilityImageType ImageType = "explainability" + // JobServiceImageType ... + JobServiceImageType ImageType = "jobs-service" + // ManagementConsoleImageType ... + ManagementConsoleImageType ImageType = "mgmt-console" + // TaskConsoleImageType ... + TaskConsoleImageType ImageType = "task-console" + // TrustyImageType ... + TrustyImageType ImageType = "trusty" + // TrustyUIImageType ... + TrustyUIImageType ImageType = "trusty-ui" +) + +// ImagePersistenceType represents the persistence type for the base image +type ImagePersistenceType string + +const ( + // EphemeralPersistenceType ... + EphemeralPersistenceType ImagePersistenceType = "ephemeral" + // InfinispanPersistenceType ... + InfinispanPersistenceType ImagePersistenceType = "infinispan" + // MongoDBPersistenceType ... + MongoDBPersistenceType ImagePersistenceType = "mongodb" + // PosgresqlPersistenceType ... + PosgresqlPersistenceType ImagePersistenceType = "posgresql" + // RedisPersistenceType ... + RedisPersistenceType ImagePersistenceType = "redis" +) + +var ( + imageTypePersistenceMapping map[ImageType][]ImagePersistenceType = map[ImageType][]ImagePersistenceType{ + DataIndexImageType: {EphemeralPersistenceType, InfinispanPersistenceType, MongoDBPersistenceType, PosgresqlPersistenceType}, + ExplainabilityImageType: {EphemeralPersistenceType}, + JobServiceImageType: {EphemeralPersistenceType, InfinispanPersistenceType, MongoDBPersistenceType, PosgresqlPersistenceType}, + ManagementConsoleImageType: {EphemeralPersistenceType}, + TaskConsoleImageType: {EphemeralPersistenceType}, + TrustyImageType: {InfinispanPersistenceType, RedisPersistenceType}, + TrustyUIImageType: {EphemeralPersistenceType}, + } +) + +type imageTags struct { + tags map[ImageType]map[ImagePersistenceType]*string +} + +func (imgTags *imageTags) GetImageTagPointerFromPersistenceType(imageType ImageType, persistenceType ImagePersistenceType) *string { + if len(imgTags.tags) <= 0 { + imgTags.tags = make(map[ImageType]map[ImagePersistenceType]*string) + } + if len(imgTags.tags[imageType]) <= 0 { + imgTags.tags[imageType] = make(map[ImagePersistenceType]*string) + } + if imgTags.tags[imageType][persistenceType] == nil { + tag := "" + imgTags.tags[imageType][persistenceType] = &tag + } + + return imgTags.tags[imageType][persistenceType] +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/check_setup.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/check_setup.go new file mode 100644 index 00000000000..e03f86d0021 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/check_setup.go @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" +) + +var verifications = []func() error{ + checkKubernetesAndDomainSuffix, + checkImageCacheMode, +} + +// CheckSetup verifies the configuration is correct +func CheckSetup() error { + for _, verification := range verifications { + if err := verification(); err != nil { + return err + } + } + + return nil +} + +func checkKubernetesAndDomainSuffix() error { + if !IsOpenshift() && !config.IsLocalCluster() && len(config.GetDomainSuffix()) <= 0 { + return fmt.Errorf("The 'domain_suffix' argument is required using Kubernetes cluster") + } + + return nil +} + +func checkImageCacheMode() error { + imageCacheMode := config.GetImageCacheMode() + if imageCacheMode.IsValid() { + return nil + } + return (fmt.Errorf("Invalid image cache mode: %s", imageCacheMode)) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/cli.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/cli.go new file mode 100644 index 00000000000..6667f175978 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/cli.go @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "os" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" +) + +// CheckCliBinaryExist checks if the CLI binary does exist +func CheckCliBinaryExist() (bool, error) { + path, err := config.GetOperatorCliPath() + if err != nil { + return false, err + } + + if _, err := os.Stat(path); err != nil { + if os.IsNotExist(err) { + return false, nil + } + return false, err + } + return true, nil +} + +// ExecuteCliCommand executes a kogito cli command for a given namespace +func ExecuteCliCommand(namespace string, args ...string) (string, error) { + path, err := config.GetOperatorCliPath() + if err != nil { + return "", err + } + + return CreateCommand(path, args...).WithLoggerContext(namespace).Execute() +} + +// ExecuteCliCommandInNamespace executes a kogito cli command in a specific namespace +func ExecuteCliCommandInNamespace(namespace string, args ...string) (string, error) { + args = append(args, "-p", namespace) + return ExecuteCliCommand(namespace, args...) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/client/client.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/client.go new file mode 100644 index 00000000000..b1f75aa8469 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/client.go @@ -0,0 +1,246 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "fmt" + "os" + "path/filepath" + "strings" + + rbac "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/runtime" + controllerruntime "sigs.k8s.io/controller-runtime" + logger "sigs.k8s.io/controller-runtime/pkg/log" + + frameworklogger "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/logger" + + appsv1 "github.com/openshift/client-go/apps/clientset/versioned/typed/apps/v1" + corev1 "k8s.io/api/core/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + apimeta "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/discovery" + "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "sigs.k8s.io/controller-runtime/pkg/client" + controllercliconfig "sigs.k8s.io/controller-runtime/pkg/client/config" + + buildv1 "github.com/openshift/client-go/build/clientset/versioned/typed/build/v1" + imagev1 "github.com/openshift/client-go/image/clientset/versioned/typed/image/v1" +) + +var ( + log = frameworklogger.Logger{Logger: logger.Log.WithName("client_api")} +) + +const ( + // OpenShiftGroupName name included in OpenShift APIs + OpenShiftGroupName = "openshift.io" +) + +// Client wraps clients functions from controller-runtime, Kube and OpenShift cli for generic API calls to the cluster +type Client struct { + // ControlCli is a reference for the controller-runtime client, normally built by a Manager inside the controller context. + ControlCli client.Client + BuildCli buildv1.BuildV1Interface + ImageCli imagev1.ImageV1Interface + Discovery discovery.DiscoveryInterface + DeploymentCli appsv1.AppsV1Interface + KubernetesExtensionCli kubernetes.Interface +} + +// NewForConsole will create a brand new client using the local machine +func NewForConsole(scheme *runtime.Scheme) *Client { + client, err := NewClientBuilder(scheme).WithBuildClient().WithDiscoveryClient().Build() + if err != nil { + panic(err) + } + return client +} + +// NewForController creates a new client based on the rest config and the controller client created by Operator SDK +// Panic if something goes wrong +func NewForController(manager controllerruntime.Manager) *Client { + newClient, err := NewClientBuilder(manager.GetScheme()). + WithAllClients(). + UseConfig(manager.GetConfig()). + UseControllerClient(manager.GetClient()). + Build() + if err != nil { + panic(err) + } + return newClient +} + +// IsOpenshift detects if the application is running on OpenShift or not +func (c *Client) IsOpenshift() bool { + return c.HasServerGroup(OpenShiftGroupName) +} + +// HasServerGroup detects if the given api group is supported by the server +func (c *Client) HasServerGroup(groupName string) bool { + if c.Discovery != nil { + groups, err := c.Discovery.ServerGroups() + if err != nil { + log.Warn("Impossible to get server groups using discovery API", "error", err) + return false + } + for _, group := range groups.Groups { + if strings.Contains(group.Name, groupName) { + return true + } + } + return false + } + log.Warn("Tried to discover the platform, but no discovery API is available") + return false +} + +func newKubeClient(config *restclient.Config, scheme *runtime.Scheme, useDynamicRestMapper bool) (client.Client, error) { + log.Debug("Creating a new core client for kube connection") + var options client.Options + if useDynamicRestMapper { + options = newControllerCliOptionsWithDynamicMapper(scheme) + } else { + options = newControllerCliOptions(scheme) + } + controlCli, err := client.New(config, options) + if err != nil { + return nil, err + } + return controlCli, nil +} + +func buildKubeConnectionConfig() (*restclient.Config, error) { + return controllercliconfig.GetConfig() +} + +// GetKubeConfigFile gets the .kubeconfig file. +// Never returns an empty string, fallback to default path if not present in the known locations +func GetKubeConfigFile() string { + filename := clientcmd.NewDefaultPathOptions().GetDefaultFilename() + // make sure the path to the file exists + if _, err := os.Stat(filename); os.IsNotExist(err) { + dirName := filepath.Dir(filename) + if err := os.MkdirAll(dirName, os.ModePerm); err != nil { + panic(fmt.Errorf("Error while trying to create kube config directories %s: %s ", filename, err)) + } + } else if err != nil { + panic(fmt.Errorf("Error while trying to access the kube config file %s: %s ", filename, err)) + } + if file, err := os.OpenFile(filename, os.O_RDONLY|os.O_CREATE, 0600); err != nil { + panic(fmt.Errorf("Error while trying to access the kube config file %s: %s ", filename, err)) + } else { + defer func() { + if file != nil { + if err := file.Close(); err != nil { + panic(fmt.Errorf("Error closing kube config file %s: %s ", filename, err)) + } + } + }() + if fileInfo, err := file.Stat(); err != nil { + panic(fmt.Errorf("Error while trying to access the kube config file %s: %s ", filename, err)) + } else if fileInfo.Size() == 0 { + log.Warn("Kubernetes local configuration is empty.", "filename", filename) + log.Warn("Make sure to login to your cluster with oc/kubectl before using this tool") + } + } + + return filename +} + +// restScope implementation +type restScope struct { + name apimeta.RESTScopeName +} + +func (r *restScope) Name() apimeta.RESTScopeName { + return r.name +} + +// newControllerCliOptions creates the mapper and schema options for the inner fallback cli. If set to defaults, the Controller Cli will try +// to discover the mapper by itself by querying the API, which can take too much time. Here we're setting this mapper manually. +// So it's need to keep adding them or find some kind of auto register in the kube api/apimachinery +func newControllerCliOptions(scheme *runtime.Scheme) client.Options { + options := client.Options{} + gvks, err := getGVKsFromAddToScheme(scheme) + if err != nil { + log.Error(err, "Error while creating SchemeBuilder for Kubernetes client") + panic(err) + } + mapper := apimeta.NewDefaultRESTMapper([]schema.GroupVersion{}) + for _, gvk := range gvks { + // namespaced resources + if (gvk.GroupVersion() == corev1.SchemeGroupVersion && gvk.Kind == "Namespace") || + (gvk.GroupVersion() == apiextensionsv1.SchemeGroupVersion && gvk.Kind == "CustomResourceDefinition") || + (gvk.GroupVersion() == rbac.SchemeGroupVersion && gvk.Kind == "ClusterRole") || + (gvk.GroupVersion() == rbac.SchemeGroupVersion && gvk.Kind == "ClusterRoleBinding") { + mapper.Add(gvk, &restScope{name: apimeta.RESTScopeNameRoot}) + } else { // everything else + mapper.Add(gvk, &restScope{name: apimeta.RESTScopeNameNamespace}) + } + } + options.Scheme = scheme + options.Mapper = mapper + return options +} + +func newControllerCliOptionsWithDynamicMapper(scheme *runtime.Scheme) client.Options { + return client.Options{ + Scheme: scheme, + } +} + +// getGVKsFromAddToScheme takes in the runtime scheme and filters out all generic apimachinery meta types. +// It returns just the GVK specific to this scheme. +func getGVKsFromAddToScheme(s *runtime.Scheme) ([]schema.GroupVersionKind, error) { + schemeAllKnownTypes := s.AllKnownTypes() + var ownGVKs []schema.GroupVersionKind + for gvk := range schemeAllKnownTypes { + if !isKubeMetaKind(gvk.Kind) { + ownGVKs = append(ownGVKs, gvk) + } + } + + return ownGVKs, nil +} + +func isKubeMetaKind(kind string) bool { + if strings.HasSuffix(kind, "List") || + kind == "PatchOptions" || + kind == "GetOptions" || + kind == "DeleteOptions" || + kind == "ExportOptions" || + kind == "APIVersions" || + kind == "APIGroupList" || + kind == "APIResourceList" || + kind == "UpdateOptions" || + kind == "CreateOptions" || + kind == "Status" || + kind == "WatchEvent" || + kind == "ListOptions" || + kind == "APIGroup" { + return true + } + + return false +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/client/client_builder.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/client_builder.go new file mode 100644 index 00000000000..413e46bfcb1 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/client_builder.go @@ -0,0 +1,188 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "fmt" + + "k8s.io/apimachinery/pkg/runtime" + + appsv1 "github.com/openshift/client-go/apps/clientset/versioned/typed/apps/v1" + buildv1 "github.com/openshift/client-go/build/clientset/versioned/typed/build/v1" + imagev1 "github.com/openshift/client-go/image/clientset/versioned/typed/image/v1" + "k8s.io/client-go/discovery" + "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// NewClientBuilder creates a builder to setup the client +func NewClientBuilder(scheme *runtime.Scheme) Builder { + return &builderStruct{ + scheme: scheme, + } +} + +// Builder wraps information about what to create for a client before building it +type Builder interface { + // UseConfig sets the restconfig to use for the different CLIs + UseConfig(kubeconfig *restclient.Config) Builder + // UseControllerClient sets a specific controllerclient + UseControllerClient(controllerClient client.Client) Builder + // UseControllerDynamicMapper will set a dynamic mapper to the constructed controller client. Cannot be used with `UseControllerClient` + UseControllerDynamicMapper() Builder + // WithDiscoveryClient tells the builder to create the discovery client + WithDiscoveryClient() Builder + // WithBuildClient tells the builder to create the build client + WithBuildClient() Builder + // WithImageClient tells the builder to create the image client + WithImageClient() Builder + // WithDeploymentClient tells the builder to create the deployment client + WithDeploymentClient() Builder + // WithKubernetesClient tells the builder to create the kubernetes extension client + WithKubernetesExtensionClient() Builder + // WithAllClients is a shortcut to tell the builder to create all clients + WithAllClients() Builder + // Build build the final client structure + Build() (*Client, error) +} + +// Builder wraps information about what to create for a client before building it +type builderStruct struct { + config *restclient.Config + scheme *runtime.Scheme + controllerCli client.Client + + useControllerDynamicMapper bool + + isDiscoveryClient bool + isBuildClient bool + isImageClient bool + isDeploymentClient bool + isKubernetesExtensionClient bool +} + +func (builder *builderStruct) UseConfig(kubeconfig *restclient.Config) Builder { + builder.config = kubeconfig + return builder +} + +func (builder *builderStruct) UseControllerClient(controllerClient client.Client) Builder { + builder.controllerCli = controllerClient + return builder +} + +func (builder *builderStruct) UseControllerDynamicMapper() Builder { + builder.useControllerDynamicMapper = true + return builder +} + +func (builder *builderStruct) WithDiscoveryClient() Builder { + builder.isDiscoveryClient = true + return builder +} + +func (builder *builderStruct) WithBuildClient() Builder { + builder.isBuildClient = true + return builder +} + +func (builder *builderStruct) WithImageClient() Builder { + builder.isImageClient = true + return builder +} + +func (builder *builderStruct) WithDeploymentClient() Builder { + builder.isDeploymentClient = true + return builder +} + +func (builder *builderStruct) WithKubernetesExtensionClient() Builder { + builder.isKubernetesExtensionClient = true + return builder +} + +func (builder *builderStruct) WithAllClients() Builder { + builder.WithBuildClient() + builder.WithDiscoveryClient() + builder.WithImageClient() + builder.WithDeploymentClient() + builder.WithKubernetesExtensionClient() + return builder +} + +func (builder *builderStruct) Build() (*Client, error) { + client := &Client{} + + var err error + + config := builder.config + if config == nil { + config, err = buildKubeConnectionConfig() + if err != nil { + return nil, fmt.Errorf("Impossible to get Kubernetes local configuration: %v", err) + } + } + + client.ControlCli = builder.controllerCli + if client.ControlCli == nil { + + scheme := builder.scheme + if scheme == nil { + return nil, fmt.Errorf("scheme not provided") + } + client.ControlCli, err = newKubeClient(config, scheme, builder.useControllerDynamicMapper) + if err != nil { + return nil, fmt.Errorf("Impossible to create new Kubernetes client: %v", err) + } + } + + if builder.isDiscoveryClient { + client.Discovery, err = discovery.NewDiscoveryClientForConfig(config) + if err != nil { + return nil, fmt.Errorf("Impossible to create new Discovery client: %v", err) + } + } + if builder.isBuildClient { + client.BuildCli, err = buildv1.NewForConfig(config) + if err != nil { + return nil, fmt.Errorf("Error getting build client: %v", err) + } + } + if builder.isImageClient { + client.ImageCli, err = imagev1.NewForConfig(config) + if err != nil { + return nil, fmt.Errorf("Error getting image client: %v", err) + } + } + if builder.isDeploymentClient { + client.DeploymentCli, err = appsv1.NewForConfig(config) + if err != nil { + return nil, fmt.Errorf("Error getting deployment client: %v", err) + } + } + if builder.isKubernetesExtensionClient { + client.KubernetesExtensionCli, err = kubernetes.NewForConfig(config) + if err != nil { + return nil, fmt.Errorf("Error getting kubernetes client: %v", err) + } + } + return client, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/client/doc.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/doc.go new file mode 100644 index 00000000000..9dc3ef84864 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/doc.go @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 encapsulates all calls to Kubernetes/OpenShift API into meaningful functions +package client diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/doc.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/doc.go new file mode 100644 index 00000000000..a611ea3f9c8 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/doc.go @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 encapsulates all calls to the Kubernetes API into meaningful functions for use by the CLI and controllers +package kubernetes diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/event.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/event.go new file mode 100644 index 00000000000..e75251d8b50 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/event.go @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + v1beta1 "k8s.io/api/events/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client" +) + +// EventInterface has functions that interacts with pod object in the Kubernetes cluster +type EventInterface interface { + // Retrieve all events from a namespace + GetEvents(namespace string) (*v1beta1.EventList, error) +} + +type event struct { + client *client.Client +} + +func newEvent(c *client.Client) EventInterface { + return &event{ + client: c, + } +} + +func (event *event) GetEvents(namespace string) (*v1beta1.EventList, error) { + opts := metav1.ListOptions{} + return event.client.KubernetesExtensionCli.EventsV1beta1().Events(namespace).List(context.TODO(), opts) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/kubernetes.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/kubernetes.go new file mode 100644 index 00000000000..3bbc1efd1b2 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/kubernetes.go @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + logger "sigs.k8s.io/controller-runtime/pkg/log" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client" + frameworklogger "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/logger" +) + +var log = frameworklogger.Logger{Logger: logger.Log.WithName("kubernetes_client")} + +// Namespace will fetch the inner Kubernetes API with a default client +func Namespace() NamespaceInterface { + return newNamespace(&client.Client{}) +} + +// NamespaceC will use a defined client to fetch the Kubernetes API +func NamespaceC(c *client.Client) NamespaceInterface { + return newNamespace(c) +} + +// Resource will fetch the inner API for any Kubernetes resource with a default client +func Resource() ResourceInterface { + return newResource(&client.Client{}) +} + +// ResourceC will use a defined client to fetch the Kubernetes API +func ResourceC(c *client.Client) ResourceInterface { + return newResource(c) +} + +// Pod will fetch the inner API for Kubernetes pod resource with a default client +func Pod() PodInterface { + return newPod(&client.Client{}) +} + +// PodC will use a defined client to fetch the Kubernetes pod resources +func PodC(c *client.Client) PodInterface { + return newPod(c) +} + +// Event will fetch the inner API for Kubernetes event resource with a default client +func Event() EventInterface { + return newEvent(&client.Client{}) +} + +// EventC will use a defined client to fetch the Kubernetes event resources +func EventC(c *client.Client) EventInterface { + return newEvent(c) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/namespace.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/namespace.go new file mode 100644 index 00000000000..a08b6fa9067 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/namespace.go @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client" +) + +// NamespaceInterface has functions that interacts with namespace object in the Kubernetes cluster +type NamespaceInterface interface { + Fetch(name string) (*corev1.Namespace, error) + Create(name string) (*corev1.Namespace, error) + CreateIfNotExists(name string) (*corev1.Namespace, error) +} + +type namespace struct { + client *client.Client +} + +func newNamespace(c *client.Client) *namespace { + return &namespace{ + client: c, + } +} + +func (n *namespace) Fetch(name string) (*corev1.Namespace, error) { + log.Debug("About to fetch namespace from cluster", "namespace", name) + ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: name}} + if err := n.client.ControlCli.Get(context.TODO(), types.NamespacedName{Name: name}, ns); err != nil && errors.IsNotFound(err) { + log.Debug("Not found", "namespace", name) + return nil, nil + } else if err != nil { + return nil, err + } + return ns, nil +} + +func (n *namespace) Create(name string) (*corev1.Namespace, error) { + ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: name}} + if err := n.client.ControlCli.Create(context.TODO(), ns); err != nil { + return nil, err + } + return ns, nil +} + +func (n *namespace) CreateIfNotExists(name string) (*corev1.Namespace, error) { + if ns, err := n.Fetch(name); err != nil { + return nil, err + } else if ns != nil { + return ns, nil + } + ns, err := n.Create(name) + if err != nil { + return nil, err + } + return ns, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/namespace_test.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/namespace_test.go new file mode 100644 index 00000000000..53c36f30931 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/namespace_test.go @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "testing" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client" + + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +func Test_CreateNamespaceThatDoesNotExist(t *testing.T) { + cli := fake.NewClientBuilder().Build() + ns, err := NamespaceC(&client.Client{ControlCli: cli}).CreateIfNotExists("test") + assert.Nil(t, err) + assert.NotNil(t, ns) +} + +func Test_FetchNamespaceThatDoesNotExist(t *testing.T) { + cli := fake.NewClientBuilder().Build() + ns, err := NamespaceC(&client.Client{ControlCli: cli}).Fetch("test") + assert.Nil(t, err) + assert.Nil(t, ns) +} + +func Test_FetchNamespaceThatDExists(t *testing.T) { + cli := fake.NewClientBuilder().WithRuntimeObjects(&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test", CreationTimestamp: metav1.Now()}}).Build() + ns, err := NamespaceC(&client.Client{ControlCli: cli}).Fetch("test") + assert.Nil(t, err) + assert.NotNil(t, ns) + assert.False(t, ns.CreationTimestamp.IsZero()) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/pod.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/pod.go new file mode 100644 index 00000000000..bd2ce15aa78 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/pod.go @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + "io/ioutil" + + corev1 "k8s.io/api/core/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client" +) + +// PodInterface has functions that interacts with pod object in the Kubernetes cluster +type PodInterface interface { + // Immediately return pod log + GetLogs(namespace, podName, containerName string) (string, error) + // Wait until pod is terminated and then return pod log + GetLogsWithFollow(namespace, podName, containerName string) (string, error) +} + +type pod struct { + client *client.Client +} + +func newPod(c *client.Client) PodInterface { + return &pod{ + client: c, + } +} + +func (pod *pod) GetLogs(namespace, podName, containerName string) (string, error) { + return pod.getLogs(namespace, podName, containerName, false) +} + +func (pod *pod) GetLogsWithFollow(namespace, podName, containerName string) (string, error) { + return pod.getLogs(namespace, podName, containerName, true) +} + +func (pod *pod) getLogs(namespace, podName, containerName string, follow bool) (string, error) { + log.Debug("About to fetch log of pod from cluster", "pod name", podName, "namespace", namespace, "follow", follow) + podLogOpts := corev1.PodLogOptions{ + Follow: follow, + Container: containerName, + } + req := pod.client.KubernetesExtensionCli.CoreV1().Pods(namespace).GetLogs(podName, &podLogOpts) + readCloser, err := req.Stream(context.TODO()) + if err != nil { + return "", err + } + bytes, err := ioutil.ReadAll(readCloser) + if err != nil { + return "", err + } + return string(bytes), nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/resource.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/resource.go new file mode 100644 index 00000000000..b53738764c4 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/resource.go @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "fmt" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + kogitocli "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client" + + "k8s.io/apimachinery/pkg/util/yaml" +) + +const ( + // Name is the name of the Kogito Operator deployed in a namespace + KogitoOperatorName = "kogito-operator" +) + +// ResourceInterface has functions that interacts with any resource object in the Kubernetes cluster +type ResourceInterface interface { + ResourceReader + ResourceWriter + // CreateIfNotExists will fetch for the object resource in the Kubernetes cluster, if not exists, will create it. + CreateIfNotExists(resource client.Object) (err error) + // CreateIfNotExistsForOwner sets the controller owner to the given resource and creates if it not exists. + // If the given resource exists, won't update the object with the given owner. + CreateIfNotExistsForOwner(resource client.Object, owner metav1.Object, scheme *runtime.Scheme) (err error) + // CreateForOwner sets the controller owner to the given resource and creates the resource. + CreateForOwner(resource client.Object, owner metav1.Object, scheme *runtime.Scheme) error + // CreateFromYamlContent creates Kubernetes resources from a yaml string content + CreateFromYamlContent(yamlContent, namespace string, resourceRef client.Object, beforeCreate func(object interface{})) error +} + +type resource struct { + ResourceReader + ResourceWriter +} + +func newResource(c *kogitocli.Client) *resource { + return &resource{ + ResourceReader: ResourceReaderC(c), + ResourceWriter: ResourceWriterC(c), + } +} + +func (r *resource) CreateIfNotExists(resource client.Object) error { + log.Info("Create resource if not exists", "kind", resource.GetObjectKind().GroupVersionKind().Kind, "name", resource.GetName(), "namespace", resource.GetNamespace()) + + if exists, err := r.ResourceReader.Fetch(resource); err == nil && !exists { + return r.ResourceWriter.Create(resource) + } else if err != nil { + log.Error(err, "Failed to fetch object. ") + return err + } + log.Info("Skip creating - object already exists") + return nil +} + +func (r *resource) CreateIfNotExistsForOwner(resource client.Object, owner metav1.Object, scheme *runtime.Scheme) error { + err := controllerutil.SetControllerReference(owner, resource, scheme) + if err != nil { + return err + } + return r.CreateIfNotExists(resource) +} + +func (r *resource) CreateForOwner(resource client.Object, owner metav1.Object, scheme *runtime.Scheme) error { + err := controllerutil.SetControllerReference(owner, resource, scheme) + if err != nil { + return err + } + return r.ResourceWriter.Create(resource) +} + +func (r *resource) CreateFromYamlContent(yamlFileContent, namespace string, resourceRef client.Object, beforeCreate func(object interface{})) error { + docs := strings.Split(yamlFileContent, "---") + for _, doc := range docs { + if len(doc) <= 0 { + log.Debug("Empty content ... Skipping it") + continue + } + + log.Debug("Create from yaml content", "content", doc) + if err := yaml.NewYAMLOrJSONDecoder(strings.NewReader(doc), len([]byte(doc))).Decode(resourceRef); err != nil { + return fmt.Errorf("Error while unmarshalling file: %v ", err) + } + + if len(resourceRef.GetObjectKind().GroupVersionKind().Kind) <= 0 { + log.Error(fmt.Errorf("Error while unmarshalling yaml content"), "Cannot parse yaml content into resources... Skipping it", "content", doc) + continue + } + + if namespace != "" { + resourceRef.SetNamespace(namespace) + } + resourceRef.SetResourceVersion("") + resourceRef.SetLabels(map[string]string{"app": KogitoOperatorName}) + + log.Debug("Will create a new resource", "kind", resourceRef.GetObjectKind().GroupVersionKind().Kind, "name", resourceRef.GetName(), "namespace", resourceRef.GetNamespace()) + if beforeCreate != nil { + beforeCreate(resourceRef) + } + if err := r.CreateIfNotExists(resourceRef); err != nil { + return fmt.Errorf("Error creating object %s: %v ", resourceRef.GetName(), err) + } + } + return nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/resource_reader.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/resource_reader.go new file mode 100644 index 00000000000..e65ab66fd21 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/resource_reader.go @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + "reflect" + + "github.com/RHsyseng/operator-utils/pkg/resource/read" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + + kogitocli "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client" +) + +// ResourceReader interface to read kubernetes object +type ResourceReader interface { + // FetchWithKey fetches and binds a resource from the Kubernetes cluster with the defined key. If not exists, returns false. + FetchWithKey(key types.NamespacedName, resource client.Object) (exists bool, err error) + // Fetch fetches and binds a resource with given name and namespace from the Kubernetes cluster. If not exists, returns false. + Fetch(resource client.Object) (exists bool, err error) + // ListWithNamespace fetches and binds a list resource from the Kubernetes cluster with the defined namespace. + ListWithNamespace(namespace string, list client.ObjectList) error + // ListWithNamespaceAndLabel same as ListWithNamespace, but also limit the query scope by the given labels + ListWithNamespaceAndLabel(namespace string, list client.ObjectList, labels map[string]string) error + // ListAll returns a map of Kubernetes resources organized by type, based on provided List objects + ListAll(objectTypes []client.ObjectList, namespace string, ownerObject metav1.Object) (map[reflect.Type][]client.Object, error) +} + +// ResourceReaderC provide ResourceReader reference +func ResourceReaderC(cli *kogitocli.Client) ResourceReader { + return &resourceReader{ + client: cli, + } +} + +type resourceReader struct { + client *kogitocli.Client +} + +func (r *resourceReader) Fetch(resource client.Object) (bool, error) { + return r.FetchWithKey(types.NamespacedName{Name: resource.GetName(), Namespace: resource.GetNamespace()}, resource) +} + +func (r *resourceReader) FetchWithKey(key types.NamespacedName, resource client.Object) (bool, error) { + log.Debug("About to fetch object", "name", key.Name, "namespace", key.Namespace) + err := r.client.ControlCli.Get(context.TODO(), key, resource) + if err != nil && errors.IsNotFound(err) { + return false, nil + } else if err != nil { + return false, err + } + log.Debug("Found object", "kind", resource.GetObjectKind().GroupVersionKind().Kind, "name", key.Name, "namespace", key.Namespace, "Creation time", resource.GetCreationTimestamp()) + return true, nil +} + +func (r *resourceReader) ListWithNamespace(namespace string, list client.ObjectList) error { + err := r.client.ControlCli.List(context.TODO(), list, client.InNamespace(namespace)) + if err != nil { + log.Error(err, "Failed to list resource.") + return err + } + return nil +} + +func (r *resourceReader) ListWithNamespaceAndLabel(namespace string, list client.ObjectList, labels map[string]string) error { + err := r.client.ControlCli.List(context.TODO(), list, client.InNamespace(namespace), client.MatchingLabels(labels)) + if err != nil { + log.Error(err, "Failed to list resource. ") + return err + } + return nil +} + +func (r *resourceReader) ListAll(objectTypes []client.ObjectList, namespace string, ownerObject metav1.Object) (map[reflect.Type][]client.Object, error) { + reader := read.New(r.client.ControlCli).WithNamespace(namespace).WithOwnerObject(ownerObject) + return reader.ListAll(objectTypes...) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/resource_writer.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/resource_writer.go new file mode 100644 index 00000000000..553058d1eb6 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes/resource_writer.go @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/RHsyseng/operator-utils/pkg/resource/write" + "sigs.k8s.io/controller-runtime/pkg/client" + + kogitocli "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client" +) + +// ResourceWriter interface to write kubernetes object +type ResourceWriter interface { + // Create creates a new Kubernetes object in the cluster. + // Note that no checks will be performed in the cluster. If you're not sure, use CreateIfNotExists. + Create(resource client.Object) error + // Delete delete the given object + Delete(resource client.Object) error + // Update the given object + Update(resource client.Object) error + // UpdateStatus update the given object status + UpdateStatus(resource client.Object) error + // CreateResources create provided objects + CreateResources(resources []client.Object) (bool, error) + // UpdateResources update provided objects + UpdateResources(existing []client.Object, resources []client.Object) (bool, error) + // DeleteResources delete provided objects + DeleteResources(resources []client.Object) (bool, error) +} + +// ResourceWriterC provide ResourceWrite reference +func ResourceWriterC(cli *kogitocli.Client) ResourceWriter { + return &resourceWriter{ + client: cli, + } +} + +type resourceWriter struct { + client *kogitocli.Client +} + +func (r *resourceWriter) Create(resource client.Object) error { + log.Debug("Creating resource", "kind", resource.GetObjectKind().GroupVersionKind().Kind, "name", resource.GetName(), "namespace", resource.GetNamespace()) + if err := r.client.ControlCli.Create(context.TODO(), resource); err != nil { + log.Error(err, "Failed to create object. ") + return err + } + return nil +} + +func (r *resourceWriter) Update(resource client.Object) error { + log.Debug("About to update resource", "name", resource.GetName(), "namespace", resource.GetNamespace()) + if err := r.client.ControlCli.Update(context.TODO(), resource); err != nil { + return err + } + log.Debug("Resource updated.", "name", resource.GetName(), "Creation Timestamp", resource.GetCreationTimestamp(), "Resource", resource) + return nil +} + +func (r *resourceWriter) Delete(resource client.Object) error { + if err := r.client.ControlCli.Delete(context.TODO(), resource); err != nil { + log.Error(err, "Failed to delete resource.", "name", resource.GetName()) + return err + } + return nil +} + +func (r *resourceWriter) UpdateStatus(resource client.Object) error { + log.Debug("About to update status for object", "name", resource.GetName(), "namespace", resource.GetNamespace()) + if err := r.client.ControlCli.Status().Update(context.TODO(), resource); err != nil { + return err + } + + log.Debug("Object status updated.", "name", resource.GetName(), "Creation Timestamp", resource.GetCreationTimestamp()) + return nil +} + +func (r *resourceWriter) CreateResources(resources []client.Object) (bool, error) { + writer := write.New(r.client.ControlCli) + return writer.AddResources(resources) +} + +func (r *resourceWriter) UpdateResources(existing []client.Object, resources []client.Object) (bool, error) { + writer := write.New(r.client.ControlCli) + return writer.UpdateResources(existing, resources) +} + +func (r *resourceWriter) DeleteResources(resources []client.Object) (bool, error) { + writer := write.New(r.client.ControlCli) + return writer.RemoveResources(resources) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/client/test/kubeconfig.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/test/kubeconfig.go new file mode 100644 index 00000000000..40ff31c6cf2 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/client/test/kubeconfig.go @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "fmt" + "os" + + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +const ( + tempKubeEnvConfig = "/tmp/.kube/config" +) + +// OverrideDefaultKubeConfigEmptyContext same as OverrideDefaultKubeConfigWithNamespace, but sets default namespace to "default" +func OverrideDefaultKubeConfigEmptyContext() (kubeconfigfile string, rollbackEnvOverride func()) { + return OverrideDefaultKubeConfigWithNamespace("default") +} + +// OverrideDefaultKubeConfigWithNamespace overrides the env var variable meant to point to the kube config file with a temporary file to be used in tests +// You must call defer with rollbackEnvOverride func to switch back to the original value and not jeopardize the local configuration +func OverrideDefaultKubeConfigWithNamespace(namespace string) (kubeconfigfile string, rollbackEnvOverride func()) { + defaultConfig := clientcmdapi.NewConfig() + defaultConfig.CurrentContext = namespace + "/cluster:8080/user" + defaultConfig.Contexts[defaultConfig.CurrentContext] = clientcmdapi.NewContext() + defaultConfig.Contexts[defaultConfig.CurrentContext].Namespace = namespace + defaultConfig.Contexts[defaultConfig.CurrentContext].Cluster = "cluster:8080" + defaultConfig.Contexts[defaultConfig.CurrentContext].AuthInfo = "user" + if err := clientcmd.WriteToFile(*defaultConfig, tempKubeEnvConfig); err != nil { + panic(fmt.Errorf("Impossible to write default kubeclient config: %s ", err)) + } + return OverrideDefaultKubeConfig() +} + +// OverrideDefaultKubeConfig overrides the default KUBECONFIG env var to point to a temporary file, does not create any context. +func OverrideDefaultKubeConfig() (kubeconfigfile string, rollbackEnvOverride func()) { + oldEnvVar := os.Getenv(clientcmd.RecommendedConfigPathEnvVar) + os.Setenv(clientcmd.RecommendedConfigPathEnvVar, tempKubeEnvConfig) + return tempKubeEnvConfig, func() { + if err := os.Remove(tempKubeEnvConfig); err != nil { + if !os.IsNotExist(err) { + panic(fmt.Errorf("Impossible to remove file %s: %s ", tempKubeEnvConfig, err)) + } + } + os.Setenv(clientcmd.RecommendedConfigPathEnvVar, oldEnvVar) + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/command.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/command.go new file mode 100644 index 00000000000..8ef70a4ac07 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/command.go @@ -0,0 +1,168 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "os/exec" + "sync" + "time" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/logger" +) + +var ( + syncMutexMap sync.Map +) + +// CreateCommand methods initializes the basic data to run commands. +func CreateCommand(commandName string, args ...string) Command { + return &commandStruct{name: commandName, args: args} +} + +// Command wraps information about the command to execute. +type Command interface { + // WithLoggerContext method attaches a logger context to trace all the command logs when executing it. + WithLoggerContext(loggerContext string) Command + // InDirectory method sets the directory where the command will be executed. + InDirectory(directory string) Command + // WithRetry method defines retry options to be applied to the command. + WithRetry(opts ...RetryOption) Command + // Sync method allows to execute only one command at a time based on the syncID. + Sync(syncID string) Command + // Execute command and returns the outputs. + Execute() (string, error) +} + +// struct that represents a command. +type commandStruct struct { + name string + args []string + directory string + loggerContext string + retries int + retryDelay time.Duration + syncID string +} + +func (cmd *commandStruct) WithLoggerContext(loggerContext string) Command { + cmd.loggerContext = loggerContext + return cmd +} + +func (cmd *commandStruct) Sync(syncID string) Command { + cmd.syncID = syncID + return cmd +} + +func (cmd *commandStruct) InDirectory(directory string) Command { + cmd.directory = directory + return cmd +} + +func (cmd *commandStruct) WithRetry(opts ...RetryOption) Command { + for _, opt := range opts { + opt(cmd) + } + return cmd +} + +func (cmd *commandStruct) Execute() (string, error) { + if len(cmd.syncID) > 0 { + mutex := getMutexOrCreate(cmd.syncID) + mutex.Lock() + defer mutex.Unlock() + } + return cmd.executeCommand() +} + +func (cmd *commandStruct) executeCommand() (string, error) { + var logger = cmd.getLogger() + + if len(cmd.directory) == 0 { + logger.Info("Execute command", "command", cmd.name, "args", cmd.args) + } else { + logger.Info("Execute command ", "command", cmd.name, "args", cmd.args, "directory", cmd.directory) + } + + var out []byte + var err error + + // If retries are set then repeat until command succeed + for i := 0; i <= cmd.retries; i++ { + command := exec.Command(cmd.name, cmd.args...) + command.Dir = cmd.directory + out, err = command.Output() + + if err == nil { + break + } + + time.Sleep(cmd.retryDelay) + } + + if err != nil { + logger.Error(err, "output command", "output", string(out[:])) + if ee, ok := err.(*exec.ExitError); ok { + logger.Error(err, "error output command", "output", string(ee.Stderr)) + } + } else { + logger.Debug("output command", "output", string(out[:])) + } + + return string(out[:]), err +} +func (cmd *commandStruct) getLogger() logger.Logger { + var logger logger.Logger + if len(cmd.loggerContext) > 0 { + logger = GetLogger(cmd.loggerContext) + } else { + logger = GetMainLogger() + } + + return logger +} + +// Retry misc functions + +// RetryOption declares funtion to be applied on Retry +type RetryOption func(*commandStruct) + +// RetryDelay declares funtion setting delay between retries +func RetryDelay(delay time.Duration) RetryOption { + return func(cmd *commandStruct) { + cmd.retryDelay = delay + } +} + +// NumberOfRetries declares funtion setting number of retries +func NumberOfRetries(retries int) RetryOption { + return func(cmd *commandStruct) { + cmd.retries = retries + } +} + +func getMutexOrCreate(syncID string) *sync.Mutex { + mutex, exists := syncMutexMap.Load(syncID) + if !exists { + mutex = &sync.Mutex{} + syncMutexMap.Store(syncID, mutex) + } + return mutex.(*sync.Mutex) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/container_engine.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/container_engine.go new file mode 100644 index 00000000000..f4f842f7be4 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/container_engine.go @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + +const ( + defaultRetryNb = 3 +) + +// ContainerEngine is the engine providing container and registry functionality +type ContainerEngine interface { + // PullImage pull image from external registry to internal registry + PullImage(imageTag string) ContainerEngine + + // PushImage push image from internal registry to external registry + PushImage(imageTag string) ContainerEngine + + // BuildImage builds the container image from specified directory + BuildImage(projectLocation, imageTag string) ContainerEngine + + // Setup the retry for the different commands + WithRetry(retryNb int) ContainerEngine + + // GetError returns error in case any execution failed + GetError() error +} + +type containerEngineStruct struct { + engine string + buildCommand string + namespace string + supportTLSVerify bool + err error + retryNb int +} + +var dockerContainerEngine = containerEngineStruct{ + engine: "docker", + supportTLSVerify: false, + buildCommand: "build", +} + +var podmanContainerEngine = containerEngineStruct{ + engine: "podman", + supportTLSVerify: true, + buildCommand: "build", +} + +var buildahContainerEngine = containerEngineStruct{ + engine: "buildah", + supportTLSVerify: true, + buildCommand: "build-using-dockerfile", +} + +var containerEngines = map[string]containerEngineStruct{ + dockerContainerEngine.engine: dockerContainerEngine, + podmanContainerEngine.engine: podmanContainerEngine, + buildahContainerEngine.engine: buildahContainerEngine, +} + +// GetContainerEngine returns container engine based on test configuration +func GetContainerEngine(namespace string) ContainerEngine { + containerEngine := containerEngines[config.GetContainerEngine()] + + containerEngine.namespace = namespace + containerEngine.retryNb = defaultRetryNb + return &containerEngine +} + +func (containerEngine *containerEngineStruct) PullImage(imageTag string) ContainerEngine { + pullImageArgs := []string{"pull"} + + if containerEngine.supportTLSVerify { + pullImageArgs = append(pullImageArgs, "--tls-verify=false") + } + + pullImageArgs = append(pullImageArgs, imageTag) + + if containerEngine.err == nil { + _, containerEngine.err = CreateCommand(containerEngine.engine, pullImageArgs...). + WithRetry(NumberOfRetries(containerEngine.retryNb)). + WithLoggerContext(containerEngine.namespace). + Execute() + } + return containerEngine +} + +func (containerEngine *containerEngineStruct) PushImage(imageTag string) ContainerEngine { + pushImageArgs := []string{"push"} + + if containerEngine.supportTLSVerify { + pushImageArgs = append(pushImageArgs, "--tls-verify=false") + } + + pushImageArgs = append(pushImageArgs, imageTag) + + if containerEngine.err == nil { + _, containerEngine.err = CreateCommand(containerEngine.engine, pushImageArgs...). + WithRetry(NumberOfRetries(containerEngine.retryNb)). + WithLoggerContext(containerEngine.namespace). + Execute() + } + return containerEngine +} + +func (containerEngine *containerEngineStruct) BuildImage(projectLocation, imageTag string) ContainerEngine { + if containerEngine.err == nil { + _, containerEngine.err = CreateCommand(containerEngine.engine, containerEngine.buildCommand, "--tag", imageTag, "."). + WithRetry(NumberOfRetries(containerEngine.retryNb)). + InDirectory(projectLocation). + WithLoggerContext(containerEngine.namespace). + Execute() + } + return containerEngine +} + +func (containerEngine *containerEngineStruct) WithRetry(retryNb int) ContainerEngine { + containerEngine.retryNb = retryNb + return containerEngine +} + +func (containerEngine *containerEngineStruct) GetError() error { + return containerEngine.err +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/dockerfile_provider.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/dockerfile_provider.go new file mode 100644 index 00000000000..a6ff0783161 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/dockerfile_provider.go @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + "io/ioutil" + "path/filepath" + "strings" +) + +const ( + quarkusFastJarFolder = "quarkus-app" + quarkusFastJarName = "quarkus-run.jar" + + quarkusJVMLegacyApplicationBinarySuffix = "-runner.jar" + quarkusJVMFastApplicationBinarySuffix = quarkusFastJarFolder + quarkusNativeApplicationBinarySuffix = "-runner" + springBootApplicationBinarySuffix = ".jar" +) + +// KogitoApplicationDockerfileProvider is the API to provide Dockerfile content for image creation based on built project content +type KogitoApplicationDockerfileProvider interface { + // GetDockerfileContent returns Dockerfile content for image creation + GetDockerfileContent() (string, error) +} + +type kogitoApplicationDockerfileProviderStruct struct { + projectLocation string + native bool + jarSubDirectory string + executableFileName string + applicationBinarySuffix string + folderDependencies []string +} + +var quarkusNonNativeLegacyJarKogitoApplicationDockerfileProvider = kogitoApplicationDockerfileProviderStruct{ + native: false, + applicationBinarySuffix: quarkusJVMLegacyApplicationBinarySuffix, + folderDependencies: []string{"lib"}, +} + +var quarkusNonNativeFastJarKogitoApplicationDockerfileProvider = kogitoApplicationDockerfileProviderStruct{ + native: false, + jarSubDirectory: quarkusFastJarFolder, + executableFileName: quarkusFastJarName, + applicationBinarySuffix: quarkusJVMFastApplicationBinarySuffix, + folderDependencies: []string{"lib", "quarkus", "app"}, +} + +var quarkusNativeKogitoApplicationDockerfileProvider = kogitoApplicationDockerfileProviderStruct{ + native: true, + applicationBinarySuffix: quarkusNativeApplicationBinarySuffix, +} + +var springbootKogitoApplicationDockerfileProvider = kogitoApplicationDockerfileProviderStruct{ + native: false, + applicationBinarySuffix: springBootApplicationBinarySuffix, +} + +// GetKogitoApplicationDockerfileProvider returns KogitoApplicationDockerfileProvider based on project location +func GetKogitoApplicationDockerfileProvider(projectLocation string) KogitoApplicationDockerfileProvider { + targetDir := projectLocation + "/target" + dockerfileProvider := &springbootKogitoApplicationDockerfileProvider + + if fileWithSuffixExists(targetDir, quarkusNativeKogitoApplicationDockerfileProvider.applicationBinarySuffix) { + dockerfileProvider = &quarkusNativeKogitoApplicationDockerfileProvider + } else if fileWithSuffixExists(targetDir, quarkusNonNativeFastJarKogitoApplicationDockerfileProvider.applicationBinarySuffix) { + dockerfileProvider = &quarkusNonNativeFastJarKogitoApplicationDockerfileProvider + } else if fileWithSuffixExists(targetDir, quarkusNonNativeLegacyJarKogitoApplicationDockerfileProvider.applicationBinarySuffix) { + dockerfileProvider = &quarkusNonNativeLegacyJarKogitoApplicationDockerfileProvider + } + + dockerfileProvider.projectLocation = projectLocation + return dockerfileProvider +} + +func (dockerfileProvider *kogitoApplicationDockerfileProviderStruct) GetDockerfileContent() (string, error) { + // Declare base image to build from + dockerfileContent := fmt.Sprintf("FROM %s\n", GetKogitoBuildRuntimeImage(dockerfileProvider.native)) + + subDir := "" + if len(dockerfileProvider.jarSubDirectory) > 0 { + subDir = dockerfileProvider.jarSubDirectory + "/" + } + executableFileName := fmt.Sprintf("%s%s", filepath.Base(dockerfileProvider.projectLocation), dockerfileProvider.applicationBinarySuffix) + if len(dockerfileProvider.executableFileName) > 0 { + executableFileName = dockerfileProvider.executableFileName + } + + // Copy application binary into $KOGITO_HOME/bin + dockerfileContent += fmt.Sprintf("COPY target/%s%s $KOGITO_HOME/bin\n", subDir, executableFileName) + + // Copy dependencies folder + for _, depFolder := range dockerfileProvider.folderDependencies { + dockerfileContent += fmt.Sprintf("COPY target/%s%s $KOGITO_HOME/bin/%s\n", subDir, depFolder, depFolder) + } + + return dockerfileContent, nil +} + +func fileWithSuffixExists(scannedDirectory, fileSuffix string) bool { + files, err := ioutil.ReadDir(scannedDirectory) + if err != nil { + panic(fmt.Errorf("Error reading directory %s: %v", scannedDirectory, err)) + } + + for _, file := range files { + if strings.HasSuffix(file.Name(), fileSuffix) { + return true + } + } + return false +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/env/env.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/env/env.go new file mode 100644 index 00000000000..955a96f2c38 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/env/env.go @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package env + +import ( + "os" + "strconv" +) + +func GetEnvUsername() string { + return GetOSEnv("USERNAME", "nouser") +} + +// GetOSEnv gets a env variable +func GetOSEnv(key, fallback string) string { + value, exists := os.LookupEnv(key) + if !exists { + value = fallback + } + return value +} + +// GetBoolOSEnv gets a env variable as a boolean +func GetBoolOSEnv(key string) bool { + val := GetOSEnv(key, "false") + ret, err := strconv.ParseBool(val) + if err != nil { + return false + } + return ret +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/grafana.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/grafana.go new file mode 100644 index 00000000000..5cdb5734bf2 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/grafana.go @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" + grafanav1 "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1" +) + +const ( + // Default Grafana service name + defaultGrafanaService = "grafana-service" + // Default Grafana deployment name + defaultGrafanaDeployment = "grafana-deployment" +) + +var grafanaImages = map[string]string{ + "docker.io/grafana/grafana:7.5.17": "docker.io/grafana/grafana@sha256:15abb652aa82eeb9f45589278b34ae6ef0e96f74c389cadde31831eb0b1ce228", +} + +// DeployGrafanaInstance deploys an instance of Grafana watching for label with specific name and value +func DeployGrafanaInstance(namespace, labelName, labelValue string) error { + GetLogger(namespace).Info("Creating Grafana CR to spin up instance.") + + grafanaCR := &grafanav1.Grafana{ + ObjectMeta: metav1.ObjectMeta{ + Name: "grafana", + Namespace: namespace, + }, + Spec: grafanav1.GrafanaSpec{ + Config: grafanav1.GrafanaConfig{ + AuthAnonymous: &grafanav1.GrafanaConfigAuthAnonymous{ + Enabled: getBool(true), + }, + }, + DashboardLabelSelector: []*metav1.LabelSelector{ + { + MatchLabels: map[string]string{labelName: labelValue}, + }, + }, + }, + } + if err := kubernetes.ResourceC(kubeClient).Create(grafanaCR); err != nil { + return fmt.Errorf("Error while creating Grafana CR: %v ", err) + } + + // Patch Grafana CR with image based on digest to allow image mirroring. Can be removed when Garafana image is moved out of docker.io registry. + if deployment, err := GetDeploymentWaiting(namespace, defaultGrafanaDeployment, 2); err != nil { + return fmt.Errorf("Error while waiting for Grafana Deployment to become available: %v ", err) + } else if imageShaTag, imageEntryPresent := grafanaImages[deployment.Spec.Template.Spec.Containers[0].Image]; imageEntryPresent { + err := patchGrafanaCR(grafanaCR.GetNamespace(), grafanaCR.GetName(), func(grafana *grafanav1.Grafana) { + grafana.Spec.BaseImage = imageShaTag + }) + if err != nil { + return err + } + } else { + return fmt.Errorf("Grafana image %s wasn't found in the list of Grafana images with defined digest. In case this is new Grafana image please add it into the list with proper digest", deployment.Spec.Template.Spec.Containers[0].Image) + } + + if IsOpenshift() { + // Grafana creates HTTPS routes by default, need to create HTTP route manually + if err := createHTTPRoute(namespace, defaultGrafanaService); err != nil { + return fmt.Errorf("Error while creating Grafana route: %v ", err) + } + } else { + // Need to expose Grafana + if err := ExposeServiceOnKubernetes(namespace, defaultGrafanaService); err != nil { + return fmt.Errorf("Error while exposing Grafana service: %v ", err) + } + } + + return nil +} + +func getBool(b bool) *bool { + return &b +} + +func patchGrafanaCR(namespace, name string, patch func(grafana *grafanav1.Grafana)) error { + var err error + // Try patching for several times + for i := 0; i < 3; i++ { + // Fetch Grafana CR + grafana := &grafanav1.Grafana{} + if exists, err := GetObjectWithKey(types.NamespacedName{Namespace: namespace, Name: name}, grafana); err != nil { + return fmt.Errorf("Error fetching Grafana %s in namespace %s: %v", name, namespace, err) + } else if !exists { + return fmt.Errorf("Grafana %s in namespace %s doesn't exist", name, namespace) + } + + // Patch Grafana CR + patch(grafana) + + // Update Grafana CR + if err = UpdateObject(grafana); err == nil { + return nil + } + } + return fmt.Errorf("Error patching Grafana %s in namespace %s: %v", name, namespace, err) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/graphql.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/graphql.go new file mode 100644 index 00000000000..ec9e303f51d --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/graphql.go @@ -0,0 +1,150 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "context" + "fmt" + "net/http" + "strconv" + "strings" + "time" + + "github.com/machinebox/graphql" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" +) + +const graphQLNoAuthToken = "" + +// WaitForSuccessfulGraphQLRequest waits for an GraphQL request to be successful +func WaitForSuccessfulGraphQLRequest(namespace, uri, path, query string, timeoutInMin int, response interface{}, analyzeResponse func(response interface{}) (bool, error)) error { + return WaitForSuccessfulGraphQLRequestUsingAccessToken(namespace, uri, path, query, graphQLNoAuthToken, timeoutInMin, response, analyzeResponse) +} + +// WaitForSuccessfulGraphQLRequestUsingPagination waits for a GraphQL request with pagination to be successful. +// You can provide 2 functions: +// +// 1. After each response. This is called after every page is queried. Useful for checking the content of each page +// or appending results for final checks after all pages are retrieved. +// +// 2. After full request. This is called once after all pages are queried. Useful for final checks on all results. +// +// If more than one page is to be retrieved, include the `$offset` variable in the query which will be used for pagination. +func WaitForSuccessfulGraphQLRequestUsingPagination(namespace, uri, path, query string, timeoutInMin, pageSize, totalSize int, response interface{}, afterEachResponse func(response interface{}) (bool, error), afterFullRequest func() (bool, error)) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("GraphQL query %s on path '%s' using '%s' access token to be successful", query, path, graphQLNoAuthToken), timeoutInMin, + func() (bool, error) { + totalPages := totalSize / pageSize + if totalSize%pageSize != 0 { + totalPages++ + } + for queried := 0; queried < totalSize; { + query := strings.ReplaceAll(query, "$offset", strconv.Itoa(queried)) + GetLogger(namespace).Info("Querying", "page no.", queried/pageSize+1, "of", totalPages, "query", query) + err := ExecuteGraphQLRequestWithLoggingOption(namespace, uri, path, query, graphQLNoAuthToken, response, false) + if err != nil { + return false, err + } + if afterEachResponse != nil { + if success, err := afterEachResponse(response); !success || err != nil { + return success, err + } + } + queried = queried + pageSize + } + + if afterFullRequest != nil { + return afterFullRequest() + } + + return true, nil + }) +} + +// WaitForSuccessfulGraphQLRequestUsingAccessToken waits for an GraphQL request using access token to be successful +func WaitForSuccessfulGraphQLRequestUsingAccessToken(namespace, uri, path, query, accessToken string, timeoutInMin int, response interface{}, analyzeResponse func(response interface{}) (bool, error)) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("GraphQL query %s on path '%s' using '%s' access token to be successful", query, path, accessToken), timeoutInMin, + func() (bool, error) { + success, err := IsGraphQLRequestSuccessful(namespace, uri, path, query, accessToken, response) + if err != nil { + return false, err + } + + if analyzeResponse != nil { + return analyzeResponse(response) + } + + return success, nil + }) +} + +// WaitForFailingGraphQLRequest waits for an GraphQL request to be fail +func WaitForFailingGraphQLRequest(namespace, uri, path, query string, timeoutInMin int) error { + return WaitForFailingGraphQLRequestUsingAccessToken(namespace, uri, path, query, graphQLNoAuthToken, timeoutInMin) +} + +// WaitForFailingGraphQLRequestUsingAccessToken waits for an GraphQL request using access token to be fail +func WaitForFailingGraphQLRequestUsingAccessToken(namespace, uri, path, query, accessToken string, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("GraphQL query %s on path '%s' using '%s' access token to be failing", query, path, accessToken), timeoutInMin, + func() (bool, error) { + success, err := IsGraphQLRequestSuccessful(namespace, uri, path, query, accessToken, nil) + return !success || err != nil, nil + }) +} + +// ExecuteGraphQLRequestWithLogging executes a GraphQL query +func ExecuteGraphQLRequestWithLogging(namespace, uri, path, query, bearerToken string, response interface{}) error { + return ExecuteGraphQLRequestWithLoggingOption(namespace, uri, path, query, bearerToken, response, true) +} + +// ExecuteGraphQLRequestWithLoggingOption executes a GraphQL query with possibility of logging each request +func ExecuteGraphQLRequestWithLoggingOption(namespace, uri, path, query, bearerToken string, response interface{}, logResponse bool) error { + // create a client (safe to share across requests) + client := graphql.NewClient(fmt.Sprintf("%s/%s", uri, path), graphql.WithHTTPClient(&http.Client{Timeout: (time.Duration(10*config.GetLoadFactor()) * time.Second)})) + req := graphql.NewRequest(query) + req.Header.Set("Cache-Control", "no-cache") + addGraphqlAuthentication(req, bearerToken) + ctx := context.Background() + if err := client.Run(ctx, req, response); err != nil { + return err + } + GetLogger(namespace).Info("GraphQL response received successfully") + if logResponse { + GetLogger(namespace).Info("GraphQL", "response", response) + + } + return nil +} + +// IsGraphQLRequestSuccessful makes and checks whether a GraphQL query is successful +func IsGraphQLRequestSuccessful(namespace, uri, path, query, bearerToken string, response interface{}) (bool, error) { + err := ExecuteGraphQLRequestWithLogging(namespace, uri, path, query, bearerToken, response) + if err != nil { + return false, err + } + return true, nil +} + +func addGraphqlAuthentication(request *graphql.Request, bearerToken string) { + if len(bearerToken) > 0 { + // Bearer authentication + request.Header.Add("Authorization", "Bearer "+bearerToken) + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/http.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/http.go new file mode 100644 index 00000000000..9b1a87967b0 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/http.go @@ -0,0 +1,369 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "bytes" + "crypto/tls" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + "strings" + "sync" + "time" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" +) + +type ( + // HTTPRequestResult represents the success or error of an HTTP request + HTTPRequestResult string + + // HTTPRequestInfo structure encapsulates all information needed to execute an HTTP request + HTTPRequestInfo struct { + HTTPMethod, URI, Path, BodyFormat, BodyContent, Token string + Unsecure bool + Headers map[string]string + } +) + +const ( + // HTTPRequestResultSuccess in case of success + HTTPRequestResultSuccess HTTPRequestResult = "success" + // HTTPRequestResultError in case of error + HTTPRequestResultError HTTPRequestResult = "error" +) + +// WaitAndRetrieveEndpointURI waits for a route and returns its URI +func WaitAndRetrieveEndpointURI(namespace, serviceName string) (string, error) { + var uri string + var err error + if IsOpenshift() { + uri, err = GetRouteURI(namespace, serviceName) + } else { + uri, err = GetIngressURI(namespace, serviceName) + } + + if err != nil { + return "", fmt.Errorf("Error retrieving URI for route %s in namespace %s: %v", serviceName, namespace, err) + } else if len(uri) <= 0 { + return "", fmt.Errorf("No URI found for route name %s in namespace %s: %v", serviceName, namespace, err) + } + GetLogger(namespace).Debug("Got", "route", uri) + return uri, nil +} + +// WaitForSuccessfulHTTPRequest waits for an HTTP request to be successful +func WaitForSuccessfulHTTPRequest(namespace string, requestInfo HTTPRequestInfo, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("HTTP %s request on path '%s' to be successful", requestInfo.HTTPMethod, requestInfo.Path), timeoutInMin, + func() (bool, error) { + return IsHTTPRequestSuccessful(namespace, requestInfo) + }) +} + +// WaitForForbiddenHTTPRequest waits for an HTTP request to be unauthorized +func WaitForForbiddenHTTPRequest(namespace string, requestInfo HTTPRequestInfo, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("HTTP %s request on path '%s' to be forbidden", requestInfo.HTTPMethod, requestInfo.Path), timeoutInMin, + func() (bool, error) { + return IsHTTPRequestForbidden(namespace, requestInfo) + }) +} + +// WaitForFailedHTTPRequest waits for an HTTP request to fail +func WaitForFailedHTTPRequest(namespace string, requestInfo HTTPRequestInfo, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("HTTP %s request on path '%s' to fail", requestInfo.HTTPMethod, requestInfo.Path), timeoutInMin, + func() (bool, error) { + return IsHTTPRequestFailed(namespace, requestInfo) + }) +} + +// ExecuteHTTPRequest executes an HTTP request +func ExecuteHTTPRequest(namespace string, requestInfo HTTPRequestInfo) (*http.Response, error) { + // Setup a retry in case the first time it did not work + retry := 0 + var resp *http.Response + var err error + for retry < config.GetHTTPRetryNumber() { + resp, err = ExecuteHTTPRequestC(createDefaultClient(), namespace, requestInfo) + if err == nil && checkHTTPResponseSuccessful(resp) { + return resp, err + } else if err != nil { + GetLogger(namespace).Warn("http call was not successful", "error", err) + } else if resp != nil { + GetLogger(namespace).Warn("Http call was not successful.", "Response code", resp.StatusCode) + if resp.StatusCode == 500 { + // In case of 500, it is server error and we don't need to call again + return resp, err + } + } else { + GetLogger(namespace).Warn("Http call was not successful. No response available ...") + } + GetLogger(namespace).Warn("Retrying in 1 second ...") + retry++ + time.Sleep(1 * time.Second) + } + return resp, err +} + +// ExecuteHTTPRequestC executes an HTTP request using a given client +func ExecuteHTTPRequestC(client *http.Client, namespace string, requestInfo HTTPRequestInfo) (*http.Response, error) { + GetLogger(namespace).Debug("ExecuteHTTPRequest", "method", requestInfo.HTTPMethod, "uri", requestInfo.URI, "path", requestInfo.Path, "bodyFormat", requestInfo.BodyFormat, "bodyContent", requestInfo.BodyContent) + + request, err := http.NewRequest(requestInfo.HTTPMethod, requestInfo.URI+"/"+requestInfo.Path, strings.NewReader(requestInfo.BodyContent)) + if len(requestInfo.BodyContent) > 0 && len(requestInfo.BodyFormat) > 0 { + switch requestInfo.BodyFormat { + case "json": + request.Header.Add("Content-Type", "application/json") + case "xml": + request.Header.Add("Content-Type", "application/xml") + case "x-www-form-urlencoded": + request.Header.Add("Content-Type", "application/x-www-form-urlencoded") + case "yaml": + request.Header.Add("Content-Type", "text/vnd.yaml") + default: + return nil, fmt.Errorf("Unknown body format to set into request: %s", requestInfo.BodyFormat) + } + } + + if err != nil { + return nil, err + } + + addHTTPAuthentication(request, requestInfo) + if requestInfo.Unsecure { + client.Transport = &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + } + + for key, value := range requestInfo.Headers { + request.Header.Add(key, value) + } + + return client.Do(request) +} + +// ExecuteHTTPRequestWithStringResponse executes an HTTP request and returns a string response in case there is no error +func ExecuteHTTPRequestWithStringResponse(namespace string, requestInfo HTTPRequestInfo) (string, error) { + httpResponse, err := ExecuteHTTPRequest(namespace, requestInfo) + if err != nil { + return "", err + } + if !checkHTTPResponseSuccessful(httpResponse) { + return "", nil + } + // Check response + defer httpResponse.Body.Close() + buf := new(bytes.Buffer) + if _, err = buf.ReadFrom(httpResponse.Body); err != nil { + return "", err + } + resultBody := buf.String() + + GetLogger(namespace).Debug("Retrieved", "resdultBody", resultBody) + return resultBody, nil +} + +// ExecuteHTTPRequestWithUnmarshalledResponse executes an HTTP request and returns response unmarshalled into specific structure in case there is no error +func ExecuteHTTPRequestWithUnmarshalledResponse(namespace string, requestInfo HTTPRequestInfo, response interface{}) error { + resultBody, err := ExecuteHTTPRequestWithStringResponse(namespace, requestInfo) + if err != nil { + return err + } + + if err := json.NewDecoder(strings.NewReader(resultBody)).Decode(response); err != nil { + return err + } + return nil +} + +// IsHTTPRequestSuccessful makes and checks whether an http request is successful +func IsHTTPRequestSuccessful(namespace string, requestInfo HTTPRequestInfo) (bool, error) { + return checkHTTPRequestConditionC(createDefaultClient(), namespace, requestInfo, checkHTTPResponseSuccessful) +} + +// IsHTTPRequestForbidden makes and checks whether an http request is unauthorized +func IsHTTPRequestForbidden(namespace string, requestInfo HTTPRequestInfo) (bool, error) { + return checkHTTPRequestConditionC(createDefaultClient(), namespace, requestInfo, checkHTTPResponseForbidden) +} + +// IsHTTPRequestFailed makes and checks whether an http request fails +func IsHTTPRequestFailed(namespace string, requestInfo HTTPRequestInfo) (bool, error) { + return checkHTTPRequestConditionC(createDefaultClient(), namespace, requestInfo, checkHTTPResponseFailed) +} + +// checkHTTPRequestConditionC makes and checks whether an http request matches a condition using a given HTTP client +func checkHTTPRequestConditionC(client *http.Client, namespace string, requestInfo HTTPRequestInfo, condition func(response *http.Response) bool) (bool, error) { + response, err := ExecuteHTTPRequestC(client, namespace, requestInfo) + if err != nil { + return false, err + } + if _, err = io.Copy(ioutil.Discard, response.Body); err != nil { // Just read the response to be able to close the connection properly + return false, err + } + defer response.Body.Close() + GetLogger(namespace).Debug("Got response", "status code", response.StatusCode) + if !condition(response) { + GetLogger(namespace).Warn("Request not expected", "status code", response.StatusCode) + return false, nil + } + + return true, nil +} + +// checkHTTPResponseSuccessful checks the HTTP response is successful +func checkHTTPResponseSuccessful(response *http.Response) bool { + return response.StatusCode >= 200 && response.StatusCode < 300 +} + +// checkHTTPResponseForbidden checks the HTTP response is forbidden +func checkHTTPResponseForbidden(response *http.Response) bool { + return response.StatusCode == 401 +} + +// checkHTTPResponseFailed checks the HTTP response failed +func checkHTTPResponseFailed(response *http.Response) bool { + return response.StatusCode >= 404 +} + +// ExecuteHTTPRequestsInThreads executes given number of requests using given number of threads (Go routines). +// Returns []HTTPRequestResult with the outcome of each thread (HTTPRequestResultSuccess or HTTPRequestResultError). +// Returns error if the desired number of requests cannot be precisely divided to the threads. +// Useful for performance testing. +func ExecuteHTTPRequestsInThreads(namespace string, requestCount, threadCount int, requestInfo HTTPRequestInfo) ([]HTTPRequestResult, error) { + if requestCount%threadCount != 0 { + return nil, fmt.Errorf("Cannot precisely divide %d requests to %d threads. Use different numbers", requestCount, threadCount) + } + requestPerThread := requestCount / threadCount + results := make([]HTTPRequestResult, threadCount) + waitGroup := &sync.WaitGroup{} + waitGroup.Add(threadCount) + + GetLogger(namespace).Info("Starting request threads") + startTime := time.Now() + + for threadID := 0; threadID < threadCount; threadID++ { + client := createDefaultClient() + go runRequestRoutine(threadID, waitGroup, client, namespace, requestPerThread, requestInfo, results) + } + + GetLogger(namespace).Info("Waiting for requests to finish") + waitGroup.Wait() + + duration := time.Since(startTime) + GetLogger(namespace).Info("requests finished", "requestCount", requestCount, "duration", duration) + return results, nil +} + +func createDefaultClient() *http.Client { + defaultTransport, ok := http.DefaultTransport.(*http.Transport) + if !ok { + panic("DefaultTransport is not of type *http.Transport") + } + customTransport := defaultTransport.Clone() + // Allow executing requests against HTTPS endpoints with insecure certificate + customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + return &http.Client{Transport: customTransport, Timeout: (time.Duration(10*config.GetLoadFactor()) * time.Second)} +} + +func runRequestRoutine(threadID int, waitGroup *sync.WaitGroup, client *http.Client, namespace string, requestPerThread int, requestInfo HTTPRequestInfo, results []HTTPRequestResult) { + defer waitGroup.Done() + GetLogger(namespace).Info("Starting Go routine", "threadID", threadID) + for i := 0; i < requestPerThread; i++ { + if success, err := checkHTTPRequestConditionC(client, namespace, requestInfo, checkHTTPResponseSuccessful); err != nil { + GetLogger(namespace).Error(err, "Go routine failed", "threadID", threadID) + results[threadID] = HTTPRequestResultError + return + } else if !success { + GetLogger(namespace).Error(fmt.Errorf("Go routine #%d - HTTP POST request to path %s was not successful", threadID, requestInfo.Path), "go routine failed") + results[threadID] = HTTPRequestResultError + return + } + } + GetLogger(namespace).Info("Go routine finished", "threadID", threadID) + results[threadID] = HTTPRequestResultSuccess +} + +// IsHTTPResponseArraySize makes and checks whether an http request returns an array of a specific size +func IsHTTPResponseArraySize(namespace string, requestInfo HTTPRequestInfo, arraySize int) (bool, error) { + var httpResponseArray []map[string]interface{} + err := ExecuteHTTPRequestWithUnmarshalledResponse(namespace, requestInfo, &httpResponseArray) + if err != nil { + return false, err + } + + return len(httpResponseArray) == arraySize, nil +} + +// DoesHTTPResponseContain checks whether the response of an http request contains a certain string +func DoesHTTPResponseContain(namespace string, requestInfo HTTPRequestInfo, responseContent string) (bool, error) { + resultBody, err := ExecuteHTTPRequestWithStringResponse(namespace, requestInfo) + if err != nil { + return false, err + } + + return strings.Contains(resultBody, responseContent), nil +} + +// DoesNotHTTPResponseContain checks whether the response of an http request does not contain a certain string +func DoesNotHTTPResponseContain(namespace string, requestInfo HTTPRequestInfo, responseContent string) (bool, error) { + resultBody, err := ExecuteHTTPRequestWithStringResponse(namespace, requestInfo) + if err != nil { + return false, err + } + + return !strings.Contains(resultBody, responseContent), nil +} + +// NewGETHTTPRequestInfo constructor creates a new HTTPRequestInfo struct with the GET HTTP method +func NewGETHTTPRequestInfo(uri, path string) HTTPRequestInfo { + return HTTPRequestInfo{ + HTTPMethod: "GET", + URI: uri, + Path: path, + } +} + +// NewPOSTHTTPRequestInfo constructor creates a new HTTPRequestInfo struct with the POST HTTP method +func NewPOSTHTTPRequestInfo(uri, path, bodyFormat, bodyContent string) HTTPRequestInfo { + return HTTPRequestInfo{ + HTTPMethod: "POST", + URI: uri, + Path: path, + BodyFormat: bodyFormat, + BodyContent: bodyContent, + } +} + +// NewPOSTHTTPRequestInfoWithHeaders constructor creates a new HTTPRequestInfo struct with the POST HTTP method and provided headers +func NewPOSTHTTPRequestInfoWithHeaders(uri, path string, headers map[string]string, bodyFormat, bodyContent string) HTTPRequestInfo { + request := NewPOSTHTTPRequestInfo(uri, path, bodyFormat, bodyContent) + request.Headers = headers + return request +} + +func addHTTPAuthentication(request *http.Request, requestInfo HTTPRequestInfo) { + if len(requestInfo.Token) > 0 { + // Bearer authentication + request.Header.Add("Authorization", "Bearer "+requestInfo.Token) + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infinispan.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infinispan.go new file mode 100644 index 00000000000..3fb311bec4c --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infinispan.go @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/operator" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/meta" + + "gopkg.in/yaml.v2" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" + infinispan "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1" +) + +// DeployInfinispanInstance deploys an instance of Infinispan +func DeployInfinispanInstance(namespace string, infinispan *infinispan.Infinispan) error { + GetLogger(namespace).Info("Creating Infinispan instance", "name", infinispan.Name) + + if err := kubernetes.ResourceC(kubeClient).Create(infinispan); err != nil { + return fmt.Errorf("Error while creating Infinispan: %v ", err) + } + + return nil +} + +// CreateInfinispanSecret creates a new secret for Infinispan instance +func CreateInfinispanSecret(namespace, name string, credentialsMap map[string]string) error { + GetLogger(namespace).Info("Create Infinispan Secret %s", "name", name) + + credentialsFileData, err := convertInfinispanCredentialsToYaml(credentialsMap) + if err != nil { + return err + } + + return CreateSecret(namespace, name, map[string]string{infrastructure.InfinispanIdentityFileName: credentialsFileData}) +} + +// WaitForInfinispanPodsToBeRunningWithConfig waits for an Infinispan pod to be running with the expected configuration +func WaitForInfinispanPodsToBeRunningWithConfig(namespace string, expectedConfig infinispan.InfinispanContainerSpec, numberOfPods, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("Infinispan pod to be running with expected configuration: %+v", expectedConfig), timeoutInMin, + func() (bool, error) { + pods, err := GetPodsWithLabels(namespace, map[string]string{"app": "infinispan-pod"}) + if err != nil || len(pods.Items) != numberOfPods { + return false, err + } + + for _, pod := range pods.Items { + // First check that the pod is really running + if !IsPodStatusConditionReady(&pod) { + return false, nil + } + if !checkContainersResources(pod.Spec.Containers, getResourceRequirements(expectedConfig.CPU, expectedConfig.Memory)) { + return false, nil + } + if !checkPodContainerHasEnvVariableWithValue(&pod, "infinispan", "EXTRA_JAVA_OPTIONS", expectedConfig.ExtraJvmOpts) { + return false, nil + } + } + + return true, nil + }) + +} + +// SetInfinispanReplicas sets the number of replicas for an Infinispan instance +func SetInfinispanReplicas(namespace, name string, nbPods int) error { + GetLogger(namespace).Info("Set Infinispan props for", "name", name, "replica number", nbPods) + infinispan, err := getInfinispan(namespace, name) + if err != nil { + return err + } else if infinispan == nil { + return fmt.Errorf("No Infinispan found with name %s in namespace %s", name, namespace) + } + replicas := int32(nbPods) + infinispan.Spec.Replicas = replicas + return kubernetes.ResourceC(kubeClient).Update(infinispan) +} + +// GetInfinispanStub returns the preconfigured Infinispan stub with set namespace, name and secretName +func GetInfinispanStub(namespace, name, secretName string) *infinispan.Infinispan { + ispn := &infinispan.Infinispan{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + Spec: infinispan.InfinispanSpec{ + Replicas: 1, + Service: infinispan.InfinispanServiceSpec{ + Type: infinispan.ServiceTypeCache, + }, + }, + } + if storageClass := config.GetInfinispanStorageClass(); len(storageClass) > 0 { + if ispn.Spec.Service.Container == nil { + ispn.Spec.Service.Container = &infinispan.InfinispanServiceContainerSpec{} + } + ispn.Spec.Service.Container.StorageClassName = storageClass + } + + return ispn +} + +func convertInfinispanCredentialsToYaml(credentialsMap map[string]string) (string, error) { + var credentials []infrastructure.InfinispanCredential + for username, password := range credentialsMap { + credentials = append(credentials, infrastructure.InfinispanCredential{Username: username, Password: password}) + } + + identity := infrastructure.InfinispanIdentity{Credentials: credentials} + + data, err := yaml.Marshal(&identity) + if err != nil { + return "", err + } + return string(data), nil +} + +func getInfinispan(namespace, name string) (*infinispan.Infinispan, error) { + infinispan := &infinispan.Infinispan{} + if exists, err := kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: name, Namespace: namespace}, infinispan); err != nil && !errors.IsNotFound(err) { + return nil, fmt.Errorf("Error while trying to look for Infinispan %s: %v ", name, err) + } else if errors.IsNotFound(err) || !exists { + return nil, nil + } + return infinispan, nil +} + +// IsInfinispanAvailable checks if Infinispan CRD is available in the cluster +func IsInfinispanAvailable(namespace string) bool { + context := operator.Context{ + Client: kubeClient, + Log: GetLogger(namespace), + Scheme: meta.GetRegisteredSchema(), + } + return infrastructure.NewInfinispanHandler(context).IsInfinispanAvailable() +} + +// GetRunningInfinispanPodLabels returns the labels set to infinispan pod instances +func GetRunningInfinispanPodLabels(crName string) map[string]string { + return map[string]string{ + "app": "infinispan-pod", + "infinispan_cr": crName, + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/group.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/group.go new file mode 100644 index 00000000000..296b09f6085 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/group.go @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// Package grafana contains grafana API versions. +// +// This file ensures Go source parsers acknowledge the grafana package +// and any child packages. It can be removed if any other Go source files are +// added to this package. +package grafana diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/doc.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/doc.go new file mode 100644 index 00000000000..084828ada23 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/doc.go @@ -0,0 +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. + */ + +// Package v1alpha1 contains API Schema definitions for the integreatly v1alpha1 API group +// +k8s:deepcopy-gen=package,register +// +groupName=integreatly.org +package v1alpha1 diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/grafana_types.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/grafana_types.go new file mode 100644 index 00000000000..7cef7d83af1 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/grafana_types.go @@ -0,0 +1,641 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1alpha1 + +import ( + v12 "github.com/openshift/api/route/v1" + appsv1 "k8s.io/api/apps/v1" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// StatusPhase ... +type StatusPhase string + +var ( + // NoPhase ... + NoPhase StatusPhase + // PhaseReconciling ... + PhaseReconciling StatusPhase = "reconciling" + // PhaseFailing ... + PhaseFailing StatusPhase = "failing" +) + +// GrafanaSpec defines the desired state of Grafana +type GrafanaSpec struct { + Config GrafanaConfig `json:"config"` + Containers []v1.Container `json:"containers,omitempty"` + DashboardLabelSelector []*metav1.LabelSelector `json:"dashboardLabelSelector,omitempty"` + Ingress *GrafanaIngress `json:"ingress,omitempty"` + InitResources *v1.ResourceRequirements `json:"initResources,omitempty"` + Secrets []string `json:"secrets,omitempty"` + ConfigMaps []string `json:"configMaps,omitempty"` + Service *GrafanaService `json:"service,omitempty"` + Deployment *GrafanaDeployment `json:"deployment,omitempty"` + Resources *v1.ResourceRequirements `json:"resources,omitempty"` + ServiceAccount *GrafanaServiceAccount `json:"serviceAccount,omitempty"` + Client *GrafanaClient `json:"client,omitempty"` + DashboardNamespaceSelector *metav1.LabelSelector `json:"dashboardNamespaceSelector,omitempty"` + DataStorage *GrafanaDataStorage `json:"dataStorage,omitempty"` + Jsonnet *JsonnetConfig `json:"jsonnet,omitempty"` + BaseImage string `json:"baseImage,omitempty"` + InitImage string `json:"initImage,omitempty"` + LivenessProbeSpec *LivenessProbeSpec `json:"livenessProbeSpec,omitempty"` + ReadinessProbeSpec *ReadinessProbeSpec `json:"readinessProbeSpec,omitempty"` +} + +// ReadinessProbeSpec ... +type ReadinessProbeSpec struct { + InitialDelaySeconds int32 `json:"initialDelaySeconds,omitempty"` + TimeOutSeconds int32 `json:"timeoutSeconds,omitempty"` + PeriodSeconds int32 `json:"periodSeconds,omitempty"` + SuccessThreshold int32 `json:"successThreshold,omitempty"` + FailureThreshold int32 `json:"failureThreshold,omitempty"` +} + +// LivenessProbeSpec ... +type LivenessProbeSpec struct { + InitialDelaySeconds int32 `json:"initialDelaySeconds,omitempty"` + TimeOutSeconds int32 `json:"timeoutSeconds,omitempty"` + PeriodSeconds int32 `json:"periodSeconds,omitempty"` + SuccessThreshold int32 `json:"successThreshold,omitempty"` + FailureThreshold int32 `json:"failureThreshold,omitempty"` +} + +// JsonnetConfig ... +type JsonnetConfig struct { + LibraryLabelSelector *metav1.LabelSelector `json:"libraryLabelSelector,omitempty"` +} + +// GrafanaClient API client settings +type GrafanaClient struct { + TimeoutSeconds *int `json:"timeout,omitempty"` + PreferService bool `json:"preferService"` +} + +// GrafanaService provides a means to configure the service +type GrafanaService struct { + Name string `json:"name,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Type v1.ServiceType `json:"type,omitempty"` + Ports []v1.ServicePort `json:"ports,omitempty"` + ClusterIP string `json:"clusterIP,omitempty"` +} + +// GrafanaDataStorage provides a means to configure the grafana data storage +type GrafanaDataStorage struct { + Annotations map[string]string `json:"annotations,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + AccessModes []v1.PersistentVolumeAccessMode `json:"accessModes,omitempty"` + Size resource.Quantity `json:"size,omitempty"` + Class string `json:"class,omitempty"` +} + +// GrafanaServiceAccount ... +type GrafanaServiceAccount struct { + Skip *bool `json:"skip,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + ImagePullSecrets []v1.LocalObjectReference `json:"imagePullSecrets,omitempty"` +} + +// GrafanaDeployment provides a means to configure the deployment +type GrafanaDeployment struct { + Annotations map[string]string `json:"annotations,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Replicas *int32 `json:"replicas,omitempty"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + Tolerations []v1.Toleration `json:"tolerations,omitempty"` + Affinity *v1.Affinity `json:"affinity,omitempty"` + SecurityContext *v1.PodSecurityContext `json:"securityContext,omitempty"` + ContainerSecurityContext *v1.SecurityContext `json:"containerSecurityContext,omitempty"` + TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"` + EnvFrom []v1.EnvFromSource `json:"envFrom,omitempty"` + Env []v1.EnvVar `json:"env,omitempty"` + SkipCreateAdminAccount *bool `json:"skipCreateAdminAccount,omitempty"` + PriorityClassName string `json:"priorityClassName,omitempty"` + HostNetwork *bool `json:"hostNetwork,omitempty"` + ExtraVolumes []v1.Volume `json:"extraVolumes,omitempty"` + ExtraVolumeMounts []v1.VolumeMount `json:"extraVolumeMounts,omitempty"` + Strategy *appsv1.DeploymentStrategy `json:"strategy,omitempty"` + HTTPProxy *GrafanaHTTPProxy `json:"httpProxy,omitempty"` +} + +// GrafanaHTTPProxy provides a means to configure the Grafana deployment +// to use a HTTP(S) proxy when making requests and resolving plugins. +type GrafanaHTTPProxy struct { + Enabled bool `json:"enabled"` + URL string `json:"url,omitempty"` +} + +// GrafanaIngress provides a means to configure the ingress created +type GrafanaIngress struct { + Annotations map[string]string `json:"annotations,omitempty"` + Hostname string `json:"hostname,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Path string `json:"path,omitempty"` + Enabled bool `json:"enabled,omitempty"` + TLSEnabled bool `json:"tlsEnabled,omitempty"` + TLSSecretName string `json:"tlsSecretName,omitempty"` + TargetPort string `json:"targetPort,omitempty"` + Termination v12.TLSTerminationType `json:"termination,omitempty"` + IngressClassName string `json:"ingressClassName,omitempty"` + PathType string `json:"pathType,omitempty"` +} + +// GrafanaConfig is the configuration for grafana +type GrafanaConfig struct { + Paths *GrafanaConfigPaths `json:"paths,omitempty" ini:"paths,omitempty"` + Server *GrafanaConfigServer `json:"server,omitempty" ini:"server,omitempty"` + Database *GrafanaConfigDatabase `json:"database,omitempty" ini:"database,omitempty"` + RemoteCache *GrafanaConfigRemoteCache `json:"remote_cache,omitempty" ini:"remote_cache,omitempty"` + Security *GrafanaConfigSecurity `json:"security,omitempty" ini:"security,omitempty"` + Users *GrafanaConfigUsers `json:"users,omitempty" ini:"users,omitempty"` + Auth *GrafanaConfigAuth `json:"auth,omitempty" ini:"auth,omitempty"` + AuthBasic *GrafanaConfigAuthBasic `json:"auth.basic,omitempty" ini:"auth.basic,omitempty"` + AuthAnonymous *GrafanaConfigAuthAnonymous `json:"auth.anonymous,omitempty" ini:"auth.anonymous,omitempty"` + AuthAzureAD *GrafanaConfigAuthAzureAD `json:"auth.azuread,omitempty" ini:"auth.azuread,omitempty"` + AuthGoogle *GrafanaConfigAuthGoogle `json:"auth.google,omitempty" ini:"auth.google,omitempty"` + AuthGithub *GrafanaConfigAuthGithub `json:"auth.github,omitempty" ini:"auth.github,omitempty"` + AuthGitlab *GrafanaConfigAuthGitlab `json:"auth.gitlab,omitempty" ini:"auth.gitlab,omitempty"` + AuthGenericOauth *GrafanaConfigAuthGenericOauth `json:"auth.generic_oauth,omitempty" ini:"auth.generic_oauth,omitempty"` + AuthOkta *GrafanaConfigAuthOkta `json:"auth.okta,omitempty" ini:"auth.okta,omitempty"` + AuthLdap *GrafanaConfigAuthLdap `json:"auth.ldap,omitempty" ini:"auth.ldap,omitempty"` + AuthProxy *GrafanaConfigAuthProxy `json:"auth.proxy,omitempty" ini:"auth.proxy,omitempty"` + AuthSaml *GrafanaConfigAuthSaml `json:"auth.saml,omitempty" ini:"auth.saml,omitempty"` + DataProxy *GrafanaConfigDataProxy `json:"dataproxy,omitempty" ini:"dataproxy,omitempty"` + Analytics *GrafanaConfigAnalytics `json:"analytics,omitempty" ini:"analytics,omitempty"` + Dashboards *GrafanaConfigDashboards `json:"dashboards,omitempty" ini:"dashboards,omitempty"` + SMTP *GrafanaConfigSMTP `json:"smtp,omitempty" ini:"smtp,omitempty"` + Log *GrafanaConfigLog `json:"log,omitempty" ini:"log,omitempty"` + LogConsole *GrafanaConfigLogConsole `json:"log.console,omitempty" ini:"log.console,omitempty"` + LogFrontend *GrafanaConfigLogFrontend `json:"log.frontend,omitempty" ini:"log.frontend,omitempty"` + Metrics *GrafanaConfigMetrics `json:"metrics,omitempty" ini:"metrics,omitempty"` + MetricsGraphite *GrafanaConfigMetricsGraphite `json:"metrics.graphite,omitempty" ini:"metrics.graphite,omitempty"` + Snapshots *GrafanaConfigSnapshots `json:"snapshots,omitempty" ini:"snapshots,omitempty"` + ExternalImageStorage *GrafanaConfigExternalImageStorage `json:"external_image_storage,omitempty" ini:"external_image_storage,omitempty"` + ExternalImageStorageS3 *GrafanaConfigExternalImageStorageS3 `json:"external_image_storage.s3,omitempty" ini:"external_image_storage.s3,omitempty"` + ExternalImageStorageWebdav *GrafanaConfigExternalImageStorageWebdav `json:"external_image_storage.webdav,omitempty" ini:"external_image_storage.webdav,omitempty"` + ExternalImageStorageGcs *GrafanaConfigExternalImageStorageGcs `json:"external_image_storage.gcs,omitempty" ini:"external_image_storage.gcs,omitempty"` + ExternalImageStorageAzureBlob *GrafanaConfigExternalImageStorageAzureBlob `json:"external_image_storage.azure_blob,omitempty" ini:"external_image_storage.azure_blob,omitempty"` + Alerting *GrafanaConfigAlerting `json:"alerting,omitempty" ini:"alerting,omitempty"` + Panels *GrafanaConfigPanels `json:"panels,omitempty" ini:"panels,omitempty"` + Plugins *GrafanaConfigPlugins `json:"plugins,omitempty" ini:"plugins,omitempty"` + Rendering *GrafanaConfigRendering `json:"rendering,omitempty" ini:"rendering,omitempty"` + FeatureToggles *GrafanaConfigFeatureToggles `json:"feature_toggles,omitempty" ini:"feature_toggles,omitempty"` +} + +// GrafanaConfigPaths ... +type GrafanaConfigPaths struct { + TempDataLifetime string `json:"temp_data_lifetime,omitempty" ini:"temp_data_lifetime,omitempty"` +} + +// GrafanaConfigServer ... +type GrafanaConfigServer struct { + HTTPAddr string `json:"http_addr,omitempty" ini:"http_addr,omitempty"` + HTTPPort string `json:"http_port,omitempty" ini:"http_port,omitempty"` + Protocol string `json:"protocol,omitempty" ini:"protocol,omitempty"` + Socket string `json:"socket,omitempty" ini:"socket,omitempty"` + Domain string `json:"domain,omitempty" ini:"domain,omitempty"` + EnforceDomain *bool `json:"enforce_domain,omitempty" ini:"enforce_domain"` + RootURL string `json:"root_url,omitempty" ini:"root_url,omitempty"` + ServeFromSubPath *bool `json:"serve_from_sub_path,omitempty" ini:"serve_from_sub_path"` + StaticRootPath string `json:"static_root_path,omitempty" ini:"static_root_path,omitempty"` + EnableGzip *bool `json:"enable_gzip,omitempty" ini:"enable_gzip"` + CertFile string `json:"cert_file,omitempty" ini:"cert_file,omitempty"` + CertKey string `json:"cert_key,omitempty" ini:"cert_key,omitempty"` + RouterLogging *bool `json:"router_logging,omitempty" ini:"router_logging"` +} + +// GrafanaConfigDatabase ... +type GrafanaConfigDatabase struct { + URL string `json:"url,omitempty" ini:"url,omitempty"` + Type string `json:"type,omitempty" ini:"type,omitempty"` + Path string `json:"path,omitempty" ini:"path,omitempty"` + Host string `json:"host,omitempty" ini:"host,omitempty"` + Name string `json:"name,omitempty" ini:"name,omitempty"` + User string `json:"user,omitempty" ini:"user,omitempty"` + Password string `json:"password,omitempty" ini:"password,omitempty"` + SslMode string `json:"ssl_mode,omitempty" ini:"ssl_mode,omitempty"` + CaCertPath string `json:"ca_cert_path,omitempty" ini:"ca_cert_path,omitempty"` + ClientKeyPath string `json:"client_key_path,omitempty" ini:"client_key_path,omitempty"` + ClientCertPath string `json:"client_cert_path,omitempty" ini:"client_cert_path,omitempty"` + ServerCertName string `json:"server_cert_name,omitempty" ini:"server_cert_name,omitempty"` + MaxIdleConn *int `json:"max_idle_conn,omitempty" ini:"max_idle_conn,omitempty"` + MaxOpenConn *int `json:"max_open_conn,omitempty" ini:"max_open_conn,omitempty"` + ConnMaxLifetime *int `json:"conn_max_lifetime,omitempty" ini:"conn_max_lifetime,omitempty"` + LogQueries *bool `json:"log_queries,omitempty" ini:"log_queries"` + CacheMode string `json:"cache_mode,omitempty" ini:"cache_mode,omitempty"` +} + +// GrafanaConfigRemoteCache ... +type GrafanaConfigRemoteCache struct { + Type string `json:"type,omitempty" ini:"type,omitempty"` + ConnStr string `json:"connstr,omitempty" ini:"connstr,omitempty"` +} + +// GrafanaConfigSecurity ... +type GrafanaConfigSecurity struct { + AdminUser string `json:"admin_user,omitempty" ini:"admin_user,omitempty"` + AdminPassword string `json:"admin_password,omitempty" ini:"admin_password,omitempty"` + LoginRememberDays *int `json:"login_remember_days,omitempty" ini:"login_remember_days,omitempty"` + SecretKey string `json:"secret_key,omitempty" ini:"secret_key,omitempty"` + DisableGravatar *bool `json:"disable_gravatar,omitempty" ini:"disable_gravatar"` + DataSourceProxyWhitelist string `json:"data_source_proxy_whitelist,omitempty" ini:"data_source_proxy_whitelist,omitempty"` + CookieSecure *bool `json:"cookie_secure,omitempty" ini:"cookie_secure"` + CookieSamesite string `json:"cookie_samesite,omitempty" ini:"cookie_samesite,omitempty"` + AllowEmbedding *bool `json:"allow_embedding,omitempty" ini:"allow_embedding"` + StrictTransportSecurity *bool `json:"strict_transport_security,omitempty" ini:"strict_transport_security"` + StrictTransportSecurityMaxAgeSeconds *int `json:"strict_transport_security_max_age_seconds,omitempty" ini:"strict_transport_security_max_age_seconds,omitempty"` + StrictTransportSecurityPreload *bool `json:"strict_transport_security_preload,omitempty" ini:"strict_transport_security_preload"` + StrictTransportSecuritySubdomains *bool `json:"strict_transport_security_subdomains,omitempty" ini:"strict_transport_security_subdomains"` + XContentTypeOptions *bool `json:"x_content_type_options,omitempty" ini:"x_content_type_options"` + XXssProtection *bool `json:"x_xss_protection,omitempty" ini:"x_xss_protection"` +} + +// GrafanaConfigUsers ... +type GrafanaConfigUsers struct { + AllowSignUp *bool `json:"allow_sign_up,omitempty" ini:"allow_sign_up"` + AllowOrgCreate *bool `json:"allow_org_create,omitempty" ini:"allow_org_create"` + AutoAssignOrg *bool `json:"auto_assign_org,omitempty" ini:"auto_assign_org"` + AutoAssignOrgID string `json:"auto_assign_org_id,omitempty" ini:"auto_assign_org_id,omitempty"` + AutoAssignOrgRole string `json:"auto_assign_org_role,omitempty" ini:"auto_assign_org_role,omitempty"` + ViewersCanEdit *bool `json:"viewers_can_edit,omitempty" ini:"viewers_can_edit"` + EditorsCanAdmin *bool `json:"editors_can_admin,omitempty" ini:"editors_can_admin"` + LoginHint string `json:"login_hint,omitempty" ini:"login_hint,omitempty"` + PasswordHint string `json:"password_hint,omitempty" ini:"password_hint,omitempty"` + DefaultTheme string `json:"default_theme,omitempty" ini:"default_theme,omitempty"` +} + +// GrafanaConfigAuth ... +type GrafanaConfigAuth struct { + LoginCookieName string `json:"login_cookie_name,omitempty" ini:"login_cookie_name,omitempty"` + LoginMaximumInactiveLifetimeDays *int `json:"login_maximum_inactive_lifetime_days,omitempty" ini:"login_maximum_inactive_lifetime_days,omitempty"` + LoginMaximumInactiveLifetimeDuration string `json:"login_maximum_inactive_lifetime_duration,omitempty" ini:"login_maximum_inactive_lifetime_duration,omitempty"` + LoginMaximumLifetimeDays *int `json:"login_maximum_lifetime_days,omitempty" ini:"login_maximum_lifetime_days,omitempty"` + LoginMaximumLifetimeDuration string `json:"login_maximum_lifetime_duration,omitempty" ini:"login_maximum_lifetime_duration,omitempty"` + TokenRotationIntervalMinutes *int `json:"token_rotation_interval_minutes,omitempty" ini:"token_rotation_interval_minutes,omitempty"` + DisableLoginForm *bool `json:"disable_login_form,omitempty" ini:"disable_login_form"` + DisableSignoutMenu *bool `json:"disable_signout_menu,omitempty" ini:"disable_signout_menu"` + SigV4AuthEnabled *bool `json:"sigv4_auth_enabled,omitempty" ini:"sigv4_auth_enabled"` + SignoutRedirectURL string `json:"signout_redirect_url,omitempty" ini:"signout_redirect_url,omitempty"` + OauthAutoLogin *bool `json:"oauth_auto_login,omitempty" ini:"oauth_auto_login"` +} + +// GrafanaConfigAuthBasic ... +type GrafanaConfigAuthBasic struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` +} + +// GrafanaConfigAuthAnonymous ... +type GrafanaConfigAuthAnonymous struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` + OrgName string `json:"org_name,omitempty" ini:"org_name,omitempty"` + OrgRole string `json:"org_role,omitempty" ini:"org_role,omitempty"` +} + +// GrafanaConfigAuthSaml ... +type GrafanaConfigAuthSaml struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` + SingleLogout *bool `json:"single_logout,omitempty" ini:"single_logout,omitempty"` + AllowIdpInitiated *bool `json:"allow_idp_initiated,omitempty" ini:"allow_idp_initiated,omitempty"` + CertificatePath string `json:"certificate_path,omitempty" ini:"certificate_path"` + KeyPath string `json:"private_key_path,omitempty" ini:"private_key_path"` + SignatureAlgorithm string `json:"signature_algorithm,omitempty" ini:"signature_algorithm,omitempty"` + IdpURL string `json:"idp_metadata_url,omitempty" ini:"idp_metadata_url"` + MaxIssueDelay string `json:"max_issue_delay,omitempty" ini:"max_issue_delay,omitempty"` + MetadataValidDuration string `json:"metadata_valid_duration,omitempty" ini:"metadata_valid_duration,omitempty"` + RelayState string `json:"relay_state,omitempty" ini:"relay_state,omitempty"` + AssertionAttributeName string `json:"assertion_attribute_name,omitempty" ini:"assertion_attribute_name,omitempty"` + AssertionAttributeLogin string `json:"assertion_attribute_login,omitempty" ini:"assertion_attribute_login,omitempty"` + AssertionAttributeEmail string `json:"assertion_attribute_email,omitempty" ini:"assertion_attribute_email,omitempty"` + AssertionAttributeGroups string `json:"assertion_attribute_groups,omitempty" ini:"assertion_attribute_groups,omitempty"` + AssertionAttributeRole string `json:"assertion_attribute_role,omitempty" ini:"assertion_attribute_role,omitempty"` + AssertionAttributeOrg string `json:"assertion_attribute_org,omitempty" ini:"assertion_attribute_org,omitempty"` + AllowedOrganizations string `json:"allowed_organizations,omitempty" ini:"allowed_organizations,omitempty"` + OrgMapping string `json:"org_mapping,omitempty" ini:"org_mapping,omitempty"` + RoleValuesEditor string `json:"role_values_editor,omitempty" ini:"role_values_editor,omitempty"` + RoleValuesAdmin string `json:"role_values_admin,omitempty" ini:"role_values_admin,omitempty"` + RoleValuesGrafanaAdmin string `json:"role_values_grafana_admin,omitempty" ini:"role_values_grafana_admin,omitempty"` +} + +// GrafanaConfigAuthAzureAD ... +type GrafanaConfigAuthAzureAD struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` + AllowSignUp *bool `json:"allow_sign_up,omitempty" ini:"allow_sign_up"` + ClientID string `json:"client_id,omitempty" ini:"client_id,omitempty"` + ClientSecret string `json:"client_secret,omitempty" ini:"client_secret,omitempty"` + Scopes string `json:"scopes,omitempty" ini:"scopes,omitempty"` + AuthURL string `json:"auth_url,omitempty" ini:"auth_url,omitempty"` + TokenURL string `json:"token_url,omitempty" ini:"token_url,omitempty"` + AllowedDomains string `json:"allowed_domains,omitempty" ini:"allowed_domains,omitempty"` + AllowedGroups string `json:"allowed_groups,omitempty" ini:"allowed_groups,omitempty"` +} + +// GrafanaConfigAuthGoogle ... +type GrafanaConfigAuthGoogle struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` + ClientID string `json:"client_id,omitempty" ini:"client_id,omitempty"` + ClientSecret string `json:"client_secret,omitempty" ini:"client_secret,omitempty"` + Scopes string `json:"scopes,omitempty" ini:"scopes,omitempty"` + AuthURL string `json:"auth_url,omitempty" ini:"auth_url,omitempty"` + TokenURL string `json:"token_url,omitempty" ini:"token_url,omitempty"` + AllowedDomains string `json:"allowed_domains,omitempty" ini:"allowed_domains,omitempty"` + AllowSignUp *bool `json:"allow_sign_up,omitempty" ini:"allow_sign_up"` +} + +// GrafanaConfigAuthGithub ... +type GrafanaConfigAuthGithub struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` + AllowSignUp *bool `json:"allow_sign_up,omitempty" ini:"allow_sign_up"` + ClientID string `json:"client_id,omitempty" ini:"client_id,omitempty"` + ClientSecret string `json:"client_secret,omitempty" ini:"client_secret,omitempty"` + Scopes string `json:"scopes,omitempty" ini:"scopes,omitempty"` + AuthURL string `json:"auth_url,omitempty" ini:"auth_url,omitempty"` + TokenURL string `json:"token_url,omitempty" ini:"token_url,omitempty"` + APIURL string `json:"api_url,omitempty" ini:"api_url,omitempty"` + TeamIds string `json:"team_ids,omitempty" ini:"team_ids,omitempty"` + AllowedOrganizations string `json:"allowed_organizations,omitempty" ini:"allowed_organizations,omitempty"` +} + +// GrafanaConfigAuthGitlab ... +type GrafanaConfigAuthGitlab struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` + AllowSignUp *bool `json:"allow_sign_up,omitempty" ini:"allow_sign_up"` + ClientID string `json:"client_id,omitempty" ini:"client_id,omitempty"` + ClientSecret string `json:"client_secret,omitempty" ini:"client_secret,omitempty"` + Scopes string `json:"scopes,omitempty" ini:"scopes,omitempty"` + AuthURL string `json:"auth_url,omitempty" ini:"auth_url,omitempty"` + TokenURL string `json:"token_url,omitempty" ini:"token_url,omitempty"` + APIURL string `json:"api_url,omitempty" ini:"api_url,omitempty"` + AllowedGroups string `json:"allowed_groups,omitempty" ini:"allowed_groups,omitempty"` +} + +// GrafanaConfigAuthGenericOauth ... +type GrafanaConfigAuthGenericOauth struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` + AllowSignUp *bool `json:"allow_sign_up,omitempty" ini:"allow_sign_up"` + ClientID string `json:"client_id,omitempty" ini:"client_id,omitempty"` + ClientSecret string `json:"client_secret,omitempty" ini:"client_secret,omitempty"` + Scopes string `json:"scopes,omitempty" ini:"scopes,omitempty"` + AuthURL string `json:"auth_url,omitempty" ini:"auth_url,omitempty"` + TokenURL string `json:"token_url,omitempty" ini:"token_url,omitempty"` + APIURL string `json:"api_url,omitempty" ini:"api_url,omitempty"` + AllowedDomains string `json:"allowed_domains,omitempty" ini:"allowed_domains,omitempty"` + RoleAttributePath string `json:"role_attribute_path,omitempty" ini:"role_attribute_path,omitempty"` + RoleAttributeStrict *bool `json:"role_attribute_strict,omitempty" ini:"role_attribute_strict,omitempty"` + EmailAttributePath string `json:"email_attribute_path,omitempty" ini:"email_attribute_path,omitempty"` + TLSSkipVerifyInsecure *bool `json:"tls_skip_verify_insecure,omitempty" ini:"tls_skip_verify_insecure,omitempty"` + TLSClientCert string `json:"tls_client_cert,omitempty" ini:"tls_client_cert,omitempty"` + TLSClientKey string `json:"tls_client_key,omitempty" ini:"tls_client_key,omitempty"` + TLSClientCa string `json:"tls_client_ca,omitempty" ini:"tls_auth_ca,omitempty"` +} + +// GrafanaConfigAuthOkta ... +type GrafanaConfigAuthOkta struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` + Name string `json:"name,omitempty" ini:"name,omitempty"` + AllowSignUp *bool `json:"allow_sign_up,omitempty" ini:"allow_sign_up"` + ClientID string `json:"client_id,omitempty" ini:"client_id,omitempty"` + ClientSecret string `json:"client_secret,omitempty" ini:"client_secret,omitempty"` + Scopes string `json:"scopes,omitempty" ini:"scopes,omitempty"` + AuthURL string `json:"auth_url,omitempty" ini:"auth_url,omitempty"` + TokenURL string `json:"token_url,omitempty" ini:"token_url,omitempty"` + APIURL string `json:"api_url,omitempty" ini:"api_url,omitempty"` + AllowedDomains string `json:"allowed_domains,omitempty" ini:"allowed_domains,omitempty"` + AllowedGroups string `json:"allowed_groups,omitempty" ini:"allowed_groups,omitempty"` + RoleAttributePath string `json:"role_attribute_path,omitempty" ini:"role_attribute_path,omitempty"` + RoleAttributeStrict *bool `json:"role_attribute_strict,omitempty" ini:"role_attribute_strict,omitempty"` +} + +// GrafanaConfigAuthLdap ... +type GrafanaConfigAuthLdap struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` + AllowSignUp *bool `json:"allow_sign_up,omitempty" ini:"allow_sign_up"` + ConfigFile string `json:"config_file,omitempty" ini:"config_file,omitempty"` +} + +// GrafanaConfigAuthProxy ... +type GrafanaConfigAuthProxy struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` + HeaderName string `json:"header_name,omitempty" ini:"header_name,omitempty"` + HeaderProperty string `json:"header_property,omitempty" ini:"header_property,omitempty"` + AutoSignUp *bool `json:"auto_sign_up,omitempty" ini:"auto_sign_up"` + LdapSyncTTL string `json:"ldap_sync_ttl,omitempty" ini:"ldap_sync_ttl,omitempty"` + Whitelist string `json:"whitelist,omitempty" ini:"whitelist,omitempty"` + Headers string `json:"headers,omitempty" ini:"headers,omitempty"` + EnableLoginToken *bool `json:"enable_login_token,omitempty" ini:"enable_login_token"` +} + +// GrafanaConfigDataProxy ... +type GrafanaConfigDataProxy struct { + Logging *bool `json:"logging,omitempty" ini:"logging"` + Timeout *int `json:"timeout,omitempty" ini:"timeout,omitempty"` + SendUserHeader *bool `json:"send_user_header,omitempty" ini:"send_user_header,omitempty"` +} + +// GrafanaConfigAnalytics ... +type GrafanaConfigAnalytics struct { + ReportingEnabled *bool `json:"reporting_enabled,omitempty" ini:"reporting_enabled"` + GoogleAnalyticsUaID string `json:"google_analytics_ua_id,omitempty" ini:"google_analytics_ua_id,omitempty"` + CheckForUpdates *bool `json:"check_for_updates,omitempty" ini:"check_for_updates"` +} + +// GrafanaConfigDashboards ... +type GrafanaConfigDashboards struct { + VersionsToKeep *int `json:"versions_to_keep,omitempty" ini:"versions_to_keep,omitempty"` +} + +// GrafanaConfigSMTP ... +type GrafanaConfigSMTP struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` + Host string `json:"host,omitempty" ini:"host,omitempty"` + User string `json:"user,omitempty" ini:"user,omitempty"` + Password string `json:"password,omitempty" ini:"password,omitempty"` + CertFile string `json:"cert_file,omitempty" ini:"cert_file,omitempty"` + KeyFile string `json:"key_file,omitempty" ini:"key_file,omitempty"` + SkipVerify *bool `json:"skip_verify,omitempty" ini:"skip_verify"` + FromAddress string `json:"from_address,omitempty" ini:"from_address,omitempty"` + FromName string `json:"from_name,omitempty" ini:"from_name,omitempty"` + EhloIdentity string `json:"ehlo_identity,omitempty" ini:"ehlo_identity,omitempty"` +} + +// GrafanaConfigLog ... +type GrafanaConfigLog struct { + Mode string `json:"mode,omitempty" ini:"mode,omitempty"` + Level string `json:"level,omitempty" ini:"level,omitempty"` + Filters string `json:"filters,omitempty" ini:"filters,omitempty"` +} + +// GrafanaConfigLogFrontend ... +type GrafanaConfigLogFrontend struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled,omitempty"` + SentryDsn string `json:"sentry_dsn,omitempty" ini:"sentry_dsn,omitempty"` + CustomEndpoint string `json:"custom_endpoint,omitempty" ini:"custom_endpoint,omitempty"` + SampleRate string `json:"sample_rate,omitempty" ini:"sample_rate,omitempty"` + LogEndpointRequestsPerSecondLimit *int `json:"log_endpoint_requests_per_second_limit,omitempty" ini:"log_endpoint_requests_per_second_limit,omitempty"` + LogEndpointBurstLimit *int `json:"log_endpoint_burst_limit,omitempty" ini:"log_endpoint_burst_limit,omitempty"` +} + +// GrafanaConfigLogConsole ... +type GrafanaConfigLogConsole struct { + Level string `json:"level,omitempty" ini:"level,omitempty"` + Format string `json:"format,omitempty" ini:"format,omitempty"` +} + +// GrafanaConfigMetrics ... +type GrafanaConfigMetrics struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` + BasicAuthUsername string `json:"basic_auth_username,omitempty" ini:"basic_auth_username,omitempty"` + BasicAuthPassword string `json:"basic_auth_password,omitempty" ini:"basic_auth_password,omitempty"` + IntervalSeconds *int `json:"interval_seconds,omitempty" ini:"interval_seconds,omitempty"` +} + +// GrafanaConfigMetricsGraphite ... +type GrafanaConfigMetricsGraphite struct { + Address string `json:"address,omitempty" ini:"address,omitempty"` + Prefix string `json:"prefix,omitempty" ini:"prefix,omitempty"` +} + +// GrafanaConfigSnapshots ... +type GrafanaConfigSnapshots struct { + ExternalEnabled *bool `json:"external_enabled,omitempty" ini:"external_enabled"` + ExternalSnapshotURL string `json:"external_snapshot_url,omitempty" ini:"external_snapshot_url,omitempty"` + ExternalSnapshotName string `json:"external_snapshot_name,omitempty" ini:"external_snapshot_name,omitempty"` + SnapshotRemoveExpired *bool `json:"snapshot_remove_expired,omitempty" ini:"snapshot_remove_expired"` +} + +// GrafanaConfigExternalImageStorage ... +type GrafanaConfigExternalImageStorage struct { + Provider string `json:"provider,omitempty" ini:"provider,omitempty"` +} + +// GrafanaConfigExternalImageStorageS3 ... +type GrafanaConfigExternalImageStorageS3 struct { + Bucket string `json:"bucket,omitempty" ini:"bucket,omitempty"` + Region string `json:"region,omitempty" ini:"region,omitempty"` + Path string `json:"path,omitempty" ini:"path,omitempty"` + BucketURL string `json:"bucket_url,omitempty" ini:"bucket_url,omitempty"` + AccessKey string `json:"access_key,omitempty" ini:"access_key,omitempty"` + SecretKey string `json:"secret_key,omitempty" ini:"secret_key,omitempty"` +} + +// GrafanaConfigExternalImageStorageWebdav ... +type GrafanaConfigExternalImageStorageWebdav struct { + URL string `json:"url,omitempty" ini:"url,omitempty"` + PublicURL string `json:"public_url,omitempty" ini:"public_url,omitempty"` + Username string `json:"username,omitempty" ini:"username,omitempty"` + Password string `json:"password,omitempty" ini:"password,omitempty"` +} + +// GrafanaConfigExternalImageStorageGcs ... +type GrafanaConfigExternalImageStorageGcs struct { + KeyFile string `json:"key_file,omitempty" ini:"key_file,omitempty"` + Bucket string `json:"bucket,omitempty" ini:"bucket,omitempty"` + Path string `json:"path,omitempty" ini:"path,omitempty"` +} + +// GrafanaConfigExternalImageStorageAzureBlob ... +type GrafanaConfigExternalImageStorageAzureBlob struct { + AccountName string `json:"account_name,omitempty" ini:"account_name,omitempty"` + AccountKey string `json:"account_key,omitempty" ini:"account_key,omitempty"` + ContainerName string `json:"container_name,omitempty" ini:"container_name,omitempty"` +} + +// GrafanaConfigAlerting ... +type GrafanaConfigAlerting struct { + Enabled *bool `json:"enabled,omitempty" ini:"enabled"` + ExecuteAlerts *bool `json:"execute_alerts,omitempty" ini:"execute_alerts"` + ErrorOrTimeout string `json:"error_or_timeout,omitempty" ini:"error_or_timeout,omitempty"` + NodataOrNullvalues string `json:"nodata_or_nullvalues,omitempty" ini:"nodata_or_nullvalues,omitempty"` + ConcurrentRenderLimit *int `json:"concurrent_render_limit,omitempty" ini:"concurrent_render_limit,omitempty"` + EvaluationTimeoutSeconds *int `json:"evaluation_timeout_seconds,omitempty" ini:"evaluation_timeout_seconds,omitempty"` + NotificationTimeoutSeconds *int `json:"notification_timeout_seconds,omitempty" ini:"notification_timeout_seconds,omitempty"` + MaxAttempts *int `json:"max_attempts,omitempty" ini:"max_attempts,omitempty"` +} + +// GrafanaConfigPanels ... +type GrafanaConfigPanels struct { + DisableSanitizeHTML *bool `json:"disable_sanitize_html,omitempty" ini:"disable_sanitize_html"` +} + +// GrafanaConfigPlugins ... +type GrafanaConfigPlugins struct { + EnableAlpha *bool `json:"enable_alpha,omitempty" ini:"enable_alpha"` +} + +// GrafanaConfigRendering ... +type GrafanaConfigRendering struct { + ServerURL string `json:"server_url,omitempty" ini:"server_url"` + CallbackURL string `json:"callback_url,omitempty" ini:"callback_url"` + ConcurrentRenderRequestLimit *int `json:"concurrent_render_request_limit,omitempty" ini:"concurrent_render_request_limit,omitempty"` +} + +// GrafanaConfigFeatureToggles ... +type GrafanaConfigFeatureToggles struct { + Enable string `json:"enable,omitempty" ini:"enable,omitempty"` +} + +// GrafanaStatus defines the observed state of Grafana +type GrafanaStatus struct { + Phase StatusPhase `json:"phase,omitempty"` + PreviousServiceName string `json:"previousServiceName,omitempty"` + Message string `json:"message,omitempty"` + InstalledDashboards []*GrafanaDashboardRef `json:"dashboards,omitempty"` + InstalledPlugins PluginList `json:"installedPlugins,omitempty"` + FailedPlugins PluginList `json:"failedPlugins,omitempty"` +} + +// PluginList ... +type PluginList []GrafanaPlugin + +// GrafanaPlugin contains information about a single plugin +// +k8s:openapi-gen=true +type GrafanaPlugin struct { + // +kubebuilder:validation:Required + Name string `json:"name"` + // +kubebuilder:validation:Required + Version string `json:"version"` +} + +// Grafana is the Schema for the grafanas API +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +type Grafana struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec GrafanaSpec `json:"spec,omitempty"` + Status GrafanaStatus `json:"status,omitempty"` +} + +// GrafanaList contains a list of Grafana +// +kubebuilder:object:root=true +type GrafanaList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Grafana `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Grafana{}, &GrafanaList{}) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/grafanadashboard_types.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/grafanadashboard_types.go new file mode 100644 index 00000000000..cdd1547c20b --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/grafanadashboard_types.go @@ -0,0 +1,87 @@ +/* +Copyright 2021. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// 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. + +// GrafanaDashboardSpec defines the desired state of GrafanaDashboard +type GrafanaDashboardSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + JSON string `json:"json"` + Jsonnet string `json:"jsonnet,omitempty"` + Plugins PluginList `json:"plugins,omitempty"` + URL string `json:"url,omitempty"` + ConfigMapRef *corev1.ConfigMapKeySelector `json:"configMapRef,omitempty"` + Datasources []GrafanaDashboardDatasource `json:"datasources,omitempty"` + CustomFolderName string `json:"customFolderName,omitempty"` +} + +// GrafanaDashboardDatasource ... +type GrafanaDashboardDatasource struct { + InputName string `json:"inputName"` + DatasourceName string `json:"datasourceName"` +} + +// GrafanaDashboardRef Used to keep a dashboard reference without having access to the dashboard +// struct itself +type GrafanaDashboardRef struct { + Name string `json:"name"` + Namespace string `json:"namespace"` + UID string `json:"uid"` + Hash string `json:"hash"` + FolderID *int64 `json:"folderId"` + FolderName string `json:"folderName"` +} + +// GrafanaDashboardStatus ... +type GrafanaDashboardStatus struct { + // Empty +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status + +// GrafanaDashboard is the Schema for the grafanadashboards API +type GrafanaDashboard struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec GrafanaDashboardSpec `json:"spec,omitempty"` + Status GrafanaDashboardStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:object:root=true + +// GrafanaDashboardList contains a list of GrafanaDashboard +type GrafanaDashboardList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []GrafanaDashboard `json:"items"` +} + +func init() { + SchemeBuilder.Register(&GrafanaDashboard{}, &GrafanaDashboardList{}) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/grafanadatasource_types.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/grafanadatasource_types.go new file mode 100644 index 00000000000..4193c724458 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/grafanadatasource_types.go @@ -0,0 +1,204 @@ +/* +Copyright 2021. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + 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. + +// GrafanaDataSourceSpec defines the desired state of GrafanaDataSource +type GrafanaDataSourceSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + Datasources []GrafanaDataSourceFields `json:"datasources"` + Name string `json:"name"` +} + +// GrafanaDataSourceStatus defines the observed state of GrafanaDatasource +type GrafanaDataSourceStatus struct { + Phase StatusPhase `json:"phase"` + Message string `json:"message"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status + +// GrafanaDataSource is the Schema for the grafanadatasources API +type GrafanaDataSource struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec GrafanaDataSourceSpec `json:"spec,omitempty"` + Status GrafanaDataSourceStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// GrafanaDataSourceList contains a list of GrafanaDataSource +// +kubebuilder:object:root=true +type GrafanaDataSourceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []GrafanaDataSource `json:"items"` +} + +// GrafanaDataSourceFields ... +type GrafanaDataSourceFields struct { + Name string `json:"name"` + Type string `json:"type"` + UID string `json:"uid,omitempty"` + Access string `json:"access"` + OrgID int `json:"orgId,omitempty"` + URL string `json:"url"` + Password string `json:"password,omitempty"` + User string `json:"user,omitempty"` + Database string `json:"database,omitempty"` + BasicAuth bool `json:"basicAuth,omitempty"` + BasicAuthUser string `json:"basicAuthUser,omitempty"` + BasicAuthPassword string `json:"basicAuthPassword,omitempty"` + WithCredentials bool `json:"withCredentials,omitempty"` + IsDefault bool `json:"isDefault,omitempty"` + JSONData GrafanaDataSourceJSONData `json:"jsonData,omitempty"` + SecureJSONData GrafanaDataSourceSecureJSONData `json:"secureJsonData,omitempty"` + Version int `json:"version,omitempty"` + Editable bool `json:"editable,omitempty"` +} + +// GrafanaDataSourceJSONData The most common json options +// See https://grafana.com/docs/administration/provisioning/#datasources +type GrafanaDataSourceJSONData struct { + OauthPassThru bool `json:"oauthPassThru,omitempty"` + TLSAuth bool `json:"tlsAuth,omitempty"` + TLSAuthWithCACert bool `json:"tlsAuthWithCACert,omitempty"` + TLSSkipVerify bool `json:"tlsSkipVerify,omitempty"` + GraphiteVersion string `json:"graphiteVersion,omitempty"` + TimeInterval string `json:"timeInterval,omitempty"` + EsVersion int `json:"esVersion,omitempty"` + TimeField string `json:"timeField,omitempty"` + Interval string `json:"interval,omitempty"` + LogMessageField string `json:"logMessageField,omitempty"` + LogLevelField string `json:"logLevelField,omitempty"` + AuthType string `json:"authType,omitempty"` + AssumeRoleArn string `json:"assumeRoleArn,omitempty"` + DefaultRegion string `json:"defaultRegion,omitempty"` + CustomMetricsNamespaces string `json:"customMetricsNamespaces,omitempty"` + TsdbVersion string `json:"tsdbVersion,omitempty"` + TsdbResolution string `json:"tsdbResolution,omitempty"` + Sslmode string `json:"sslmode,omitempty"` + Encrypt string `json:"encrypt,omitempty"` + PostgresVersion int `json:"postgresVersion,omitempty"` + Timescaledb bool `json:"timescaledb,omitempty"` + MaxOpenConns int `json:"maxOpenConns,omitempty"` + MaxIdleConns int `json:"maxIdleConns,omitempty"` + ConnMaxLifetime int `json:"connMaxLifetime,omitempty"` + // Useful fields for clickhouse datasource + // See https://github.com/Vertamedia/clickhouse-grafana/tree/master/dist/README.md#configure-the-datasource-with-provisioning + // See https://github.com/Vertamedia/clickhouse-grafana/tree/master/src/datasource.ts#L44 + AddCorsHeader bool `json:"addCorsHeader,omitempty"` + DefaultDatabase string `json:"defaultDatabase,omitempty"` + UsePOST bool `json:"usePOST,omitempty"` + UseYandexCloudAuthorization bool `json:"useYandexCloudAuthorization,omitempty"` + XHeaderUser string `json:"xHeaderUser,omitempty"` + XHeaderKey string `json:"xHeaderKey,omitempty"` + // Custom HTTP headers for datasources + // See https://grafana.com/docs/grafana/latest/administration/provisioning/#datasources + HTTPHeaderName1 string `json:"httpHeaderName1,omitempty"` + HTTPHeaderName2 string `json:"httpHeaderName2,omitempty"` + HTTPHeaderName3 string `json:"httpHeaderName3,omitempty"` + HTTPHeaderName4 string `json:"httpHeaderName4,omitempty"` + HTTPHeaderName5 string `json:"httpHeaderName5,omitempty"` + HTTPHeaderName6 string `json:"httpHeaderName6,omitempty"` + HTTPHeaderName7 string `json:"httpHeaderName7,omitempty"` + HTTPHeaderName8 string `json:"httpHeaderName8,omitempty"` + HTTPHeaderName9 string `json:"httpHeaderName9,omitempty"` + // Fields for Stackdriver data sources + TokenURI string `json:"tokenUri,omitempty"` + ClientEmail string `json:"clientEmail,omitempty"` + AuthenticationType string `json:"authenticationType,omitempty"` + DefaultProject string `json:"defaultProject,omitempty"` + // Fields for Azure data sources + AppInsightsAppID string `json:"appInsightsAppId,omitempty"` + AzureLogAnalyticsSameAs string `json:"azureLogAnalyticsSameAs,omitempty"` + ClientID string `json:"clientId,omitempty"` + CloudName string `json:"cloudName,omitempty"` + LogAnalyticsDefaultWorkspace string `json:"logAnalyticsDefaultWorkspace,omitempty"` + LogAnalyticsClientID string `json:"logAnalyticsClientId,omitempty"` + LogAnalyticsSubscriptionID string `json:"logAnalyticsSubscriptionId,omitempty"` + LogAnalyticsTenantID string `json:"logAnalyticsTenantId,omitempty"` + SubscriptionID string `json:"subscriptionId,omitempty"` + TenantID string `json:"tenantId,omitempty"` + // Fields for InfluxDB data sources + HTTPMode string `json:"httpMode,omitempty"` + Version string `json:"version,omitempty"` + Organization string `json:"organization,omitempty"` + DefaultBucket string `json:"defaultBucket,omitempty"` + // Fields for Loki data sources + MaxLines int `json:"maxLines,omitempty"` + DerivedFields []GrafanaDataSourceJSONDerivedFields `json:"derivedFields,omitempty"` + // Fields for Prometheus data sources + CustomQueryParameters string `json:"customQueryParameters,omitempty"` + HTTPMethod string `json:"httpMethod,omitempty"` +} + +// GrafanaDataSourceJSONDerivedFields ... +type GrafanaDataSourceJSONDerivedFields struct { + DatasourceUID string `json:"datasourceUid,omitempty"` + MatcherRegex string `json:"matcherRegex,omitempty"` + Name string `json:"name,omitempty"` + URL string `json:"url,omitempty"` +} + +// GrafanaDataSourceSecureJSONData The most common secure json options +// See https://grafana.com/docs/administration/provisioning/#datasources +type GrafanaDataSourceSecureJSONData struct { + TLSCaCert string `json:"tlsCACert,omitempty"` + TLSClientCert string `json:"tlsClientCert,omitempty"` + TLSClientKey string `json:"tlsClientKey,omitempty"` + Password string `json:"password,omitempty"` + BasicAuthPassword string `json:"basicAuthPassword,omitempty"` + AccessKey string `json:"accessKey,omitempty"` + SecretKey string `json:"secretKey,omitempty"` + // Custom HTTP headers for datasources + // See https://grafana.com/docs/grafana/latest/administration/provisioning/#datasources + HTTPHeaderValue1 string `json:"httpHeaderValue1,omitempty"` + HTTPHeaderValue2 string `json:"httpHeaderValue2,omitempty"` + HTTPHeaderValue3 string `json:"httpHeaderValue3,omitempty"` + HTTPHeaderValue4 string `json:"httpHeaderValue4,omitempty"` + HTTPHeaderValue5 string `json:"httpHeaderValue5,omitempty"` + HTTPHeaderValue6 string `json:"httpHeaderValue6,omitempty"` + HTTPHeaderValue7 string `json:"httpHeaderValue7,omitempty"` + HTTPHeaderValue8 string `json:"httpHeaderValue8,omitempty"` + HTTPHeaderValue9 string `json:"httpHeaderValue9,omitempty"` + // Fields for Stackdriver data sources + PrivateKey string `json:"privateKey,omitempty"` + // Fields for Azure data sources + ClientSecret string `json:"clientSecret,omitempty"` + AppInsightsAPIKey string `json:"appInsightsApiKey,omitempty"` + LogAnalyticsClientSecret string `json:"logAnalyticsClientSecret,omitempty"` + // Fields for InfluxDB data sources + Token string `json:"token,omitempty"` +} + +func init() { + SchemeBuilder.Register(&GrafanaDataSource{}, &GrafanaDataSourceList{}) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/groupversion_info.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/groupversion_info.go new file mode 100644 index 00000000000..c632f8e6d6f --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/groupversion_info.go @@ -0,0 +1,37 @@ +/* +Copyright 2021. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1alpha1 contains API Schema definitions for the integreatly.org v1alpha1 API group +// +kubebuilder:skip +// +kubebuilder:object:generate=true +// +groupName=integreatly.org +package v1alpha1 + +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: "integreatly.org", Version: "v1alpha1"} + + // 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/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/zz_generated.deepcopy.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..16ea1ec9a10 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,2072 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright 2021 Red Hat, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + appsv1 "k8s.io/api/apps/v1" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Grafana) DeepCopyInto(out *Grafana) { + *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 Grafana. +func (in *Grafana) DeepCopy() *Grafana { + if in == nil { + return nil + } + out := new(Grafana) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Grafana) 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 *GrafanaClient) DeepCopyInto(out *GrafanaClient) { + *out = *in + if in.TimeoutSeconds != nil { + in, out := &in.TimeoutSeconds, &out.TimeoutSeconds + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaClient. +func (in *GrafanaClient) DeepCopy() *GrafanaClient { + if in == nil { + return nil + } + out := new(GrafanaClient) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfig) DeepCopyInto(out *GrafanaConfig) { + *out = *in + if in.Paths != nil { + in, out := &in.Paths, &out.Paths + *out = new(GrafanaConfigPaths) + **out = **in + } + if in.Server != nil { + in, out := &in.Server, &out.Server + *out = new(GrafanaConfigServer) + (*in).DeepCopyInto(*out) + } + if in.Database != nil { + in, out := &in.Database, &out.Database + *out = new(GrafanaConfigDatabase) + (*in).DeepCopyInto(*out) + } + if in.RemoteCache != nil { + in, out := &in.RemoteCache, &out.RemoteCache + *out = new(GrafanaConfigRemoteCache) + **out = **in + } + if in.Security != nil { + in, out := &in.Security, &out.Security + *out = new(GrafanaConfigSecurity) + (*in).DeepCopyInto(*out) + } + if in.Users != nil { + in, out := &in.Users, &out.Users + *out = new(GrafanaConfigUsers) + (*in).DeepCopyInto(*out) + } + if in.Auth != nil { + in, out := &in.Auth, &out.Auth + *out = new(GrafanaConfigAuth) + (*in).DeepCopyInto(*out) + } + if in.AuthBasic != nil { + in, out := &in.AuthBasic, &out.AuthBasic + *out = new(GrafanaConfigAuthBasic) + (*in).DeepCopyInto(*out) + } + if in.AuthAnonymous != nil { + in, out := &in.AuthAnonymous, &out.AuthAnonymous + *out = new(GrafanaConfigAuthAnonymous) + (*in).DeepCopyInto(*out) + } + if in.AuthAzureAD != nil { + in, out := &in.AuthAzureAD, &out.AuthAzureAD + *out = new(GrafanaConfigAuthAzureAD) + (*in).DeepCopyInto(*out) + } + if in.AuthGoogle != nil { + in, out := &in.AuthGoogle, &out.AuthGoogle + *out = new(GrafanaConfigAuthGoogle) + (*in).DeepCopyInto(*out) + } + if in.AuthGithub != nil { + in, out := &in.AuthGithub, &out.AuthGithub + *out = new(GrafanaConfigAuthGithub) + (*in).DeepCopyInto(*out) + } + if in.AuthGitlab != nil { + in, out := &in.AuthGitlab, &out.AuthGitlab + *out = new(GrafanaConfigAuthGitlab) + (*in).DeepCopyInto(*out) + } + if in.AuthGenericOauth != nil { + in, out := &in.AuthGenericOauth, &out.AuthGenericOauth + *out = new(GrafanaConfigAuthGenericOauth) + (*in).DeepCopyInto(*out) + } + if in.AuthOkta != nil { + in, out := &in.AuthOkta, &out.AuthOkta + *out = new(GrafanaConfigAuthOkta) + (*in).DeepCopyInto(*out) + } + if in.AuthLdap != nil { + in, out := &in.AuthLdap, &out.AuthLdap + *out = new(GrafanaConfigAuthLdap) + (*in).DeepCopyInto(*out) + } + if in.AuthProxy != nil { + in, out := &in.AuthProxy, &out.AuthProxy + *out = new(GrafanaConfigAuthProxy) + (*in).DeepCopyInto(*out) + } + if in.AuthSaml != nil { + in, out := &in.AuthSaml, &out.AuthSaml + *out = new(GrafanaConfigAuthSaml) + (*in).DeepCopyInto(*out) + } + if in.DataProxy != nil { + in, out := &in.DataProxy, &out.DataProxy + *out = new(GrafanaConfigDataProxy) + (*in).DeepCopyInto(*out) + } + if in.Analytics != nil { + in, out := &in.Analytics, &out.Analytics + *out = new(GrafanaConfigAnalytics) + (*in).DeepCopyInto(*out) + } + if in.Dashboards != nil { + in, out := &in.Dashboards, &out.Dashboards + *out = new(GrafanaConfigDashboards) + (*in).DeepCopyInto(*out) + } + if in.SMTP != nil { + in, out := &in.SMTP, &out.SMTP + *out = new(GrafanaConfigSMTP) + (*in).DeepCopyInto(*out) + } + if in.Log != nil { + in, out := &in.Log, &out.Log + *out = new(GrafanaConfigLog) + **out = **in + } + if in.LogConsole != nil { + in, out := &in.LogConsole, &out.LogConsole + *out = new(GrafanaConfigLogConsole) + **out = **in + } + if in.LogFrontend != nil { + in, out := &in.LogFrontend, &out.LogFrontend + *out = new(GrafanaConfigLogFrontend) + (*in).DeepCopyInto(*out) + } + if in.Metrics != nil { + in, out := &in.Metrics, &out.Metrics + *out = new(GrafanaConfigMetrics) + (*in).DeepCopyInto(*out) + } + if in.MetricsGraphite != nil { + in, out := &in.MetricsGraphite, &out.MetricsGraphite + *out = new(GrafanaConfigMetricsGraphite) + **out = **in + } + if in.Snapshots != nil { + in, out := &in.Snapshots, &out.Snapshots + *out = new(GrafanaConfigSnapshots) + (*in).DeepCopyInto(*out) + } + if in.ExternalImageStorage != nil { + in, out := &in.ExternalImageStorage, &out.ExternalImageStorage + *out = new(GrafanaConfigExternalImageStorage) + **out = **in + } + if in.ExternalImageStorageS3 != nil { + in, out := &in.ExternalImageStorageS3, &out.ExternalImageStorageS3 + *out = new(GrafanaConfigExternalImageStorageS3) + **out = **in + } + if in.ExternalImageStorageWebdav != nil { + in, out := &in.ExternalImageStorageWebdav, &out.ExternalImageStorageWebdav + *out = new(GrafanaConfigExternalImageStorageWebdav) + **out = **in + } + if in.ExternalImageStorageGcs != nil { + in, out := &in.ExternalImageStorageGcs, &out.ExternalImageStorageGcs + *out = new(GrafanaConfigExternalImageStorageGcs) + **out = **in + } + if in.ExternalImageStorageAzureBlob != nil { + in, out := &in.ExternalImageStorageAzureBlob, &out.ExternalImageStorageAzureBlob + *out = new(GrafanaConfigExternalImageStorageAzureBlob) + **out = **in + } + if in.Alerting != nil { + in, out := &in.Alerting, &out.Alerting + *out = new(GrafanaConfigAlerting) + (*in).DeepCopyInto(*out) + } + if in.Panels != nil { + in, out := &in.Panels, &out.Panels + *out = new(GrafanaConfigPanels) + (*in).DeepCopyInto(*out) + } + if in.Plugins != nil { + in, out := &in.Plugins, &out.Plugins + *out = new(GrafanaConfigPlugins) + (*in).DeepCopyInto(*out) + } + if in.Rendering != nil { + in, out := &in.Rendering, &out.Rendering + *out = new(GrafanaConfigRendering) + (*in).DeepCopyInto(*out) + } + if in.FeatureToggles != nil { + in, out := &in.FeatureToggles, &out.FeatureToggles + *out = new(GrafanaConfigFeatureToggles) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfig. +func (in *GrafanaConfig) DeepCopy() *GrafanaConfig { + if in == nil { + return nil + } + out := new(GrafanaConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAlerting) DeepCopyInto(out *GrafanaConfigAlerting) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.ExecuteAlerts != nil { + in, out := &in.ExecuteAlerts, &out.ExecuteAlerts + *out = new(bool) + **out = **in + } + if in.ConcurrentRenderLimit != nil { + in, out := &in.ConcurrentRenderLimit, &out.ConcurrentRenderLimit + *out = new(int) + **out = **in + } + if in.EvaluationTimeoutSeconds != nil { + in, out := &in.EvaluationTimeoutSeconds, &out.EvaluationTimeoutSeconds + *out = new(int) + **out = **in + } + if in.NotificationTimeoutSeconds != nil { + in, out := &in.NotificationTimeoutSeconds, &out.NotificationTimeoutSeconds + *out = new(int) + **out = **in + } + if in.MaxAttempts != nil { + in, out := &in.MaxAttempts, &out.MaxAttempts + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigAlerting. +func (in *GrafanaConfigAlerting) DeepCopy() *GrafanaConfigAlerting { + if in == nil { + return nil + } + out := new(GrafanaConfigAlerting) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAnalytics) DeepCopyInto(out *GrafanaConfigAnalytics) { + *out = *in + if in.ReportingEnabled != nil { + in, out := &in.ReportingEnabled, &out.ReportingEnabled + *out = new(bool) + **out = **in + } + if in.CheckForUpdates != nil { + in, out := &in.CheckForUpdates, &out.CheckForUpdates + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigAnalytics. +func (in *GrafanaConfigAnalytics) DeepCopy() *GrafanaConfigAnalytics { + if in == nil { + return nil + } + out := new(GrafanaConfigAnalytics) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAuth) DeepCopyInto(out *GrafanaConfigAuth) { + *out = *in + if in.LoginMaximumInactiveLifetimeDays != nil { + in, out := &in.LoginMaximumInactiveLifetimeDays, &out.LoginMaximumInactiveLifetimeDays + *out = new(int) + **out = **in + } + if in.LoginMaximumLifetimeDays != nil { + in, out := &in.LoginMaximumLifetimeDays, &out.LoginMaximumLifetimeDays + *out = new(int) + **out = **in + } + if in.TokenRotationIntervalMinutes != nil { + in, out := &in.TokenRotationIntervalMinutes, &out.TokenRotationIntervalMinutes + *out = new(int) + **out = **in + } + if in.DisableLoginForm != nil { + in, out := &in.DisableLoginForm, &out.DisableLoginForm + *out = new(bool) + **out = **in + } + if in.DisableSignoutMenu != nil { + in, out := &in.DisableSignoutMenu, &out.DisableSignoutMenu + *out = new(bool) + **out = **in + } + if in.SigV4AuthEnabled != nil { + in, out := &in.SigV4AuthEnabled, &out.SigV4AuthEnabled + *out = new(bool) + **out = **in + } + if in.OauthAutoLogin != nil { + in, out := &in.OauthAutoLogin, &out.OauthAutoLogin + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigAuth. +func (in *GrafanaConfigAuth) DeepCopy() *GrafanaConfigAuth { + if in == nil { + return nil + } + out := new(GrafanaConfigAuth) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAuthAnonymous) DeepCopyInto(out *GrafanaConfigAuthAnonymous) { + *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 GrafanaConfigAuthAnonymous. +func (in *GrafanaConfigAuthAnonymous) DeepCopy() *GrafanaConfigAuthAnonymous { + if in == nil { + return nil + } + out := new(GrafanaConfigAuthAnonymous) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAuthAzureAD) DeepCopyInto(out *GrafanaConfigAuthAzureAD) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.AllowSignUp != nil { + in, out := &in.AllowSignUp, &out.AllowSignUp + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigAuthAzureAD. +func (in *GrafanaConfigAuthAzureAD) DeepCopy() *GrafanaConfigAuthAzureAD { + if in == nil { + return nil + } + out := new(GrafanaConfigAuthAzureAD) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAuthBasic) DeepCopyInto(out *GrafanaConfigAuthBasic) { + *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 GrafanaConfigAuthBasic. +func (in *GrafanaConfigAuthBasic) DeepCopy() *GrafanaConfigAuthBasic { + if in == nil { + return nil + } + out := new(GrafanaConfigAuthBasic) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAuthGenericOauth) DeepCopyInto(out *GrafanaConfigAuthGenericOauth) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.AllowSignUp != nil { + in, out := &in.AllowSignUp, &out.AllowSignUp + *out = new(bool) + **out = **in + } + if in.RoleAttributeStrict != nil { + in, out := &in.RoleAttributeStrict, &out.RoleAttributeStrict + *out = new(bool) + **out = **in + } + if in.TLSSkipVerifyInsecure != nil { + in, out := &in.TLSSkipVerifyInsecure, &out.TLSSkipVerifyInsecure + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigAuthGenericOauth. +func (in *GrafanaConfigAuthGenericOauth) DeepCopy() *GrafanaConfigAuthGenericOauth { + if in == nil { + return nil + } + out := new(GrafanaConfigAuthGenericOauth) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAuthGithub) DeepCopyInto(out *GrafanaConfigAuthGithub) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.AllowSignUp != nil { + in, out := &in.AllowSignUp, &out.AllowSignUp + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigAuthGithub. +func (in *GrafanaConfigAuthGithub) DeepCopy() *GrafanaConfigAuthGithub { + if in == nil { + return nil + } + out := new(GrafanaConfigAuthGithub) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAuthGitlab) DeepCopyInto(out *GrafanaConfigAuthGitlab) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.AllowSignUp != nil { + in, out := &in.AllowSignUp, &out.AllowSignUp + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigAuthGitlab. +func (in *GrafanaConfigAuthGitlab) DeepCopy() *GrafanaConfigAuthGitlab { + if in == nil { + return nil + } + out := new(GrafanaConfigAuthGitlab) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAuthGoogle) DeepCopyInto(out *GrafanaConfigAuthGoogle) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.AllowSignUp != nil { + in, out := &in.AllowSignUp, &out.AllowSignUp + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigAuthGoogle. +func (in *GrafanaConfigAuthGoogle) DeepCopy() *GrafanaConfigAuthGoogle { + if in == nil { + return nil + } + out := new(GrafanaConfigAuthGoogle) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAuthLdap) DeepCopyInto(out *GrafanaConfigAuthLdap) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.AllowSignUp != nil { + in, out := &in.AllowSignUp, &out.AllowSignUp + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigAuthLdap. +func (in *GrafanaConfigAuthLdap) DeepCopy() *GrafanaConfigAuthLdap { + if in == nil { + return nil + } + out := new(GrafanaConfigAuthLdap) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAuthOkta) DeepCopyInto(out *GrafanaConfigAuthOkta) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.AllowSignUp != nil { + in, out := &in.AllowSignUp, &out.AllowSignUp + *out = new(bool) + **out = **in + } + if in.RoleAttributeStrict != nil { + in, out := &in.RoleAttributeStrict, &out.RoleAttributeStrict + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigAuthOkta. +func (in *GrafanaConfigAuthOkta) DeepCopy() *GrafanaConfigAuthOkta { + if in == nil { + return nil + } + out := new(GrafanaConfigAuthOkta) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAuthProxy) DeepCopyInto(out *GrafanaConfigAuthProxy) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.AutoSignUp != nil { + in, out := &in.AutoSignUp, &out.AutoSignUp + *out = new(bool) + **out = **in + } + if in.EnableLoginToken != nil { + in, out := &in.EnableLoginToken, &out.EnableLoginToken + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigAuthProxy. +func (in *GrafanaConfigAuthProxy) DeepCopy() *GrafanaConfigAuthProxy { + if in == nil { + return nil + } + out := new(GrafanaConfigAuthProxy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigAuthSaml) DeepCopyInto(out *GrafanaConfigAuthSaml) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.SingleLogout != nil { + in, out := &in.SingleLogout, &out.SingleLogout + *out = new(bool) + **out = **in + } + if in.AllowIdpInitiated != nil { + in, out := &in.AllowIdpInitiated, &out.AllowIdpInitiated + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigAuthSaml. +func (in *GrafanaConfigAuthSaml) DeepCopy() *GrafanaConfigAuthSaml { + if in == nil { + return nil + } + out := new(GrafanaConfigAuthSaml) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigDashboards) DeepCopyInto(out *GrafanaConfigDashboards) { + *out = *in + if in.VersionsToKeep != nil { + in, out := &in.VersionsToKeep, &out.VersionsToKeep + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigDashboards. +func (in *GrafanaConfigDashboards) DeepCopy() *GrafanaConfigDashboards { + if in == nil { + return nil + } + out := new(GrafanaConfigDashboards) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigDataProxy) DeepCopyInto(out *GrafanaConfigDataProxy) { + *out = *in + if in.Logging != nil { + in, out := &in.Logging, &out.Logging + *out = new(bool) + **out = **in + } + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(int) + **out = **in + } + if in.SendUserHeader != nil { + in, out := &in.SendUserHeader, &out.SendUserHeader + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigDataProxy. +func (in *GrafanaConfigDataProxy) DeepCopy() *GrafanaConfigDataProxy { + if in == nil { + return nil + } + out := new(GrafanaConfigDataProxy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigDatabase) DeepCopyInto(out *GrafanaConfigDatabase) { + *out = *in + if in.MaxIdleConn != nil { + in, out := &in.MaxIdleConn, &out.MaxIdleConn + *out = new(int) + **out = **in + } + if in.MaxOpenConn != nil { + in, out := &in.MaxOpenConn, &out.MaxOpenConn + *out = new(int) + **out = **in + } + if in.ConnMaxLifetime != nil { + in, out := &in.ConnMaxLifetime, &out.ConnMaxLifetime + *out = new(int) + **out = **in + } + if in.LogQueries != nil { + in, out := &in.LogQueries, &out.LogQueries + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigDatabase. +func (in *GrafanaConfigDatabase) DeepCopy() *GrafanaConfigDatabase { + if in == nil { + return nil + } + out := new(GrafanaConfigDatabase) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigExternalImageStorage) DeepCopyInto(out *GrafanaConfigExternalImageStorage) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigExternalImageStorage. +func (in *GrafanaConfigExternalImageStorage) DeepCopy() *GrafanaConfigExternalImageStorage { + if in == nil { + return nil + } + out := new(GrafanaConfigExternalImageStorage) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigExternalImageStorageAzureBlob) DeepCopyInto(out *GrafanaConfigExternalImageStorageAzureBlob) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigExternalImageStorageAzureBlob. +func (in *GrafanaConfigExternalImageStorageAzureBlob) DeepCopy() *GrafanaConfigExternalImageStorageAzureBlob { + if in == nil { + return nil + } + out := new(GrafanaConfigExternalImageStorageAzureBlob) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigExternalImageStorageGcs) DeepCopyInto(out *GrafanaConfigExternalImageStorageGcs) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigExternalImageStorageGcs. +func (in *GrafanaConfigExternalImageStorageGcs) DeepCopy() *GrafanaConfigExternalImageStorageGcs { + if in == nil { + return nil + } + out := new(GrafanaConfigExternalImageStorageGcs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigExternalImageStorageS3) DeepCopyInto(out *GrafanaConfigExternalImageStorageS3) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigExternalImageStorageS3. +func (in *GrafanaConfigExternalImageStorageS3) DeepCopy() *GrafanaConfigExternalImageStorageS3 { + if in == nil { + return nil + } + out := new(GrafanaConfigExternalImageStorageS3) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigExternalImageStorageWebdav) DeepCopyInto(out *GrafanaConfigExternalImageStorageWebdav) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigExternalImageStorageWebdav. +func (in *GrafanaConfigExternalImageStorageWebdav) DeepCopy() *GrafanaConfigExternalImageStorageWebdav { + if in == nil { + return nil + } + out := new(GrafanaConfigExternalImageStorageWebdav) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigFeatureToggles) DeepCopyInto(out *GrafanaConfigFeatureToggles) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigFeatureToggles. +func (in *GrafanaConfigFeatureToggles) DeepCopy() *GrafanaConfigFeatureToggles { + if in == nil { + return nil + } + out := new(GrafanaConfigFeatureToggles) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigLog) DeepCopyInto(out *GrafanaConfigLog) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigLog. +func (in *GrafanaConfigLog) DeepCopy() *GrafanaConfigLog { + if in == nil { + return nil + } + out := new(GrafanaConfigLog) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigLogConsole) DeepCopyInto(out *GrafanaConfigLogConsole) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigLogConsole. +func (in *GrafanaConfigLogConsole) DeepCopy() *GrafanaConfigLogConsole { + if in == nil { + return nil + } + out := new(GrafanaConfigLogConsole) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigLogFrontend) DeepCopyInto(out *GrafanaConfigLogFrontend) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.LogEndpointRequestsPerSecondLimit != nil { + in, out := &in.LogEndpointRequestsPerSecondLimit, &out.LogEndpointRequestsPerSecondLimit + *out = new(int) + **out = **in + } + if in.LogEndpointBurstLimit != nil { + in, out := &in.LogEndpointBurstLimit, &out.LogEndpointBurstLimit + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigLogFrontend. +func (in *GrafanaConfigLogFrontend) DeepCopy() *GrafanaConfigLogFrontend { + if in == nil { + return nil + } + out := new(GrafanaConfigLogFrontend) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigMetrics) DeepCopyInto(out *GrafanaConfigMetrics) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.IntervalSeconds != nil { + in, out := &in.IntervalSeconds, &out.IntervalSeconds + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigMetrics. +func (in *GrafanaConfigMetrics) DeepCopy() *GrafanaConfigMetrics { + if in == nil { + return nil + } + out := new(GrafanaConfigMetrics) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigMetricsGraphite) DeepCopyInto(out *GrafanaConfigMetricsGraphite) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigMetricsGraphite. +func (in *GrafanaConfigMetricsGraphite) DeepCopy() *GrafanaConfigMetricsGraphite { + if in == nil { + return nil + } + out := new(GrafanaConfigMetricsGraphite) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigPanels) DeepCopyInto(out *GrafanaConfigPanels) { + *out = *in + if in.DisableSanitizeHTML != nil { + in, out := &in.DisableSanitizeHTML, &out.DisableSanitizeHTML + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigPanels. +func (in *GrafanaConfigPanels) DeepCopy() *GrafanaConfigPanels { + if in == nil { + return nil + } + out := new(GrafanaConfigPanels) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigPaths) DeepCopyInto(out *GrafanaConfigPaths) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigPaths. +func (in *GrafanaConfigPaths) DeepCopy() *GrafanaConfigPaths { + if in == nil { + return nil + } + out := new(GrafanaConfigPaths) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigPlugins) DeepCopyInto(out *GrafanaConfigPlugins) { + *out = *in + if in.EnableAlpha != nil { + in, out := &in.EnableAlpha, &out.EnableAlpha + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigPlugins. +func (in *GrafanaConfigPlugins) DeepCopy() *GrafanaConfigPlugins { + if in == nil { + return nil + } + out := new(GrafanaConfigPlugins) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigRemoteCache) DeepCopyInto(out *GrafanaConfigRemoteCache) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigRemoteCache. +func (in *GrafanaConfigRemoteCache) DeepCopy() *GrafanaConfigRemoteCache { + if in == nil { + return nil + } + out := new(GrafanaConfigRemoteCache) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigRendering) DeepCopyInto(out *GrafanaConfigRendering) { + *out = *in + if in.ConcurrentRenderRequestLimit != nil { + in, out := &in.ConcurrentRenderRequestLimit, &out.ConcurrentRenderRequestLimit + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigRendering. +func (in *GrafanaConfigRendering) DeepCopy() *GrafanaConfigRendering { + if in == nil { + return nil + } + out := new(GrafanaConfigRendering) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigSMTP) DeepCopyInto(out *GrafanaConfigSMTP) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.SkipVerify != nil { + in, out := &in.SkipVerify, &out.SkipVerify + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigSMTP. +func (in *GrafanaConfigSMTP) DeepCopy() *GrafanaConfigSMTP { + if in == nil { + return nil + } + out := new(GrafanaConfigSMTP) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigSecurity) DeepCopyInto(out *GrafanaConfigSecurity) { + *out = *in + if in.LoginRememberDays != nil { + in, out := &in.LoginRememberDays, &out.LoginRememberDays + *out = new(int) + **out = **in + } + if in.DisableGravatar != nil { + in, out := &in.DisableGravatar, &out.DisableGravatar + *out = new(bool) + **out = **in + } + if in.CookieSecure != nil { + in, out := &in.CookieSecure, &out.CookieSecure + *out = new(bool) + **out = **in + } + if in.AllowEmbedding != nil { + in, out := &in.AllowEmbedding, &out.AllowEmbedding + *out = new(bool) + **out = **in + } + if in.StrictTransportSecurity != nil { + in, out := &in.StrictTransportSecurity, &out.StrictTransportSecurity + *out = new(bool) + **out = **in + } + if in.StrictTransportSecurityMaxAgeSeconds != nil { + in, out := &in.StrictTransportSecurityMaxAgeSeconds, &out.StrictTransportSecurityMaxAgeSeconds + *out = new(int) + **out = **in + } + if in.StrictTransportSecurityPreload != nil { + in, out := &in.StrictTransportSecurityPreload, &out.StrictTransportSecurityPreload + *out = new(bool) + **out = **in + } + if in.StrictTransportSecuritySubdomains != nil { + in, out := &in.StrictTransportSecuritySubdomains, &out.StrictTransportSecuritySubdomains + *out = new(bool) + **out = **in + } + if in.XContentTypeOptions != nil { + in, out := &in.XContentTypeOptions, &out.XContentTypeOptions + *out = new(bool) + **out = **in + } + if in.XXssProtection != nil { + in, out := &in.XXssProtection, &out.XXssProtection + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigSecurity. +func (in *GrafanaConfigSecurity) DeepCopy() *GrafanaConfigSecurity { + if in == nil { + return nil + } + out := new(GrafanaConfigSecurity) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigServer) DeepCopyInto(out *GrafanaConfigServer) { + *out = *in + if in.EnforceDomain != nil { + in, out := &in.EnforceDomain, &out.EnforceDomain + *out = new(bool) + **out = **in + } + if in.ServeFromSubPath != nil { + in, out := &in.ServeFromSubPath, &out.ServeFromSubPath + *out = new(bool) + **out = **in + } + if in.EnableGzip != nil { + in, out := &in.EnableGzip, &out.EnableGzip + *out = new(bool) + **out = **in + } + if in.RouterLogging != nil { + in, out := &in.RouterLogging, &out.RouterLogging + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigServer. +func (in *GrafanaConfigServer) DeepCopy() *GrafanaConfigServer { + if in == nil { + return nil + } + out := new(GrafanaConfigServer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigSnapshots) DeepCopyInto(out *GrafanaConfigSnapshots) { + *out = *in + if in.ExternalEnabled != nil { + in, out := &in.ExternalEnabled, &out.ExternalEnabled + *out = new(bool) + **out = **in + } + if in.SnapshotRemoveExpired != nil { + in, out := &in.SnapshotRemoveExpired, &out.SnapshotRemoveExpired + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigSnapshots. +func (in *GrafanaConfigSnapshots) DeepCopy() *GrafanaConfigSnapshots { + if in == nil { + return nil + } + out := new(GrafanaConfigSnapshots) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfigUsers) DeepCopyInto(out *GrafanaConfigUsers) { + *out = *in + if in.AllowSignUp != nil { + in, out := &in.AllowSignUp, &out.AllowSignUp + *out = new(bool) + **out = **in + } + if in.AllowOrgCreate != nil { + in, out := &in.AllowOrgCreate, &out.AllowOrgCreate + *out = new(bool) + **out = **in + } + if in.AutoAssignOrg != nil { + in, out := &in.AutoAssignOrg, &out.AutoAssignOrg + *out = new(bool) + **out = **in + } + if in.ViewersCanEdit != nil { + in, out := &in.ViewersCanEdit, &out.ViewersCanEdit + *out = new(bool) + **out = **in + } + if in.EditorsCanAdmin != nil { + in, out := &in.EditorsCanAdmin, &out.EditorsCanAdmin + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfigUsers. +func (in *GrafanaConfigUsers) DeepCopy() *GrafanaConfigUsers { + if in == nil { + return nil + } + out := new(GrafanaConfigUsers) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaDashboard) DeepCopyInto(out *GrafanaDashboard) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDashboard. +func (in *GrafanaDashboard) DeepCopy() *GrafanaDashboard { + if in == nil { + return nil + } + out := new(GrafanaDashboard) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GrafanaDashboard) 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 *GrafanaDashboardDatasource) DeepCopyInto(out *GrafanaDashboardDatasource) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDashboardDatasource. +func (in *GrafanaDashboardDatasource) DeepCopy() *GrafanaDashboardDatasource { + if in == nil { + return nil + } + out := new(GrafanaDashboardDatasource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaDashboardList) DeepCopyInto(out *GrafanaDashboardList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]GrafanaDashboard, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDashboardList. +func (in *GrafanaDashboardList) DeepCopy() *GrafanaDashboardList { + if in == nil { + return nil + } + out := new(GrafanaDashboardList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GrafanaDashboardList) 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 *GrafanaDashboardRef) DeepCopyInto(out *GrafanaDashboardRef) { + *out = *in + if in.FolderID != nil { + in, out := &in.FolderID, &out.FolderID + *out = new(int64) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDashboardRef. +func (in *GrafanaDashboardRef) DeepCopy() *GrafanaDashboardRef { + if in == nil { + return nil + } + out := new(GrafanaDashboardRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaDashboardSpec) DeepCopyInto(out *GrafanaDashboardSpec) { + *out = *in + if in.Plugins != nil { + in, out := &in.Plugins, &out.Plugins + *out = make(PluginList, len(*in)) + copy(*out, *in) + } + if in.ConfigMapRef != nil { + in, out := &in.ConfigMapRef, &out.ConfigMapRef + *out = new(v1.ConfigMapKeySelector) + (*in).DeepCopyInto(*out) + } + if in.Datasources != nil { + in, out := &in.Datasources, &out.Datasources + *out = make([]GrafanaDashboardDatasource, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDashboardSpec. +func (in *GrafanaDashboardSpec) DeepCopy() *GrafanaDashboardSpec { + if in == nil { + return nil + } + out := new(GrafanaDashboardSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaDashboardStatus) DeepCopyInto(out *GrafanaDashboardStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDashboardStatus. +func (in *GrafanaDashboardStatus) DeepCopy() *GrafanaDashboardStatus { + if in == nil { + return nil + } + out := new(GrafanaDashboardStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaDataSource) DeepCopyInto(out *GrafanaDataSource) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataSource. +func (in *GrafanaDataSource) DeepCopy() *GrafanaDataSource { + if in == nil { + return nil + } + out := new(GrafanaDataSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GrafanaDataSource) 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 *GrafanaDataSourceFields) DeepCopyInto(out *GrafanaDataSourceFields) { + *out = *in + in.JSONData.DeepCopyInto(&out.JSONData) + out.SecureJSONData = in.SecureJSONData +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataSourceFields. +func (in *GrafanaDataSourceFields) DeepCopy() *GrafanaDataSourceFields { + if in == nil { + return nil + } + out := new(GrafanaDataSourceFields) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaDataSourceJSONData) DeepCopyInto(out *GrafanaDataSourceJSONData) { + *out = *in + if in.DerivedFields != nil { + in, out := &in.DerivedFields, &out.DerivedFields + *out = make([]GrafanaDataSourceJSONDerivedFields, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataSourceJSONData. +func (in *GrafanaDataSourceJSONData) DeepCopy() *GrafanaDataSourceJSONData { + if in == nil { + return nil + } + out := new(GrafanaDataSourceJSONData) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaDataSourceJSONDerivedFields) DeepCopyInto(out *GrafanaDataSourceJSONDerivedFields) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataSourceJSONDerivedFields. +func (in *GrafanaDataSourceJSONDerivedFields) DeepCopy() *GrafanaDataSourceJSONDerivedFields { + if in == nil { + return nil + } + out := new(GrafanaDataSourceJSONDerivedFields) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaDataSourceList) DeepCopyInto(out *GrafanaDataSourceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]GrafanaDataSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataSourceList. +func (in *GrafanaDataSourceList) DeepCopy() *GrafanaDataSourceList { + if in == nil { + return nil + } + out := new(GrafanaDataSourceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GrafanaDataSourceList) 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 *GrafanaDataSourceSecureJSONData) DeepCopyInto(out *GrafanaDataSourceSecureJSONData) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataSourceSecureJSONData. +func (in *GrafanaDataSourceSecureJSONData) DeepCopy() *GrafanaDataSourceSecureJSONData { + if in == nil { + return nil + } + out := new(GrafanaDataSourceSecureJSONData) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaDataSourceSpec) DeepCopyInto(out *GrafanaDataSourceSpec) { + *out = *in + if in.Datasources != nil { + in, out := &in.Datasources, &out.Datasources + *out = make([]GrafanaDataSourceFields, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataSourceSpec. +func (in *GrafanaDataSourceSpec) DeepCopy() *GrafanaDataSourceSpec { + if in == nil { + return nil + } + out := new(GrafanaDataSourceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaDataSourceStatus) DeepCopyInto(out *GrafanaDataSourceStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataSourceStatus. +func (in *GrafanaDataSourceStatus) DeepCopy() *GrafanaDataSourceStatus { + if in == nil { + return nil + } + out := new(GrafanaDataSourceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaDataStorage) DeepCopyInto(out *GrafanaDataStorage) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.AccessModes != nil { + in, out := &in.AccessModes, &out.AccessModes + *out = make([]v1.PersistentVolumeAccessMode, len(*in)) + copy(*out, *in) + } + out.Size = in.Size.DeepCopy() +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDataStorage. +func (in *GrafanaDataStorage) DeepCopy() *GrafanaDataStorage { + if in == nil { + return nil + } + out := new(GrafanaDataStorage) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaDeployment) DeepCopyInto(out *GrafanaDeployment) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]v1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(v1.Affinity) + (*in).DeepCopyInto(*out) + } + if in.SecurityContext != nil { + in, out := &in.SecurityContext, &out.SecurityContext + *out = new(v1.PodSecurityContext) + (*in).DeepCopyInto(*out) + } + if in.ContainerSecurityContext != nil { + in, out := &in.ContainerSecurityContext, &out.ContainerSecurityContext + *out = new(v1.SecurityContext) + (*in).DeepCopyInto(*out) + } + if in.TerminationGracePeriodSeconds != nil { + in, out := &in.TerminationGracePeriodSeconds, &out.TerminationGracePeriodSeconds + *out = new(int64) + **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]) + } + } + if in.SkipCreateAdminAccount != nil { + in, out := &in.SkipCreateAdminAccount, &out.SkipCreateAdminAccount + *out = new(bool) + **out = **in + } + if in.HostNetwork != nil { + in, out := &in.HostNetwork, &out.HostNetwork + *out = new(bool) + **out = **in + } + if in.ExtraVolumes != nil { + in, out := &in.ExtraVolumes, &out.ExtraVolumes + *out = make([]v1.Volume, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ExtraVolumeMounts != nil { + in, out := &in.ExtraVolumeMounts, &out.ExtraVolumeMounts + *out = make([]v1.VolumeMount, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Strategy != nil { + in, out := &in.Strategy, &out.Strategy + *out = new(appsv1.DeploymentStrategy) + (*in).DeepCopyInto(*out) + } + if in.HTTPProxy != nil { + in, out := &in.HTTPProxy, &out.HTTPProxy + *out = new(GrafanaHTTPProxy) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaDeployment. +func (in *GrafanaDeployment) DeepCopy() *GrafanaDeployment { + if in == nil { + return nil + } + out := new(GrafanaDeployment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaHTTPProxy) DeepCopyInto(out *GrafanaHTTPProxy) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaHTTPProxy. +func (in *GrafanaHTTPProxy) DeepCopy() *GrafanaHTTPProxy { + if in == nil { + return nil + } + out := new(GrafanaHTTPProxy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaIngress) DeepCopyInto(out *GrafanaIngress) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaIngress. +func (in *GrafanaIngress) DeepCopy() *GrafanaIngress { + if in == nil { + return nil + } + out := new(GrafanaIngress) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaList) DeepCopyInto(out *GrafanaList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Grafana, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaList. +func (in *GrafanaList) DeepCopy() *GrafanaList { + if in == nil { + return nil + } + out := new(GrafanaList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GrafanaList) 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 *GrafanaPlugin) DeepCopyInto(out *GrafanaPlugin) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaPlugin. +func (in *GrafanaPlugin) DeepCopy() *GrafanaPlugin { + if in == nil { + return nil + } + out := new(GrafanaPlugin) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaService) DeepCopyInto(out *GrafanaService) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Ports != nil { + in, out := &in.Ports, &out.Ports + *out = make([]v1.ServicePort, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaService. +func (in *GrafanaService) DeepCopy() *GrafanaService { + if in == nil { + return nil + } + out := new(GrafanaService) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaServiceAccount) DeepCopyInto(out *GrafanaServiceAccount) { + *out = *in + if in.Skip != nil { + in, out := &in.Skip, &out.Skip + *out = new(bool) + **out = **in + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]v1.LocalObjectReference, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaServiceAccount. +func (in *GrafanaServiceAccount) DeepCopy() *GrafanaServiceAccount { + if in == nil { + return nil + } + out := new(GrafanaServiceAccount) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaSpec) DeepCopyInto(out *GrafanaSpec) { + *out = *in + in.Config.DeepCopyInto(&out.Config) + 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.DashboardLabelSelector != nil { + in, out := &in.DashboardLabelSelector, &out.DashboardLabelSelector + *out = make([]*metav1.LabelSelector, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } + } + } + if in.Ingress != nil { + in, out := &in.Ingress, &out.Ingress + *out = new(GrafanaIngress) + (*in).DeepCopyInto(*out) + } + if in.InitResources != nil { + in, out := &in.InitResources, &out.InitResources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } + if in.Secrets != nil { + in, out := &in.Secrets, &out.Secrets + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ConfigMaps != nil { + in, out := &in.ConfigMaps, &out.ConfigMaps + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = new(GrafanaService) + (*in).DeepCopyInto(*out) + } + if in.Deployment != nil { + in, out := &in.Deployment, &out.Deployment + *out = new(GrafanaDeployment) + (*in).DeepCopyInto(*out) + } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } + if in.ServiceAccount != nil { + in, out := &in.ServiceAccount, &out.ServiceAccount + *out = new(GrafanaServiceAccount) + (*in).DeepCopyInto(*out) + } + if in.Client != nil { + in, out := &in.Client, &out.Client + *out = new(GrafanaClient) + (*in).DeepCopyInto(*out) + } + if in.DashboardNamespaceSelector != nil { + in, out := &in.DashboardNamespaceSelector, &out.DashboardNamespaceSelector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.DataStorage != nil { + in, out := &in.DataStorage, &out.DataStorage + *out = new(GrafanaDataStorage) + (*in).DeepCopyInto(*out) + } + if in.Jsonnet != nil { + in, out := &in.Jsonnet, &out.Jsonnet + *out = new(JsonnetConfig) + (*in).DeepCopyInto(*out) + } + if in.LivenessProbeSpec != nil { + in, out := &in.LivenessProbeSpec, &out.LivenessProbeSpec + *out = new(LivenessProbeSpec) + **out = **in + } + if in.ReadinessProbeSpec != nil { + in, out := &in.ReadinessProbeSpec, &out.ReadinessProbeSpec + *out = new(ReadinessProbeSpec) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaSpec. +func (in *GrafanaSpec) DeepCopy() *GrafanaSpec { + if in == nil { + return nil + } + out := new(GrafanaSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaStatus) DeepCopyInto(out *GrafanaStatus) { + *out = *in + if in.InstalledDashboards != nil { + in, out := &in.InstalledDashboards, &out.InstalledDashboards + *out = make([]*GrafanaDashboardRef, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(GrafanaDashboardRef) + (*in).DeepCopyInto(*out) + } + } + } + if in.InstalledPlugins != nil { + in, out := &in.InstalledPlugins, &out.InstalledPlugins + *out = make(PluginList, len(*in)) + copy(*out, *in) + } + if in.FailedPlugins != nil { + in, out := &in.FailedPlugins, &out.FailedPlugins + *out = make(PluginList, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaStatus. +func (in *GrafanaStatus) DeepCopy() *GrafanaStatus { + if in == nil { + return nil + } + out := new(GrafanaStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JsonnetConfig) DeepCopyInto(out *JsonnetConfig) { + *out = *in + if in.LibraryLabelSelector != nil { + in, out := &in.LibraryLabelSelector, &out.LibraryLabelSelector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JsonnetConfig. +func (in *JsonnetConfig) DeepCopy() *JsonnetConfig { + if in == nil { + return nil + } + out := new(JsonnetConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LivenessProbeSpec) DeepCopyInto(out *LivenessProbeSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LivenessProbeSpec. +func (in *LivenessProbeSpec) DeepCopy() *LivenessProbeSpec { + if in == nil { + return nil + } + out := new(LivenessProbeSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in PluginList) DeepCopyInto(out *PluginList) { + { + in := &in + *out = make(PluginList, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PluginList. +func (in PluginList) DeepCopy() PluginList { + if in == nil { + return nil + } + out := new(PluginList) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReadinessProbeSpec) DeepCopyInto(out *ReadinessProbeSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReadinessProbeSpec. +func (in *ReadinessProbeSpec) DeepCopy() *ReadinessProbeSpec { + if in == nil { + return nil + } + out := new(ReadinessProbeSpec) + in.DeepCopyInto(out) + return out +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan.go new file mode 100644 index 00000000000..2982d312f5b --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan.go @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package infrastructure + +import ( + "fmt" + + "gopkg.in/yaml.v2" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" + ispn "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/operator" +) + +const ( + // Default Infinispan port + defaultInfinispanPort = 11222 + // InfinispanSecretUsernameKey is the secret username key set in the linked secret + InfinispanSecretUsernameKey = "username" + // InfinispanSecretPasswordKey is the secret password key set in the linked secret + InfinispanSecretPasswordKey = "password" + // Default Infinispan user + defaultInfinispanUser = "developer" + // InfinispanIdentityFileName is the name of YAML file containing list of Infinispan credentials + InfinispanIdentityFileName = "identities.yaml" + + // InfinispanKind CRD Kind for Infinispan server (as defined by Infinispan Operator) + InfinispanKind = "Infinispan" + + // InfinispanInstanceName is the default name for Infinispan managed by KogitoInfra + InfinispanInstanceName = "kogito-infinispan" +) + +// InfinispanHandler ... +type InfinispanHandler interface { + FetchInfinispanInstance(key types.NamespacedName) (*ispn.Infinispan, error) + IsInfinispanAvailable() bool + FetchInfinispanInstanceURI(key types.NamespacedName) (string, error) + GetInfinispanCredential(infinispanInstance *ispn.Infinispan) (*InfinispanCredential, error) +} + +type infinispanHandler struct { + operator.Context +} + +var ( + // InfinispanAPIVersion CRD API group version for Infinispan server (as defined by Infinispan Operator) + InfinispanAPIVersion = ispn.SchemeGroupVersion.String() +) + +// InfinispanIdentity is the struct for the secret holding the credential for the Infinispan server +type InfinispanIdentity struct { + Credentials []InfinispanCredential `yaml:"credentials"` +} + +// InfinispanCredential holds the information to authenticate into an infinispan server +type InfinispanCredential struct { + Username string `yaml:"username"` + Password string `yaml:"password"` +} + +// NewInfinispanHandler ... +func NewInfinispanHandler(context operator.Context) InfinispanHandler { + return &infinispanHandler{ + context, + } +} + +func (i *infinispanHandler) FetchInfinispanInstance(key types.NamespacedName) (*ispn.Infinispan, error) { + i.Log.Debug("fetching deployed kogito infinispan instance") + infinispanInstance := &ispn.Infinispan{} + if exits, err := kubernetes.ResourceC(i.Client).FetchWithKey(key, infinispanInstance); err != nil { + i.Log.Error(err, "Error occurs while fetching infinispan instance") + return nil, err + } else if !exits { + i.Log.Debug("Infinispan instance is not exists") + return nil, nil + } else { + i.Log.Debug("Infinispan instance found") + return infinispanInstance, nil + } +} + +// IsInfinispanAvailable checks whether Infinispan CRD is available or not +func (i *infinispanHandler) IsInfinispanAvailable() bool { + return i.Client.HasServerGroup(ispn.SchemeGroupVersion.Group) +} + +// FetchInfinispanInstanceURI provide infinispan URI for given instance name +func (i *infinispanHandler) FetchInfinispanInstanceURI(key types.NamespacedName) (string, error) { + i.Log.Debug("Fetching kogito infinispan instance URI.") + service := &corev1.Service{} + if exits, err := kubernetes.ResourceC(i.Client).FetchWithKey(key, service); err != nil { + return "", err + } else if !exits { + return "", fmt.Errorf("service with name %s not exist for Infinispan instance in given namespace %s", key.Name, key.Namespace) + } else { + for _, port := range service.Spec.Ports { + if port.TargetPort.IntVal == defaultInfinispanPort { + uri := fmt.Sprintf("%s:%d", service.Name, port.TargetPort.IntVal) + i.Log.Debug("", "kogito infinispan instance URI", uri) + return uri, nil + } + } + return "", fmt.Errorf("Infinispan default port (%d) not found in service %s ", defaultInfinispanPort, service.Name) + } +} + +// GetInfinispanCredential gets the credential of the Infinispan server deployed with the Kogito Operator +func (i *infinispanHandler) GetInfinispanCredential(infinispanInstance *ispn.Infinispan) (*InfinispanCredential, error) { + secret := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: infinispanInstance.Spec.Security.EndpointSecretName, Namespace: infinispanInstance.Namespace}} + if exists, err := kubernetes.ResourceC(i.Client).Fetch(secret); err != nil { + return nil, err + } else if exists { + return getDefaultInfinispanCredential(secret) + } + i.Log.Warn("Infinispan credential not found", "secret", infinispanInstance.Spec.Security.EndpointSecretName) + return nil, nil +} + +// getDefaultInfinispanCredential will return the credential to be used by internal services +func getDefaultInfinispanCredential(infinispanSecret *corev1.Secret) (*InfinispanCredential, error) { + return findInfinispanCredentialByUsernameOrFirst(defaultInfinispanUser, infinispanSecret) +} + +// findInfinispanCredentialByUsernameOrFirst fetches the default credential in a infinispan operator generated cluster or first one found +func findInfinispanCredentialByUsernameOrFirst(username string, infinispanSecret *corev1.Secret) (*InfinispanCredential, error) { + secretFileData := infinispanSecret.Data[InfinispanIdentityFileName] + identity := &InfinispanIdentity{} + if len(secretFileData) == 0 { + return &InfinispanCredential{ + Username: string(infinispanSecret.Data[InfinispanSecretUsernameKey]), + Password: string(infinispanSecret.Data[InfinispanSecretPasswordKey]), + }, nil + } + err := yaml.Unmarshal(secretFileData, identity) + if err != nil { + return nil, err + } + for _, c := range identity.Credentials { + if c.Username == username { + return &c, nil + } + } + if len(identity.Credentials) == 1 { + return &identity.Credentials[0], nil + } + return nil, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/group.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/group.go new file mode 100644 index 00000000000..1316c8e8981 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/group.go @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// Package infinispan contains infinispan API versions. +// +// This file ensures Go source parsers acknowledge the infinispan package +// and any child packages. It can be removed if any other Go source files are +// added to this package. +package infinispan diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1/doc.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1/doc.go new file mode 100644 index 00000000000..87513d4cf12 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1/doc.go @@ -0,0 +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. + */ + +// Package v1 contains API Schema definitions for the infinispan v1 API group +// +k8s:deepcopy-gen=package,register +// +groupName=infinispan.org +package v1 diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1/infinispan_types.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1/infinispan_types.go new file mode 100644 index 00000000000..d9426244e41 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1/infinispan_types.go @@ -0,0 +1,449 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 + +// IMPORTANT: run "make codegen" or "operator-sdk generate k8s" to regenerate code after modifying this file +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +import ( + "fmt" + "strings" + + "github.com/RHsyseng/operator-utils/pkg/olm" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// InfinispanSecurity info for the user application connection +type InfinispanSecurity struct { + // +optional + Authorization *Authorization `json:"authorization,omitempty"` + // +optional + EndpointAuthentication *bool `json:"endpointAuthentication,omitempty"` + // +optional + EndpointSecretName string `json:"endpointSecretName,omitempty"` + // +optional + EndpointEncryption *EndpointEncryption `json:"endpointEncryption,omitempty"` +} + +// Authorization ... +type Authorization struct { + // +optional + Enabled bool `json:"enabled,omitempty"` + // +optional + Roles []AuthorizationRole `json:"roles,omitempty"` +} + +// AuthorizationRole ... +type AuthorizationRole struct { + Name string `json:"name"` + Permissions []string `json:"permissions"` +} + +// CertificateSourceType specifies all the possible sources for the encryption certificate +// +kubebuilder:validation:Enum=Service;service;Secret;secret;None +type CertificateSourceType string + +const ( + // CertificateSourceTypeService certificate coming from a cluster service + CertificateSourceTypeService CertificateSourceType = "Service" + // CertificateSourceTypeServiceLowCase certificate coming from a cluster service + CertificateSourceTypeServiceLowCase CertificateSourceType = "service" + + // CertificateSourceTypeSecret certificate coming from a user provided secret + CertificateSourceTypeSecret CertificateSourceType = "Secret" + // CertificateSourceTypeSecretLowCase certificate coming from a user provided secret + CertificateSourceTypeSecretLowCase CertificateSourceType = "secret" + + // CertificateSourceTypeNoneNoEncryption no certificate encryption disabled + CertificateSourceTypeNoneNoEncryption CertificateSourceType = "None" +) + +// ClientCertType specifies a client certificate validation mechanism. +// +kubebuilder:validation:Enum=None;Authenticate;Validate +type ClientCertType string + +const ( + // ClientCertNone No client certificates required + ClientCertNone ClientCertType = "None" + // ClientCertAuthenticate All client certificates must be in the configured truststore. + ClientCertAuthenticate ClientCertType = "Authenticate" + // ClientCertValidate Client certificates are validated against the CA in the truststore. It is not required for all client certificates to be contained in the trustore. + ClientCertValidate ClientCertType = "Validate" +) + +// EndpointEncryption configuration +type EndpointEncryption struct { + // +optional + Type CertificateSourceType `json:"type,omitempty"` + // +optional + CertServiceName string `json:"certServiceName,omitempty"` + // +optional + CertSecretName string `json:"certSecretName,omitempty"` + // +optional + ClientCert ClientCertType `json:"clientCert,omitempty"` + // +optional + ClientCertSecretName string `json:"clientCertSecretName,omitempty"` +} + +// InfinispanServiceContainerSpec resource requirements specific for service +type InfinispanServiceContainerSpec struct { + // +optional + Storage *string `json:"storage,omitempty"` + // +optional + EphemeralStorage bool `json:"ephemeralStorage,omitempty"` + // +optional + StorageClassName string `json:"storageClassName,omitempty"` +} + +// +kubebuilder:validation:Enum=DataGrid;Cache + +// ServiceType ... +type ServiceType string + +const ( + // ServiceTypeCache Deploys Infinispan to act like a cache. This means: + // Caches are only used for volatile data. + // No support for data persistence. + // Cache definitions can still be permanent, but PV size is not configurable. + // A default cache is created by default, + // Additional caches can be created, but only as copies of default cache. + ServiceTypeCache ServiceType = "Cache" + + // ServiceTypeDataGrid Deploys Infinispan to act like a data grid. + // More flexibility and more configuration options are available: + // Cross-site replication, store cached data in persistence store...etc. + ServiceTypeDataGrid ServiceType = "DataGrid" +) + +// InfinispanServiceSpec specify configuration for specific service +type InfinispanServiceSpec struct { + Type ServiceType `json:"type,omitempty"` + // +optional + Container *InfinispanServiceContainerSpec `json:"container,omitempty"` + // +optional + Sites *InfinispanSitesSpec `json:"sites,omitempty"` + // +optional + ReplicationFactor int32 `json:"replicationFactor,omitempty"` +} + +// InfinispanContainerSpec specify resource requirements per container +type InfinispanContainerSpec struct { + // +optional + ExtraJvmOpts string `json:"extraJvmOpts,omitempty"` + // +optional + Memory string `json:"memory,omitempty"` + // +optional + CPU string `json:"cpu,omitempty"` +} + +// InfinispanSitesLocalSpec ... +type InfinispanSitesLocalSpec struct { + Name string `json:"name"` + Expose CrossSiteExposeSpec `json:"expose"` +} + +// InfinispanSiteLocationSpec ... +type InfinispanSiteLocationSpec struct { + Name string `json:"name"` + // +optional + Namespace string `json:"namespace,omitempty"` + // +optional + ClusterName string `json:"clusterName,omitempty"` + // Deprecated and to be removed on subsequent release. Use .URL with infinispan+xsite schema instead. + // +optional + Host *string `json:"host,omitempty"` + // Deprecated and to be removed on subsequent release. Use .URL with infinispan+xsite schema instead. + // +optional + Port *int32 `json:"port,omitempty"` + // +kubebuilder:validation:Pattern=`(^(kubernetes|minikube|openshift):\/\/(([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])*(:[0-9]+)+$)|(^(infinispan\+xsite):\/\/(([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])*(:[0-9]+)*$)` + // +optional + URL string `json:"url,omitempty"` + // +optional + SecretName string `json:"secretName,omitempty"` +} + +// InfinispanSitesSpec ... +type InfinispanSitesSpec struct { + Local InfinispanSitesLocalSpec `json:"local"` + Locations []InfinispanSiteLocationSpec `json:"locations,omitempty"` +} + +// LoggingLevelType describe the logging level for selected category +// +kubebuilder:validation:Enum=trace;debug;info;warn;error +type LoggingLevelType string + +const ( + // LoggingLevelTrace ... + LoggingLevelTrace LoggingLevelType = "trace" + // LoggingLevelDebug ... + LoggingLevelDebug LoggingLevelType = "debug" + // LoggingLevelInfo ... + LoggingLevelInfo LoggingLevelType = "info" + // LoggingLevelWarn ... + LoggingLevelWarn LoggingLevelType = "warn" + // LoggingLevelError ... + LoggingLevelError LoggingLevelType = "error" +) + +// InfinispanLoggingSpec ... +type InfinispanLoggingSpec struct { + Categories map[string]LoggingLevelType `json:"categories,omitempty"` +} + +// ExposeType describe different exposition methods for Infinispan +// +kubebuilder:validation:Enum=NodePort;LoadBalancer;Route +type ExposeType string + +const ( + // ExposeTypeNodePort means a service will be exposed on one port of + // every node, in addition to 'ClusterIP' type. + ExposeTypeNodePort = ExposeType(corev1.ServiceTypeNodePort) + + // ExposeTypeLoadBalancer means a service will be exposed via an + // external load balancer (if the cloud provider supports it), in addition + // to 'NodePort' type. + ExposeTypeLoadBalancer = ExposeType(corev1.ServiceTypeLoadBalancer) + + // ExposeTypeRoute means the service will be exposed via + // `Route` on Openshift or via `Ingress` on Kubernetes + ExposeTypeRoute ExposeType = "Route" +) + +// CrossSiteExposeType describe different exposition methods for Infinispan Cross-Site service +// +kubebuilder:validation:Enum=NodePort;LoadBalancer;ClusterIP +type CrossSiteExposeType string + +const ( + // CrossSiteExposeTypeNodePort means a service will be exposed on one port of + // every node, in addition to 'ClusterIP' type. + CrossSiteExposeTypeNodePort = CrossSiteExposeType(corev1.ServiceTypeNodePort) + + // CrossSiteExposeTypeLoadBalancer means a service will be exposed via an + // external load balancer (if the cloud provider supports it), in addition + // to 'NodePort' type. + CrossSiteExposeTypeLoadBalancer = CrossSiteExposeType(corev1.ServiceTypeLoadBalancer) + + // CrossSiteExposeTypeClusterIP means an internal 'ClusterIP' + // service will be created without external exposition + CrossSiteExposeTypeClusterIP = CrossSiteExposeType(corev1.ServiceTypeClusterIP) +) + +// ExposeSpec describe how Infinispan will be exposed externally +type ExposeSpec struct { + // Type specifies different exposition methods for data grid + Type ExposeType `json:"type"` + // +optional + NodePort int32 `json:"nodePort,omitempty"` + // +optional + Port int32 `json:"port,omitempty"` + // +optional + Host string `json:"host,omitempty"` + // +optional + Annotations map[string]string `json:"annotations,omitempty"` +} + +// CrossSiteExposeSpec describe how Infinispan Cross-Site service will be exposed externally +type CrossSiteExposeSpec struct { + // Type specifies different exposition methods for data grid + Type CrossSiteExposeType `json:"type"` + // +optional + NodePort int32 `json:"nodePort,omitempty"` + // +optional + Port int32 `json:"port,omitempty"` + // +optional + Annotations map[string]string `json:"annotations,omitempty"` +} + +// Autoscale describe autoscaling configuration for the cluster +type Autoscale struct { + MaxReplicas int32 `json:"maxReplicas"` + MinReplicas int32 `json:"minReplicas"` + MaxMemUsagePercent int `json:"maxMemUsagePercent"` + MinMemUsagePercent int `json:"minMemUsagePercent"` + // +optional + Disabled bool `json:"disabled,omitempty"` +} + +// InfinispanExternalDependencies describes all the external dependencies +// used by the Infinispan cluster: i.e. lib folder with custom jar, maven artifact, images ... +type InfinispanExternalDependencies struct { + // Name of the persistent volume claim with custom libraries + // +optional + VolumeClaimName string `json:"volumeClaimName,omitempty"` +} + +// InfinispanCloudEvents describes how Infinispan is connected with Cloud Event, see Kafka docs for more info +type InfinispanCloudEvents struct { + // BootstrapServers is comma separated list of boostrap server:port addresses + BootstrapServers string `json:"bootstrapServers"` + // Acks configuration for the producer ack-value + // +optional + Acks string `json:"acks,omitempty"` + // CacheEntriesTopic is the name of the topic on which events will be published + // +optional + CacheEntriesTopic string `json:"cacheEntriesTopic,omitempty"` +} + +// InfinispanSpec defines the desired state of Infinispan +type InfinispanSpec struct { + Replicas int32 `json:"replicas"` + // +optional + Image *string `json:"image,omitempty"` + // +optional + Security InfinispanSecurity `json:"security,omitempty"` + // +optional + Container InfinispanContainerSpec `json:"container,omitempty"` + // +optional + Service InfinispanServiceSpec `json:"service,omitempty"` + // +optional + Logging *InfinispanLoggingSpec `json:"logging,omitempty"` + // +optional + Expose *ExposeSpec `json:"expose,omitempty"` + // +optional + Autoscale *Autoscale `json:"autoscale,omitempty"` + // +optional + Affinity *corev1.Affinity `json:"affinity,omitempty"` + // +optional + CloudEvents *InfinispanCloudEvents `json:"cloudEvents,omitempty"` + // External dependencies needed by the Infinispan cluster + // +optional + Dependencies *InfinispanExternalDependencies `json:"dependencies,omitempty"` +} + +// ConditionType ... +type ConditionType string + +const ( + // ConditionPrelimChecksPassed ... + ConditionPrelimChecksPassed ConditionType = "PreliminaryChecksPassed" + // ConditionGracefulShutdown ... + ConditionGracefulShutdown ConditionType = "GracefulShutdown" + // ConditionStopping ... + ConditionStopping ConditionType = "Stopping" + // ConditionUpgrade ... + ConditionUpgrade ConditionType = "Upgrade" + // ConditionWellFormed ... + ConditionWellFormed ConditionType = "WellFormed" + // ConditionCrossSiteViewFormed ... + ConditionCrossSiteViewFormed ConditionType = "CrossSiteViewFormed" +) + +// InfinispanCondition define a condition of the cluster +type InfinispanCondition struct { + // Type is the type of the condition. + Type ConditionType `json:"type"` + // Status is the status of the condition. + Status metav1.ConditionStatus `json:"status"` + // Human-readable message indicating details about last transition. + // +optional + Message string `json:"message,omitempty"` +} + +// InfinispanStatus defines the observed state of Infinispan +type InfinispanStatus struct { + // +optional + Conditions []InfinispanCondition `json:"conditions,omitempty"` + // +optional + StatefulSetName string `json:"statefulSetName,omitempty"` + // +optional + Security *InfinispanSecurity `json:"security,omitempty"` + // +optional + ReplicasWantedAtRestart int32 `json:"replicasWantedAtRestart,omitempty"` + // +optional + PodStatus olm.DeploymentStatus `json:"podStatus,omitempty"` + // +optional + ConsoleURL *string `json:"consoleUrl,omitempty"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Infinispan is the Schema for the infinispans API +// +k8s:openapi-gen=true +// +kubebuilder:subresource:status +type Infinispan struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec InfinispanSpec `json:"spec,omitempty"` + Status InfinispanStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// InfinispanList contains a list of Infinispan +type InfinispanList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Infinispan `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Infinispan{}, &InfinispanList{}) +} + +// IsWellFormed return true if cluster is well formed +func (ispn *Infinispan) IsWellFormed() bool { + return ispn.EnsureClusterStability() == nil +} + +// EnsureClusterStability ... +func (ispn *Infinispan) EnsureClusterStability() error { + conditions := map[ConditionType]metav1.ConditionStatus{ + ConditionGracefulShutdown: metav1.ConditionFalse, + ConditionPrelimChecksPassed: metav1.ConditionTrue, + ConditionUpgrade: metav1.ConditionFalse, + ConditionStopping: metav1.ConditionFalse, + ConditionWellFormed: metav1.ConditionTrue, + } + return ispn.ExpectConditionStatus(conditions) +} + +// ExpectConditionStatus ... +func (ispn *Infinispan) ExpectConditionStatus(expected map[ConditionType]metav1.ConditionStatus) error { + for key, value := range expected { + c := ispn.GetCondition(key) + if c.Status != value { + if c.Message == "" { + return fmt.Errorf("key '%s' has Status '%s', expected '%s'", key, c.Status, value) + } + return fmt.Errorf("key '%s' has Status '%s', expected '%s' Reason '%s", key, c.Status, value, c.Message) + } + } + return nil +} + +// GetCondition return the Status of the given condition or nil +// if condition is not present +func (ispn *Infinispan) GetCondition(condition ConditionType) InfinispanCondition { + for _, c := range ispn.Status.Conditions { + if c.Type.equals(condition) { + return c + } + } + // Absence of condition means `False` value + return InfinispanCondition{Type: condition, Status: metav1.ConditionFalse} +} + +// equals compares two ConditionType's case insensitive +func (a ConditionType) equals(b ConditionType) bool { + return strings.EqualFold(strings.ToLower(string(a)), strings.ToLower(string(b))) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1/register.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1/register.go new file mode 100644 index 00000000000..57069dcb14d --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1/register.go @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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: Boilerplate only. Ignore this file. + +// Package v1 contains API Schema definitions for the infinispan v1 API group +// +kubebuilder:skip +// +k8s:deepcopy-gen=package,register +// +groupName=infinispan.org +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "infinispan.org", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} + + // AddToScheme adds registered types + AddToScheme = SchemeBuilder.AddToScheme +) + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1/zz_generated.deepcopy.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..2cf7ef05926 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1/zz_generated.deepcopy.go @@ -0,0 +1,505 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright 2021 Red Hat, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + 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 *Authorization) DeepCopyInto(out *Authorization) { + *out = *in + if in.Roles != nil { + in, out := &in.Roles, &out.Roles + *out = make([]AuthorizationRole, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Authorization. +func (in *Authorization) DeepCopy() *Authorization { + if in == nil { + return nil + } + out := new(Authorization) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationRole) DeepCopyInto(out *AuthorizationRole) { + *out = *in + if in.Permissions != nil { + in, out := &in.Permissions, &out.Permissions + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationRole. +func (in *AuthorizationRole) DeepCopy() *AuthorizationRole { + if in == nil { + return nil + } + out := new(AuthorizationRole) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Autoscale) DeepCopyInto(out *Autoscale) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Autoscale. +func (in *Autoscale) DeepCopy() *Autoscale { + if in == nil { + return nil + } + out := new(Autoscale) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CrossSiteExposeSpec) DeepCopyInto(out *CrossSiteExposeSpec) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CrossSiteExposeSpec. +func (in *CrossSiteExposeSpec) DeepCopy() *CrossSiteExposeSpec { + if in == nil { + return nil + } + out := new(CrossSiteExposeSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EndpointEncryption) DeepCopyInto(out *EndpointEncryption) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EndpointEncryption. +func (in *EndpointEncryption) DeepCopy() *EndpointEncryption { + if in == nil { + return nil + } + out := new(EndpointEncryption) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExposeSpec) DeepCopyInto(out *ExposeSpec) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExposeSpec. +func (in *ExposeSpec) DeepCopy() *ExposeSpec { + if in == nil { + return nil + } + out := new(ExposeSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Infinispan) DeepCopyInto(out *Infinispan) { + *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 Infinispan. +func (in *Infinispan) DeepCopy() *Infinispan { + if in == nil { + return nil + } + out := new(Infinispan) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Infinispan) 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 *InfinispanCloudEvents) DeepCopyInto(out *InfinispanCloudEvents) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanCloudEvents. +func (in *InfinispanCloudEvents) DeepCopy() *InfinispanCloudEvents { + if in == nil { + return nil + } + out := new(InfinispanCloudEvents) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InfinispanCondition) DeepCopyInto(out *InfinispanCondition) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanCondition. +func (in *InfinispanCondition) DeepCopy() *InfinispanCondition { + if in == nil { + return nil + } + out := new(InfinispanCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InfinispanContainerSpec) DeepCopyInto(out *InfinispanContainerSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanContainerSpec. +func (in *InfinispanContainerSpec) DeepCopy() *InfinispanContainerSpec { + if in == nil { + return nil + } + out := new(InfinispanContainerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InfinispanExternalDependencies) DeepCopyInto(out *InfinispanExternalDependencies) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanExternalDependencies. +func (in *InfinispanExternalDependencies) DeepCopy() *InfinispanExternalDependencies { + if in == nil { + return nil + } + out := new(InfinispanExternalDependencies) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InfinispanList) DeepCopyInto(out *InfinispanList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Infinispan, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanList. +func (in *InfinispanList) DeepCopy() *InfinispanList { + if in == nil { + return nil + } + out := new(InfinispanList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *InfinispanList) 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 *InfinispanLoggingSpec) DeepCopyInto(out *InfinispanLoggingSpec) { + *out = *in + if in.Categories != nil { + in, out := &in.Categories, &out.Categories + *out = make(map[string]LoggingLevelType, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanLoggingSpec. +func (in *InfinispanLoggingSpec) DeepCopy() *InfinispanLoggingSpec { + if in == nil { + return nil + } + out := new(InfinispanLoggingSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InfinispanSecurity) DeepCopyInto(out *InfinispanSecurity) { + *out = *in + if in.Authorization != nil { + in, out := &in.Authorization, &out.Authorization + *out = new(Authorization) + (*in).DeepCopyInto(*out) + } + if in.EndpointAuthentication != nil { + in, out := &in.EndpointAuthentication, &out.EndpointAuthentication + *out = new(bool) + **out = **in + } + if in.EndpointEncryption != nil { + in, out := &in.EndpointEncryption, &out.EndpointEncryption + *out = new(EndpointEncryption) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanSecurity. +func (in *InfinispanSecurity) DeepCopy() *InfinispanSecurity { + if in == nil { + return nil + } + out := new(InfinispanSecurity) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InfinispanServiceContainerSpec) DeepCopyInto(out *InfinispanServiceContainerSpec) { + *out = *in + if in.Storage != nil { + in, out := &in.Storage, &out.Storage + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanServiceContainerSpec. +func (in *InfinispanServiceContainerSpec) DeepCopy() *InfinispanServiceContainerSpec { + if in == nil { + return nil + } + out := new(InfinispanServiceContainerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InfinispanServiceSpec) DeepCopyInto(out *InfinispanServiceSpec) { + *out = *in + if in.Container != nil { + in, out := &in.Container, &out.Container + *out = new(InfinispanServiceContainerSpec) + (*in).DeepCopyInto(*out) + } + if in.Sites != nil { + in, out := &in.Sites, &out.Sites + *out = new(InfinispanSitesSpec) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanServiceSpec. +func (in *InfinispanServiceSpec) DeepCopy() *InfinispanServiceSpec { + if in == nil { + return nil + } + out := new(InfinispanServiceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InfinispanSiteLocationSpec) DeepCopyInto(out *InfinispanSiteLocationSpec) { + *out = *in + if in.Host != nil { + in, out := &in.Host, &out.Host + *out = new(string) + **out = **in + } + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanSiteLocationSpec. +func (in *InfinispanSiteLocationSpec) DeepCopy() *InfinispanSiteLocationSpec { + if in == nil { + return nil + } + out := new(InfinispanSiteLocationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InfinispanSitesLocalSpec) DeepCopyInto(out *InfinispanSitesLocalSpec) { + *out = *in + in.Expose.DeepCopyInto(&out.Expose) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanSitesLocalSpec. +func (in *InfinispanSitesLocalSpec) DeepCopy() *InfinispanSitesLocalSpec { + if in == nil { + return nil + } + out := new(InfinispanSitesLocalSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InfinispanSitesSpec) DeepCopyInto(out *InfinispanSitesSpec) { + *out = *in + in.Local.DeepCopyInto(&out.Local) + if in.Locations != nil { + in, out := &in.Locations, &out.Locations + *out = make([]InfinispanSiteLocationSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanSitesSpec. +func (in *InfinispanSitesSpec) DeepCopy() *InfinispanSitesSpec { + if in == nil { + return nil + } + out := new(InfinispanSitesSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InfinispanSpec) DeepCopyInto(out *InfinispanSpec) { + *out = *in + if in.Image != nil { + in, out := &in.Image, &out.Image + *out = new(string) + **out = **in + } + in.Security.DeepCopyInto(&out.Security) + out.Container = in.Container + in.Service.DeepCopyInto(&out.Service) + if in.Logging != nil { + in, out := &in.Logging, &out.Logging + *out = new(InfinispanLoggingSpec) + (*in).DeepCopyInto(*out) + } + if in.Expose != nil { + in, out := &in.Expose, &out.Expose + *out = new(ExposeSpec) + (*in).DeepCopyInto(*out) + } + if in.Autoscale != nil { + in, out := &in.Autoscale, &out.Autoscale + *out = new(Autoscale) + **out = **in + } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(corev1.Affinity) + (*in).DeepCopyInto(*out) + } + if in.CloudEvents != nil { + in, out := &in.CloudEvents, &out.CloudEvents + *out = new(InfinispanCloudEvents) + **out = **in + } + if in.Dependencies != nil { + in, out := &in.Dependencies, &out.Dependencies + *out = new(InfinispanExternalDependencies) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanSpec. +func (in *InfinispanSpec) DeepCopy() *InfinispanSpec { + if in == nil { + return nil + } + out := new(InfinispanSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InfinispanStatus) DeepCopyInto(out *InfinispanStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]InfinispanCondition, len(*in)) + copy(*out, *in) + } + if in.Security != nil { + in, out := &in.Security, &out.Security + *out = new(InfinispanSecurity) + (*in).DeepCopyInto(*out) + } + in.PodStatus.DeepCopyInto(&out.PodStatus) + if in.ConsoleURL != nil { + in, out := &in.ConsoleURL, &out.ConsoleURL + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfinispanStatus. +func (in *InfinispanStatus) DeepCopy() *InfinispanStatus { + if in == nil { + return nil + } + out := new(InfinispanStatus) + in.DeepCopyInto(out) + return out +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka.go new file mode 100644 index 00000000000..0c7ff7d6f75 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka.go @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package infrastructure + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/operator" +) + +const ( + strimziServerGroup = "kafka.strimzi.io" + + strimziBrokerLabel = "strimzi.io/cluster" + defaultKafkaTopicPartition = 1 + defaultKafkaTopicReplicas = 1 + + // KafkaKind refers to Kafka Kind as defined by Strimzi + KafkaKind = "Kafka" + + // KafkaInstanceName is the default name for the Kafka cluster managed by KogitoInfra + KafkaInstanceName = "kogito-kafka" +) + +var ( + // KafkaAPIVersion refers to kafka APIVersion + KafkaAPIVersion = v1beta2.SchemeGroupVersion.String() +) + +// KafkaHandler ... +type KafkaHandler interface { + IsStrimziAvailable() bool + FetchKafkaInstance(key types.NamespacedName) (*v1beta2.Kafka, error) + FetchKafkaTopic(key types.NamespacedName) (*v1beta2.KafkaTopic, error) + CreateKafkaTopic(topicName, kafkaName, kafkaNamespace string) (*v1beta2.KafkaTopic, error) + ResolveKafkaServerURI(kafka *v1beta2.Kafka) (string, error) +} + +type kafkaHandler struct { + operator.Context +} + +// NewKafkaHandler ... +func NewKafkaHandler(context operator.Context) KafkaHandler { + return &kafkaHandler{ + context, + } +} + +// IsStrimziAvailable checks if Strimzi CRD is available in the cluster +func (k *kafkaHandler) IsStrimziAvailable() bool { + return k.Client.HasServerGroup(strimziServerGroup) +} + +func (k *kafkaHandler) FetchKafkaInstance(key types.NamespacedName) (*v1beta2.Kafka, error) { + k.Log.Debug("fetching deployed kafka instance") + kafkaInstance := &v1beta2.Kafka{} + if exists, err := kubernetes.ResourceC(k.Client).FetchWithKey(key, kafkaInstance); err != nil { + k.Log.Error(err, "Error occurs while fetching kogito kafka instance") + return nil, err + } else if !exists { + k.Log.Debug("kafka instance does not exist") + return nil, nil + } else { + k.Log.Debug("kafka instance found") + return kafkaInstance, nil + } +} + +func (k *kafkaHandler) FetchKafkaTopic(key types.NamespacedName) (*v1beta2.KafkaTopic, error) { + k.Log.Debug("Going to load deployed kafka topic", "topicName", key.Name) + kafkaTopic := &v1beta2.KafkaTopic{} + if exits, err := kubernetes.ResourceC(k.Client).FetchWithKey(key, kafkaTopic); err != nil { + k.Log.Error(err, "Error occurs while fetching kogito kafka topic", "topicName", key.Name) + return nil, err + } else if exits { + k.Log.Debug("kafka topic found", "topicName", key.Name) + return kafkaTopic, nil + } + k.Log.Debug("kafka topic not exists", "topicName", key.Name) + return nil, nil +} + +func (k *kafkaHandler) CreateKafkaTopic(topicName, kafkaName, kafkaNamespace string) (*v1beta2.KafkaTopic, error) { + k.Log.Debug("Going to create kafka topic", "topicName", topicName) + kafkaTopic := getKafkaTopic(topicName, kafkaNamespace, kafkaName) + if err := kubernetes.ResourceC(k.Client).Create(kafkaTopic); err != nil { + k.Log.Error(err, "Error occurs while creating kogito Kafka topic") + return nil, err + } + k.Log.Debug("Kogito Kafka topic created successfully", "topicName", topicName) + return kafkaTopic, nil +} + +// getKafkaTopic returns a Kafka topic resource with default configuration +func getKafkaTopic(name, namespace, kafkaBroker string) *v1beta2.KafkaTopic { + + labels := make(map[string]string) + labels[strimziBrokerLabel] = kafkaBroker + + return &v1beta2.KafkaTopic{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + Labels: labels, + }, + Spec: v1beta2.KafkaTopicSpec{ + Partitions: defaultKafkaTopicPartition, + Replicas: defaultKafkaTopicReplicas, + TopicName: name, + }, + } +} + +// ResolveKafkaServerURI returns the uri of the kafka instance +func (k *kafkaHandler) ResolveKafkaServerURI(kafka *v1beta2.Kafka) (string, error) { + k.Log.Debug("Resolving kafka URI", "kafka instance", kafka.Name) + kafkaURI := ResolveKafkaServerURI(kafka) + if len(kafkaURI) > 0 { + k.Log.Debug("Success fetch Kafka URI", "kafka instance", kafka.Name, "kafka URI", kafkaURI) + return kafkaURI, nil + } + k.Log.Debug("Not able resolve URI for given kafka instance") + return "", fmt.Errorf("not able resolve URI for given kafka instance %s", kafka.Name) +} + +// ResolveKafkaServerURI returns the uri of the kafka instance +func ResolveKafkaServerURI(kafka *v1beta2.Kafka) string { + if len(kafka.Status.Listeners) > 0 { + for _, listenerStatus := range kafka.Status.Listeners { + if listenerStatus.Type == "plain" && len(listenerStatus.Addresses) > 0 { + for _, listenerAddress := range listenerStatus.Addresses { + if len(listenerAddress.Host) > 0 && listenerAddress.Port > 0 { + kafkaURI := fmt.Sprintf("%s:%d", listenerAddress.Host, listenerAddress.Port) + return kafkaURI + } + } + } + } + } + return "" +} + +// IsKafkaResource checks if provided KogitoInfra instance is for kafka resource +func IsKafkaResource(apiVersion, kind string) bool { + return apiVersion == KafkaAPIVersion && kind == KafkaKind +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/group.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/group.go new file mode 100644 index 00000000000..3c5cad046a3 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/group.go @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// Package kafka contains kafka API versions. +// +// This file ensures Go source parsers acknowledge the kafka package +// and any child packages. It can be removed if any other Go source files are +// added to this package. +package kafka diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/doc.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/doc.go new file mode 100644 index 00000000000..ed3c5591cbb --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/doc.go @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// Package v1beta2 contains API Schema definitions for the kafka v1beta2 API group +// +k8s:deepcopy-gen=package,register +// +groupName=kafka.strimzi.io +// +kubebuilder:skip +package v1beta2 diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/kafka_types.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/kafka_types.go new file mode 100644 index 00000000000..7b8dddfbc32 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/kafka_types.go @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1beta2 + +import ( + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// KafkaSpec defines the desired state of Kafka +type KafkaSpec struct { + Kafka KafkaClusterSpec `json:"kafka,omitempty"` + Zookeeper ZookeeperClusterSpec `json:"zookeeper,omitempty"` + EntityOperator EntityOperatorSpec `json:"entityOperator,omitempty"` +} + +// EntityOperatorSpec ... +type EntityOperatorSpec struct { + TopicOperator EntityTopicOperatorSpec `json:"topicOperator,omitempty"` + UserOperator EntityUserOperatorSpec `json:"userOperator,omitempty"` +} + +// EntityTopicOperatorSpec ... +type EntityTopicOperatorSpec struct { +} + +// EntityUserOperatorSpec ... +type EntityUserOperatorSpec struct { +} + +// KafkaMap a feasible way to implement a map with interface values to match the Java counterpart: Map +type KafkaMap map[string]interface{} + +// DeepCopy implements a custom deepcopy function since map[string]interface{} it's not available +func (kafkaMap *KafkaMap) DeepCopy() *KafkaMap { + o := &KafkaMap{} + *o = *kafkaMap + return o +} + +// KafkaClusterSpec defines the desired state of Kafka Cluster +type KafkaClusterSpec struct { + Replicas int32 `json:"replicas,omitempty"` + Listeners []GenericKafkaListener `json:"listeners,omitempty"` + Storage KafkaStorage `json:"storage,omitempty"` + Config KafkaMap `json:"config,omitempty"` + JvmOptions KafkaMap `json:"jvmOptions,omitempty"` +} + +// GenericKafkaListener ... +type GenericKafkaListener struct { + Name string `json:"name,omitempty"` + Port int `json:"port,omitempty"` + ListenerType string `json:"type,omitempty"` + TLS bool `json:"tls"` +} + +// ZookeeperClusterSpec Representation of a Strimzi-managed ZooKeeper "cluster". +type ZookeeperClusterSpec struct { + Replicas int32 `json:"replicas,omitempty"` + Storage KafkaStorage `json:"storage,omitempty"` +} + +// KafkaStorage The type of storage used by Kafka brokers +type KafkaStorage struct { + StorageType KafkaStorageType `json:"type,omitempty"` +} + +// KafkaStorageType defines the enum for Kafka storage +type KafkaStorageType string + +const ( + // KafkaEphemeralStorage ... + KafkaEphemeralStorage KafkaStorageType = "ephemeral" +) + +// KafkaStatus defines the observed state of Kafka +type KafkaStatus struct { + Listeners []ListenerStatus `json:"listeners,omitempty"` + Conditions []KafkaCondition `json:"conditions,omitempty"` +} + +// KafkaCondition conditions for a Kafka resource +type KafkaCondition struct { + Type string `json:"type"` + Status corev1.ConditionStatus `json:"status"` + // This is defined by the Strimzi Java API as String + LastTransitionTime string `json:"lastTransitionTime,omitempty"` + // we don't have all possibilities for this type, leave as string and compare with known values + Reason string `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +const ( + // KafkaConditionTypeReady ... + KafkaConditionTypeReady = "Ready" + // KafkaLastTransitionTimeLayout the default date layout for KafkaCondition + KafkaLastTransitionTimeLayout = time.RFC3339 +) + +// ListenerStatus defines a single listener +type ListenerStatus struct { + Type string `json:"type,omitempty"` + Addresses []ListenerAddress `json:"addresses,omitempty"` +} + +// ListenerAddress defines a single address of particular listener +type ListenerAddress struct { + Host string `json:"host,omitempty"` + Port int32 `json:"port,omitempty"` +} + +// Kafka is the Schema for the kafkas API +// +kubebuilder:object:root=true +type Kafka struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KafkaSpec `json:"spec,omitempty"` + Status KafkaStatus `json:"status,omitempty"` +} + +// KafkaList contains a list of Kafka +// +kubebuilder:object:root=true +type KafkaList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Kafka `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Kafka{}, &KafkaList{}) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/kafkatopic_types.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/kafkatopic_types.go new file mode 100644 index 00000000000..290d134e7a1 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/kafkatopic_types.go @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1beta2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// KafkaTopicSpec defines the desired state of KafkaTopic +type KafkaTopicSpec struct { + Partitions int32 `json:"partitions,omitempty"` + Replicas int32 `json:"replicas,omitempty"` + TopicName string `json:"topicName,omitempty"` +} + +// KafkaTopicStatus defines the observed state of KafkaTopic +type KafkaTopicStatus struct { +} + +// KafkaTopic is the Schema for the kafkatopics API +// +kubebuilder:object:root=true +type KafkaTopic struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KafkaTopicSpec `json:"spec,omitempty"` + Status KafkaTopicStatus `json:"status,omitempty"` +} + +// KafkaTopicList contains a list of KafkaTopic +// +kubebuilder:object:root=true +type KafkaTopicList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []KafkaTopic `json:"items"` +} + +func init() { + SchemeBuilder.Register(&KafkaTopic{}, &KafkaTopicList{}) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/register.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/register.go new file mode 100644 index 00000000000..165f72231a4 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/register.go @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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: Boilerplate only. Ignore this file. + +// Package v1beta2 contains API Schema definitions for the kafka v1beta2 API group +// +kubebuilder:skip +// +k8s:deepcopy-gen=package,register +// +groupName=kafka.strimzi.io +package v1beta2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "kafka.strimzi.io", Version: "v1beta2"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} +) diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/zz_generated.deepcopy.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/zz_generated.deepcopy.go new file mode 100644 index 00000000000..4c36b51dfc7 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2/zz_generated.deepcopy.go @@ -0,0 +1,392 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright 2021 Red Hat, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 v1beta2 + +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 *EntityOperatorSpec) DeepCopyInto(out *EntityOperatorSpec) { + *out = *in + out.TopicOperator = in.TopicOperator + out.UserOperator = in.UserOperator +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EntityOperatorSpec. +func (in *EntityOperatorSpec) DeepCopy() *EntityOperatorSpec { + if in == nil { + return nil + } + out := new(EntityOperatorSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EntityTopicOperatorSpec) DeepCopyInto(out *EntityTopicOperatorSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EntityTopicOperatorSpec. +func (in *EntityTopicOperatorSpec) DeepCopy() *EntityTopicOperatorSpec { + if in == nil { + return nil + } + out := new(EntityTopicOperatorSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EntityUserOperatorSpec) DeepCopyInto(out *EntityUserOperatorSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EntityUserOperatorSpec. +func (in *EntityUserOperatorSpec) DeepCopy() *EntityUserOperatorSpec { + if in == nil { + return nil + } + out := new(EntityUserOperatorSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GenericKafkaListener) DeepCopyInto(out *GenericKafkaListener) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenericKafkaListener. +func (in *GenericKafkaListener) DeepCopy() *GenericKafkaListener { + if in == nil { + return nil + } + out := new(GenericKafkaListener) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Kafka) DeepCopyInto(out *Kafka) { + *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 Kafka. +func (in *Kafka) DeepCopy() *Kafka { + if in == nil { + return nil + } + out := new(Kafka) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Kafka) 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 *KafkaClusterSpec) DeepCopyInto(out *KafkaClusterSpec) { + *out = *in + if in.Listeners != nil { + in, out := &in.Listeners, &out.Listeners + *out = make([]GenericKafkaListener, len(*in)) + copy(*out, *in) + } + out.Storage = in.Storage + in.Config.DeepCopyInto(&out.Config) + in.JvmOptions.DeepCopyInto(&out.JvmOptions) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaClusterSpec. +func (in *KafkaClusterSpec) DeepCopy() *KafkaClusterSpec { + if in == nil { + return nil + } + out := new(KafkaClusterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaCondition) DeepCopyInto(out *KafkaCondition) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaCondition. +func (in *KafkaCondition) DeepCopy() *KafkaCondition { + if in == nil { + return nil + } + out := new(KafkaCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaList) DeepCopyInto(out *KafkaList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Kafka, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaList. +func (in *KafkaList) DeepCopy() *KafkaList { + if in == nil { + return nil + } + out := new(KafkaList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KafkaList) 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 KafkaMap) DeepCopyInto(out *KafkaMap) { + { + in := &in + clone := in.DeepCopy() + *out = *clone + } +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaSpec) DeepCopyInto(out *KafkaSpec) { + *out = *in + in.Kafka.DeepCopyInto(&out.Kafka) + out.Zookeeper = in.Zookeeper + out.EntityOperator = in.EntityOperator +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaSpec. +func (in *KafkaSpec) DeepCopy() *KafkaSpec { + if in == nil { + return nil + } + out := new(KafkaSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaStatus) DeepCopyInto(out *KafkaStatus) { + *out = *in + if in.Listeners != nil { + in, out := &in.Listeners, &out.Listeners + *out = make([]ListenerStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]KafkaCondition, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaStatus. +func (in *KafkaStatus) DeepCopy() *KafkaStatus { + if in == nil { + return nil + } + out := new(KafkaStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaStorage) DeepCopyInto(out *KafkaStorage) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaStorage. +func (in *KafkaStorage) DeepCopy() *KafkaStorage { + if in == nil { + return nil + } + out := new(KafkaStorage) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaTopic) DeepCopyInto(out *KafkaTopic) { + *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 KafkaTopic. +func (in *KafkaTopic) DeepCopy() *KafkaTopic { + if in == nil { + return nil + } + out := new(KafkaTopic) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KafkaTopic) 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 *KafkaTopicList) DeepCopyInto(out *KafkaTopicList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KafkaTopic, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaTopicList. +func (in *KafkaTopicList) DeepCopy() *KafkaTopicList { + if in == nil { + return nil + } + out := new(KafkaTopicList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KafkaTopicList) 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 *KafkaTopicSpec) DeepCopyInto(out *KafkaTopicSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaTopicSpec. +func (in *KafkaTopicSpec) DeepCopy() *KafkaTopicSpec { + if in == nil { + return nil + } + out := new(KafkaTopicSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KafkaTopicStatus) DeepCopyInto(out *KafkaTopicStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KafkaTopicStatus. +func (in *KafkaTopicStatus) DeepCopy() *KafkaTopicStatus { + if in == nil { + return nil + } + out := new(KafkaTopicStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ListenerAddress) DeepCopyInto(out *ListenerAddress) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerAddress. +func (in *ListenerAddress) DeepCopy() *ListenerAddress { + if in == nil { + return nil + } + out := new(ListenerAddress) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ListenerStatus) DeepCopyInto(out *ListenerStatus) { + *out = *in + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]ListenerAddress, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerStatus. +func (in *ListenerStatus) DeepCopy() *ListenerStatus { + if in == nil { + return nil + } + out := new(ListenerStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ZookeeperClusterSpec) DeepCopyInto(out *ZookeeperClusterSpec) { + *out = *in + out.Storage = in.Storage +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZookeeperClusterSpec. +func (in *ZookeeperClusterSpec) DeepCopy() *ZookeeperClusterSpec { + if in == nil { + return nil + } + out := new(ZookeeperClusterSpec) + in.DeepCopyInto(out) + return out +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka_test.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka_test.go new file mode 100644 index 00000000000..6044cce17fa --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka_test.go @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package infrastructure + +import ( + "reflect" + "testing" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/log" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/logger" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/operator" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/meta" +) + +func Test_getKafkaInstanceWithName(t *testing.T) { + ns := t.Name() + + kafka := &v1beta2.Kafka{ + TypeMeta: v1.TypeMeta{Kind: "Kafka", APIVersion: "kafka.strimzi.io/v1beta2"}, + ObjectMeta: v1.ObjectMeta{ + Name: "kafka", + Namespace: ns, + }, + Spec: v1beta2.KafkaSpec{ + Kafka: v1beta2.KafkaClusterSpec{ + Replicas: 1, + Listeners: []v1beta2.GenericKafkaListener{ + { + Name: "plain", + Port: 9092, + TLS: false, + ListenerType: "internal", + }, + { + Name: "tls", + Port: 9093, + TLS: true, + ListenerType: "internal", + }, + }, + }, + }, + } + + cli := NewFakeClientBuilder().AddK8sObjects(kafka).Build() + + type args struct { + name string + namespace string + client *client.Client + } + tests := []struct { + name string + args args + want *v1beta2.Kafka + wantErr bool + }{ + { + "KafkaInstanceExists", + args{ + "kafka", + ns, + cli, + }, + kafka, + false, + }, + { + "KafkaInstanceNotExists", + args{ + "kafka1", + ns, + cli, + }, + nil, + false, + }, + } + context := operator.Context{ + Client: cli, + Log: logger.Logger{Logger: log.Log.WithName("test")}, + Scheme: meta.GetRegisteredSchema(), + } + kafkaHandler := NewKafkaHandler(context) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := kafkaHandler.FetchKafkaInstance(types.NamespacedName{Name: tt.args.name, Namespace: tt.args.namespace}) + if (err != nil) != tt.wantErr { + t.Errorf("getKafkaInstanceWithName() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("getKafkaInstanceWithName() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_resolveKafkaServerURI(t *testing.T) { + type args struct { + kafka *v1beta2.Kafka + } + tests := []struct { + name string + args args + want string + }{ + { + "ResolveKafkaServerURI", + args{ + &v1beta2.Kafka{ + Status: v1beta2.KafkaStatus{ + Listeners: []v1beta2.ListenerStatus{ + { + Type: "tls", + Addresses: []v1beta2.ListenerAddress{ + { + Host: "kafka1", + Port: 9093, + }, + }, + }, + { + Type: "plain", + Addresses: []v1beta2.ListenerAddress{ + { + Host: "kafka", + Port: 9092, + }, + }, + }, + }, + }, + }, + }, + "kafka:9092", + }, + } + cli := NewFakeClientBuilder().Build() + context := operator.Context{ + Client: cli, + Log: logger.Logger{Logger: log.Log.WithName("test")}, + Scheme: meta.GetRegisteredSchema(), + } + kafkaHandler := NewKafkaHandler(context) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got, _ := kafkaHandler.ResolveKafkaServerURI(tt.args.kafka); got != tt.want { + t.Errorf("ResolveKafkaServerURI() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak.go new file mode 100644 index 00000000000..e18bfe2545c --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak.go @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package infrastructure + +import ( + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/operator" +) + +const ( + // KeycloakKind refers to Keycloak Kind + KeycloakKind = "Keycloak" +) + +var ( + // KeycloakAPIVersion refers to kafka APIVersion + KeycloakAPIVersion = v1alpha1.SchemeGroupVersion.String() + + keycloakServerGroup = v1alpha1.SchemeGroupVersion.Group +) + +// KeycloakHandler ... +type KeycloakHandler interface { + IsKeycloakAvailable() bool +} + +type keycloakHandler struct { + operator.Context +} + +// NewKeycloakHandler ... +func NewKeycloakHandler(context operator.Context) KeycloakHandler { + return &keycloakHandler{ + context, + } +} + +// IsKeycloakAvailable checks if Strimzi CRD is available in the cluster +func (k *keycloakHandler) IsKeycloakAvailable() bool { + return k.Client.HasServerGroup(keycloakServerGroup) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/group.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/group.go new file mode 100644 index 00000000000..47c684cf6c0 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/group.go @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// Package keycloak contains keycloak API versions. +// +// This file ensures Go source parsers acknowledge the keycloak package +// and any child packages. It can be removed if any other Go source files are +// added to this package. +package keycloak diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/doc.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/doc.go new file mode 100644 index 00000000000..018b0617fd4 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/doc.go @@ -0,0 +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. + */ + +// Package v1alpha1 contains API Schema definitions for the keycloak v1alpha1 API group +// +k8s:deepcopy-gen=package,register +// +groupName=keycloak.org +package v1alpha1 diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloak_types.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloak_types.go new file mode 100644 index 00000000000..d2494f7ec1f --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloak_types.go @@ -0,0 +1,320 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1alpha1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// TLSTerminationType ... +type TLSTerminationType string + +var ( + // DefaultTLSTermintation ... + DefaultTLSTermintation TLSTerminationType + // ReencryptTLSTerminationType ... + ReencryptTLSTerminationType TLSTerminationType = "reencrypt" + // PassthroughTLSTerminationType ... + PassthroughTLSTerminationType TLSTerminationType = "passthrough" +) + +// KeycloakSpec defines the desired state of Keycloak. +// +k8s:openapi-gen=true +type KeycloakSpec struct { + // When set to true, this Keycloak will be marked as unmanaged and will not be managed by this operator. + // It can then be used for targeting purposes. + // +optional + Unmanaged bool `json:"unmanaged,omitempty"` + // Contains configuration for external Keycloak instances. Unmanaged needs to be set to true to use this. + // +optional + External KeycloakExternal `json:"external"` + // A list of extensions, where each one is a URL to a JAR files that will be deployed in Keycloak. + // +listType=set + // +optional + Extensions []string `json:"extensions,omitempty"` + // Number of Keycloak instances in HA mode. Default is 1. + // +optional + Instances int `json:"instances,omitempty"` + // Controls external Ingress/Route settings. + // +optional + ExternalAccess KeycloakExternalAccess `json:"externalAccess,omitempty"` + // Controls external database settings. + // Using an external database requires providing a secret containing credentials + // as well as connection details. Here's an example of such secret: + // + // apiVersion: v1 + // kind: Secret + // metadata: + // name: keycloak-db-secret + // namespace: keycloak + // stringData: + // POSTGRES_DATABASE: + // POSTGRES_EXTERNAL_ADDRESS: + // POSTGRES_EXTERNAL_PORT: + // # Strongly recommended to use <'Keycloak CR Name'-postgresql> + // POSTGRES_HOST: + // POSTGRES_PASSWORD: + // # Required for AWS Backup functionality + // POSTGRES_SUPERUSER: true + // POSTGRES_USERNAME: + // type: Opaque + // + // Both POSTGRES_EXTERNAL_ADDRESS and POSTGRES_EXTERNAL_PORT are specifically required for creating + // connection to the external database. The secret name is created using the following convention: + // -db-secret + // + // For more information, please refer to the Operator documentation. + // +optional + ExternalDatabase KeycloakExternalDatabase `json:"externalDatabase,omitempty"` + // Profile used for controlling Operator behavior. Default is empty. + // +optional + Profile string `json:"profile,omitempty"` + // Specify PodDisruptionBudget configuration. + // +optional + PodDisruptionBudget PodDisruptionBudgetConfig `json:"podDisruptionBudget,omitempty"` + // Resources (Requests and Limits) for KeycloakDeployment. + // +optional + KeycloakDeploymentSpec KeycloakDeploymentSpec `json:"keycloakDeploymentSpec,omitempty"` + // Resources (Requests and Limits) for PostgresDeployment. + // +optional + PostgresDeploymentSpec PostgresqlDeploymentSpec `json:"postgresDeploymentSpec,omitempty"` + // Specify Migration configuration + // +optional + Migration MigrateConfig `json:"migration,omitempty"` + // Name of the StorageClass for Postgresql Persistent Volume Claim + // +optional + StorageClassName *string `json:"storageClassName,omitempty"` + // Specify PodAntiAffinity settings for Keycloak deployment in Multi AZ + // +optional + MultiAvailablityZones MultiAvailablityZonesConfig `json:"multiAvailablityZones,omitempty"` +} + +// DeploymentSpec ... +type DeploymentSpec struct { + // Resources (Requests and Limits) for the Pods. + // +optional + Resources corev1.ResourceRequirements `json:"resources,omitempty"` +} + +// KeycloakDeploymentSpec ... +type KeycloakDeploymentSpec struct { + DeploymentSpec `json:",inline"` + // Experimental section + // NOTE: This section might change or get removed without any notice. It may also cause + // the deployment to behave in an unpredictable fashion. Please use with care. + // +optional + Experimental ExperimentalSpec `json:"experimental,omitempty"` +} + +// PostgresqlDeploymentSpec ... +type PostgresqlDeploymentSpec struct { + DeploymentSpec `json:",inline"` +} + +// ExperimentalSpec ... +type ExperimentalSpec struct { + // Arguments to the entrypoint. Translates into Container CMD. + // +optional + Args []string `json:"args,omitempty"` + // Container command. Translates into Container ENTRYPOINT. + // +optional + Command []string `json:"command,omitempty"` + // List of environment variables to set in the container. + // +optional + // +patchMergeKey=name + // +patchStrategy=merge + Env []corev1.EnvVar `json:"env,omitempty" patchStrategy:"merge" patchMergeKey:"name"` + // Additional volume mounts + // +optional + Volumes VolumesSpec `json:"volumes,omitempty"` + // Affinity settings + //+optional + Affinity *corev1.Affinity `json:"affinity,omitempty"` + // ServiceAccountName settings + // +optional + ServiceAccountName string `json:"serviceAccountName,omitempty"` +} + +// VolumesSpec ... +type VolumesSpec struct { + Items []VolumeSpec `json:"items,omitempty"` + // Permissions mode. + // +optional + DefaultMode *int32 `json:"defaultMode,omitempty"` +} + +// VolumeSpec ... +type VolumeSpec struct { + // Volume name + Name string `json:"name,omitempty"` + // An absolute path where to mount it + MountPath string `json:"mountPath"` + // Allow multiple configmaps to mount to the same directory + // +optional + ConfigMaps []string `json:"configMaps,omitempty"` + // Secret mount + // +optional + Secrets []string `json:"secrets,omitempty"` + // Mount details + // +optional + Items []corev1.KeyToPath `json:"items,omitempty" protobuf:"bytes,2,rep,name=items"` +} + +// KeycloakExternal ... +type KeycloakExternal struct { + // If set to true, this Keycloak will be treated as an external instance. + // The unmanaged field also needs to be set to true if this field is true. + Enabled bool `json:"enabled,omitempty"` + // The URL to use for the keycloak admin API. Needs to be set if external is true. + // +optional + URL string `json:"url,omitempty"` +} + +// KeycloakExternalAccess ... +type KeycloakExternalAccess struct { + // If set to true, the Operator will create an Ingress or a Route + // pointing to Keycloak. + Enabled bool `json:"enabled,omitempty"` + // TLS Termination type for the external access. Setting this field to "reencrypt" will + // terminate TLS on the Ingress/Route level. Setting this field to "passthrough" will + // send encrypted traffic to the Pod. If unspecified, defaults to "reencrypt". + // Note, that this setting has no effect on Ingress + // as Ingress TLS settings are not reconciled by this operator. In other words, + // Ingress TLS configuration is the same in both cases and it is up to the user + // to configure TLS section of the Ingress. + TLSTermination TLSTerminationType `json:"tlsTermination,omitempty"` + // If set, the Operator will use value of host for Ingress host + // instead of default value keycloak.local. Using this setting in OpenShift + // environment will result an error. Only users with special permissions are + // allowed to modify the hostname. + // +optional + Host string `json:"host,omitempty"` +} + +// KeycloakExternalDatabase ... +type KeycloakExternalDatabase struct { + // If set to true, the Operator will use an external database. + // pointing to Keycloak. + Enabled bool `json:"enabled,omitempty"` +} + +// PodDisruptionBudgetConfig ... +type PodDisruptionBudgetConfig struct { + // If set to true, the operator will create a PodDistruptionBudget for the Keycloak deployment and set its `maxUnavailable` value to 1. + Enabled bool `json:"enabled,omitempty"` +} + +// MultiAvailablityZonesConfig ... +type MultiAvailablityZonesConfig struct { + // If set to true, the operator will create a podAntiAffinity settings for the Keycloak deployment. + Enabled bool `json:"enabled,omitempty"` +} + +// MigrateConfig ... +type MigrateConfig struct { + // Specify migration strategy + // +optional + MigrationStrategy MigrationStrategy `json:"strategy,omitempty"` + // Set it to config backup policy for migration + // +optional + Backups BackupConfig `json:"backups,omitempty"` +} + +// MigrationStrategy ... +type MigrationStrategy string + +var ( + // NoStrategy ... + NoStrategy MigrationStrategy + // StrategyRecreate ... + StrategyRecreate MigrationStrategy = "recreate" + // StrategyRolling ... + StrategyRolling MigrationStrategy = "rolling" +) + +// BackupConfig ... +type BackupConfig struct { + // If set to true, the operator will do database backup before doing migration + Enabled bool `json:"enabled,omitempty"` +} + +// +k8s:openapi-gen=true + +// KeycloakStatus defines the observed state of Keycloak. +type KeycloakStatus struct { + // Current phase of the operator. + Phase StatusPhase `json:"phase"` + // Human-readable message indicating details about current operator phase or error. + Message string `json:"message"` + // True if all resources are in a ready state and all work is done. + Ready bool `json:"ready"` + // A map of all the secondary resources types and names created for this CR. e.g "Deployment": [ "DeploymentName1", "DeploymentName2" ]. + SecondaryResources map[string][]string `json:"secondaryResources,omitempty"` + // Version of Keycloak or RHSSO running on the cluster. + Version string `json:"version"` + // An internal URL (service name) to be used by the admin client. + InternalURL string `json:"internalURL"` + // External URL for accessing Keycloak instance from outside the cluster. Is identical to external.URL if it's specified, otherwise is computed (e.g. from Ingress). + ExternalURL string `json:"externalURL,omitempty"` + // The secret where the admin credentials are to be found. + CredentialSecret string `json:"credentialSecret"` +} + +// StatusPhase ... +type StatusPhase string + +var ( + // NoPhase ... + NoPhase StatusPhase + // PhaseReconciling ... + PhaseReconciling StatusPhase = "reconciling" + // PhaseFailing ... + PhaseFailing StatusPhase = "failing" + // PhaseInitialising ... + PhaseInitialising StatusPhase = "initialising" +) + +// +genclient +// +k8s:openapi-gen=true +// +kubebuilder:subresource:status +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Keycloak is the Schema for the keycloaks API. +type Keycloak struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KeycloakSpec `json:"spec,omitempty"` + Status KeycloakStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// KeycloakList contains a list of Keycloak. +type KeycloakList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Keycloak `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Keycloak{}, &KeycloakList{}) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloakbackup_types.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloakbackup_types.go new file mode 100644 index 00000000000..3b6cf258670 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloakbackup_types.go @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// KeycloakBackupSpec defines the desired state of KeycloakBackup. +// +k8s:openapi-gen=true +type KeycloakBackupSpec struct { + // Controls automatic restore behavior. + // Currently not implemented. + // + // In the future this will be used to trigger automatic restore for a given KeycloakBackup. + // Each backup will correspond to a single snapshot of the database (stored either in a + // Persistent Volume or AWS). If a user wants to restore it, all he/she needs to do is to + // change this flag to true. + // Potentially, it will be possible to restore a single backup multiple times. + // +optional + Restore bool `json:"restore,omitempty"` + // If provided, an automatic database backup will be created on AWS S3 instead of + // a local Persistent Volume. If this property is not provided - a local + // Persistent Volume backup will be chosen. + // +optional + AWS KeycloakAWSSpec `json:"aws,omitempty"` + // Selector for looking up Keycloak Custom Resources. + // +kubebuilder:validation:Required + InstanceSelector *metav1.LabelSelector `json:"instanceSelector,omitempty"` + // Name of the StorageClass for Postgresql Backup Persistent Volume Claim + // +optional + StorageClassName *string `json:"storageClassName,omitempty"` +} + +// KeycloakAWSSpec defines the desired state of KeycloakBackupSpec. +// +k8s:openapi-gen=true +type KeycloakAWSSpec struct { + // If provided, the database backup will be encrypted. + // Provides a secret name used for encrypting database data. + // The secret needs to be in the following form: + // + // apiVersion: v1 + // kind: Secret + // metadata: + // name: + // type: Opaque + // stringData: + // GPG_PUBLIC_KEY: + // GPG_TRUST_MODEL: + // GPG_RECIPIENT: + // + // For more information, please refer to the Operator documentation. + // +optional + EncryptionKeySecretName string `json:"encryptionKeySecretName,omitempty"` + // Provides a secret name used for connecting to AWS S3 Service. + // The secret needs to be in the following form: + // + // apiVersion: v1 + // kind: Secret + // metadata: + // name: + // type: Opaque + // stringData: + // AWS_S3_BUCKET_NAME: + // AWS_ACCESS_KEY_ID: + // AWS_SECRET_ACCESS_KEY: + // + // For more information, please refer to the Operator documentation. + // +kubebuilder:validation:Required + CredentialsSecretName string `json:"credentialsSecretName,omitempty"` + // If specified, it will be used as a schedule for creating a CronJob. + // +optional + Schedule string `json:"schedule,omitempty"` +} + +// BackupStatusPhase ... +type BackupStatusPhase string + +var ( + // BackupPhaseNone ... + BackupPhaseNone BackupStatusPhase + // BackupPhaseReconciling ... + BackupPhaseReconciling BackupStatusPhase = "reconciling" + // BackupPhaseCreated ... + BackupPhaseCreated BackupStatusPhase = "created" + // BackupPhaseRestored ... + BackupPhaseRestored BackupStatusPhase = "restored" + // BackupPhaseFailing ... + BackupPhaseFailing BackupStatusPhase = "failing" +) + +// +k8s:openapi-gen=true + +// KeycloakBackupStatus defines the observed state of KeycloakBackup. +type KeycloakBackupStatus struct { + // Current phase of the operator. + Phase BackupStatusPhase `json:"phase"` + // Human-readable message indicating details about current operator phase or error. + Message string `json:"message"` + // True if all resources are in a ready state and all work is done. + Ready bool `json:"ready"` + // A map of all the secondary resources types and names created for this CR. e.g "Deployment": [ "DeploymentName1", "DeploymentName2" ] + SecondaryResources map[string][]string `json:"secondaryResources,omitempty"` +} + +// +genclient +// +k8s:openapi-gen=true +// +kubebuilder:subresource:status +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// KeycloakBackup is the Schema for the keycloakbackups API. +type KeycloakBackup struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KeycloakBackupSpec `json:"spec,omitempty"` + Status KeycloakBackupStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// KeycloakBackupList contains a list of KeycloakBackup. +type KeycloakBackupList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []KeycloakBackup `json:"items"` +} + +func init() { + SchemeBuilder.Register(&KeycloakBackup{}, &KeycloakBackupList{}) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloakclient_types.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloakclient_types.go new file mode 100644 index 00000000000..7f1db28180c --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloakclient_types.go @@ -0,0 +1,410 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1alpha1 + +import ( + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// KeycloakClientSpec defines the desired state of KeycloakClient. +// +k8s:openapi-gen=true +type KeycloakClientSpec struct { + // Selector for looking up KeycloakRealm Custom Resources. + // +kubebuilder:validation:Required + RealmSelector *metav1.LabelSelector `json:"realmSelector"` + // Keycloak Client REST object. + // +kubebuilder:validation:Required + Client *KeycloakAPIClient `json:"client"` + // Client Roles + // +optional + // +listType=map + // +listMapKey=name + Roles []RoleRepresentation `json:"roles,omitempty"` + // Scope Mappings + // +optional + ScopeMappings *MappingsRepresentation `json:"scopeMappings,omitempty"` +} + +// MappingsRepresentation ... +// https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_mappingsrepresentation +type MappingsRepresentation struct { + // Client Mappings + // +optional + ClientMappings map[string]ClientMappingsRepresentation `json:"clientMappings,omitempty"` + + // Realm Mappings + // +optional + RealmMappings []RoleRepresentation `json:"realmMappings,omitempty"` +} + +// ClientMappingsRepresentation ... +// https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_clientmappingsrepresentation +type ClientMappingsRepresentation struct { + // Client + // +optional + Client string `json:"client,omitempty"` + + // ID + // +optional + ID string `json:"id,omitempty"` + + // Mappings + // +optional + Mappings []RoleRepresentation `json:"mappings,omitempty"` +} + +// KeycloakAPIClient ... +type KeycloakAPIClient struct { + // Client ID. If not specified, automatically generated. + // +optional + ID string `json:"id,omitempty"` + // Client ID. + // +kubebuilder:validation:Required + ClientID string `json:"clientId"` + // Client name. + // +optional + Name string `json:"name,omitempty"` + // Surrogate Authentication Required option. + // +optional + SurrogateAuthRequired bool `json:"surrogateAuthRequired,omitempty"` + // Client enabled flag. + // +optional + Enabled bool `json:"enabled,omitempty"` + // What Client authentication type to use. + // +optional + ClientAuthenticatorType string `json:"clientAuthenticatorType,omitempty"` + // Client Secret. The Operator will automatically create a Secret based on this value. + // +optional + Secret string `json:"secret,omitempty"` + // Application base URL. + // +optional + BaseURL string `json:"baseUrl,omitempty"` + // Application Admin URL. + // +optional + AdminURL string `json:"adminUrl,omitempty"` + // Application root URL. + // +optional + RootURL string `json:"rootUrl,omitempty"` + // Client description. + // +optional + Description string `json:"description,omitempty"` + // Default Client roles. + // +optional + DefaultRoles []string `json:"defaultRoles,omitempty"` + // A list of valid Redirection URLs. + // +optional + RedirectUris []string `json:"redirectUris,omitempty"` + // A list of valid Web Origins. + // +optional + WebOrigins []string `json:"webOrigins,omitempty"` + // Not Before setting. + // +optional + NotBefore int `json:"notBefore,omitempty"` + // True if a client supports only Bearer Tokens. + // +optional + BearerOnly bool `json:"bearerOnly,omitempty"` + // True if Consent Screen is required. + // +optional + ConsentRequired bool `json:"consentRequired,omitempty"` + // True if Standard flow is enabled. + // +optional + StandardFlowEnabled bool `json:"standardFlowEnabled"` + // True if Implicit flow is enabled. + // +optional + ImplicitFlowEnabled bool `json:"implicitFlowEnabled"` + // True if Direct Grant is enabled. + // +optional + DirectAccessGrantsEnabled bool `json:"directAccessGrantsEnabled"` + // True if Service Accounts are enabled. + // +optional + ServiceAccountsEnabled bool `json:"serviceAccountsEnabled,omitempty"` + // True if this is a public Client. + // +optional + PublicClient bool `json:"publicClient"` + // True if this client supports Front Channel logout. + // +optional + FrontchannelLogout bool `json:"frontchannelLogout,omitempty"` + // Protocol used for this Client. + // +optional + Protocol string `json:"protocol,omitempty"` + // Client Attributes. + // +optional + Attributes map[string]string `json:"attributes,omitempty"` + // True if Full Scope is allowed. + // +optional + FullScopeAllowed *bool `json:"fullScopeAllowed,omitempty"` + // Node registration timeout. + // +optional + NodeReRegistrationTimeout int `json:"nodeReRegistrationTimeout,omitempty"` + // Protocol Mappers. + // +optional + ProtocolMappers []KeycloakProtocolMapper `json:"protocolMappers,omitempty"` + // True to use a Template Config. + // +optional + UseTemplateConfig bool `json:"useTemplateConfig,omitempty"` + // True to use Template Scope. + // +optional + UseTemplateScope bool `json:"useTemplateScope,omitempty"` + // True to use Template Mappers. + // +optional + UseTemplateMappers bool `json:"useTemplateMappers,omitempty"` + // Access options. + // +optional + Access map[string]bool `json:"access,omitempty"` + // A list of optional client scopes. Optional client scopes are + // applied when issuing tokens for this client, but only when they + // are requested by the scope parameter in the OpenID Connect + // authorization request. + // +optional + OptionalClientScopes []string `json:"optionalClientScopes,omitempty"` + // A list of default client scopes. Default client scopes are + // always applied when issuing OpenID Connect tokens or SAML + // assertions for this client. + // +optional + DefaultClientScopes []string `json:"defaultClientScopes,omitempty"` + // True if fine-grained authorization support is enabled for this client. + // +optional + AuthorizationServicesEnabled bool `json:"authorizationServicesEnabled,omitempty"` + // Authorization settings for this resource server. + // +optional + AuthorizationSettings *KeycloakResourceServer `json:"authorizationSettings,omitempty"` +} + +// KeycloakProtocolMapper ... +type KeycloakProtocolMapper struct { + // Protocol Mapper ID. + // +optional + ID string `json:"id,omitempty"` + // Protocol Mapper Name. + // +optional + Name string `json:"name,omitempty"` + // Protocol to use. + // +optional + Protocol string `json:"protocol,omitempty"` + // Protocol Mapper to use + // +optional + ProtocolMapper string `json:"protocolMapper,omitempty"` + // True if Consent Screen is required. + // +optional + ConsentRequired bool `json:"consentRequired,omitempty"` + // Text to use for displaying Consent Screen. + // +optional + ConsentText string `json:"consentText,omitempty"` + // Config options. + // +optional + Config map[string]string `json:"config,omitempty"` +} + +// KeycloakResourceServer ... +// https://www.keycloak.org/docs-api/12.0/rest-api/index.html#_resourceserverrepresentation +type KeycloakResourceServer struct { + // True if resources should be managed remotely by the resource server. + // +optional + AllowRemoteResourceManagement bool `json:"allowRemoteResourceManagement,omitempty"` + // Client ID. + // +optional + ClientID string `json:"clientId,omitempty"` + // The decision strategy dictates how permissions are evaluated and how a + // final decision is obtained. 'Affirmative' means that at least one + // permission must evaluate to a positive decision in order to grant access + // to a resource and its scopes. 'Unanimous' means that all permissions must + // evaluate to a positive decision in order for the final decision to be also positive. + // +optional + DecisionStrategy string `json:"decisionStrategy,omitempty"` + // ID. + // +optional + ID string `json:"id,omitempty"` + // Name. + // +optional + Name string `json:"name,omitempty"` + // Policies. + // +optional + Policies []KeycloakPolicy `json:"policies,omitempty"` + // The policy enforcement mode dictates how policies are enforced when evaluating authorization requests. + // 'Enforcing' means requests are denied by default even when there is no policy associated with a given resource. + // 'Permissive' means requests are allowed even when there is no policy associated with a given resource. + // 'Disabled' completely disables the evaluation of policies and allows access to any resource. + // +optional + PolicyEnforcementMode string `json:"policyEnforcementMode,omitempty"` + // Resources. + // +optional + Resources []KeycloakResource `json:"resources,omitempty"` + // Authorization Scopes. + // +optional + Scopes []KeycloakScope `json:"scopes,omitempty"` +} + +// KeycloakPolicy ... +// https://www.keycloak.org/docs-api/12.0/rest-api/index.html#_policyrepresentation +type KeycloakPolicy struct { + // Config. + // +optional + Config map[string]string `json:"config,omitempty"` + // The decision strategy dictates how the policies associated with a given permission are evaluated and how + // a final decision is obtained. 'Affirmative' means that at least one policy must evaluate to a positive + // decision in order for the final decision to be also positive. 'Unanimous' means that all policies must + // evaluate to a positive decision in order for the final decision to be also positive. 'Consensus' means + // that the number of positive decisions must be greater than the number of negative decisions. If the number + // of positive and negative is the same, the final decision will be negative. + // +optional + DecisionStrategy string `json:"decisionStrategy,omitempty"` + // A description for this policy. + // +optional + Description string `json:"description,omitempty"` + // ID. + // +optional + ID string `json:"id,omitempty"` + // The logic dictates how the policy decision should be made. If 'Positive', the resulting effect + // (permit or deny) obtained during the evaluation of this policy will be used to perform a decision. + // If 'Negative', the resulting effect will be negated, in other words, a permit becomes a deny and vice-versa. + // +optional + Logic string `json:"logic,omitempty"` + // The name of this policy. + // +optional + Name string `json:"name,omitempty"` + // Owner. + // +optional + Owner string `json:"owner,omitempty"` + // Policies. + // +optional + Policies []string `json:"policies,omitempty"` + // Resources. + // +optional + Resources []string `json:"resources,omitempty"` + // Resources Data. + // +optional + ResourcesData []KeycloakResource `json:"resourcesData,omitempty"` + // Scopes. + // +optional + Scopes []string `json:"scopes,omitempty"` + // Type. + // +optional + Type string `json:"type,omitempty"` + // Scopes Data. + // +optional + ScopesData []apiextensionsv1.JSON `json:"scopesData,omitempty"` + // TODO: JSON struct is a workaround for the lack of support for recursive types + // in CRD validation schemas. Keycloak will do validation for this field. Read more: + // https://github.com/kubernetes/kubernetes/issues/62872 +} + +// KeycloakResource ... +// https://www.keycloak.org/docs-api/12.0/rest-api/index.html#_resourcerepresentation +type KeycloakResource struct { + // ID. + // +optional + ID string `json:"_id,omitempty"` + // The attributes associated with the resource. + // +optional + Attributes map[string]string `json:"attributes,omitempty"` + // A unique name for this resource. The name can be used to uniquely identify a resource, useful when + // querying for a specific resource. + // +optional + DisplayName string `json:"displayName,omitempty"` + // An URI pointing to an icon. + // +optional + IconURI string `json:"icon_uri,omitempty"` + // A unique name for this resource. The name can be used to uniquely identify a resource, useful when + // querying for a specific resource. + // +optional + Name string `json:"name,omitempty"` + // True if the access to this resource can be managed by the resource owner. + // +optional + OwnerManagedAccess bool `json:"ownerManagedAccess,omitempty"` + // The type of this resource. It can be used to group different resource instances with the same type. + // +optional + Type string `json:"type,omitempty"` + // Set of URIs which are protected by resource. + // +optional + Uris []string `json:"uris,omitempty"` + // The scopes associated with this resource. + // +optional + Scopes []apiextensionsv1.JSON `json:"scopes,omitempty"` + // TODO: JSON struct is a workaround for the lack of support for recursive types + // in CRD validation schemas. Keycloak will do validation for this field. Read more: + // https://github.com/kubernetes/kubernetes/issues/62872 +} + +// KeycloakScope ... +// https://www.keycloak.org/docs-api/12.0/rest-api/index.html#_scoperepresentation +type KeycloakScope struct { + // A unique name for this scope. The name can be used to uniquely identify a scope, useful when querying + // for a specific scope. + // +optional + DisplayName string `json:"displayName,omitempty"` + // An URI pointing to an icon. + // +optional + IconURI string `json:"iconUri,omitempty"` + // ID. + // +optional + ID string `json:"id,omitempty"` + // A unique name for this scope. The name can be used to uniquely identify a scope, useful when querying + // for a specific scope. + // +optional + Name string `json:"name,omitempty"` + // Policies. + // +optional + Policies []KeycloakPolicy `json:"policies,omitempty"` + // Resources. + // +optional + Resources []KeycloakResource `json:"resources,omitempty"` +} + +// +k8s:openapi-gen=true + +// KeycloakClientStatus defines the observed state of KeycloakClient +type KeycloakClientStatus struct { + // Current phase of the operator. + Phase StatusPhase `json:"phase"` + // Human-readable message indicating details about current operator phase or error. + Message string `json:"message"` + // True if all resources are in a ready state and all work is done. + Ready bool `json:"ready"` + // A map of all the secondary resources types and names created for this CR. e.g "Deployment": [ "DeploymentName1", "DeploymentName2" ] + SecondaryResources map[string][]string `json:"secondaryResources,omitempty"` +} + +// +genclient +// +k8s:openapi-gen=true +// +kubebuilder:subresource:status +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// KeycloakClient is the Schema for the keycloakclients API. +type KeycloakClient struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KeycloakClientSpec `json:"spec,omitempty"` + Status KeycloakClientStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// KeycloakClientList contains a list of KeycloakClient. +type KeycloakClientList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []KeycloakClient `json:"items"` +} + +func init() { + SchemeBuilder.Register(&KeycloakClient{}, &KeycloakClientList{}) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloakrealm_types.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloakrealm_types.go new file mode 100644 index 00000000000..345f122b725 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloakrealm_types.go @@ -0,0 +1,638 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// KeycloakRealmSpec defines the desired state of KeycloakRealm. +// +k8s:openapi-gen=true +type KeycloakRealmSpec struct { + // When set to true, this KeycloakRealm will be marked as unmanaged and not be managed by this operator. + // It can then be used for targeting purposes. + // +optional + Unmanaged bool `json:"unmanaged,omitempty"` + // Selector for looking up Keycloak Custom Resources. + // +kubebuilder:validation:Required + InstanceSelector *metav1.LabelSelector `json:"instanceSelector,omitempty"` + // Keycloak Realm REST object. + // +kubebuilder:validation:Required + Realm *KeycloakAPIRealm `json:"realm"` + // A list of overrides to the default Realm behavior. + // +listType=atomic + RealmOverrides []*RedirectorIdentityProviderOverride `json:"realmOverrides,omitempty"` +} + +// KeycloakAPIRealm ... +type KeycloakAPIRealm struct { + // +kubebuilder:validation:Required + // +optional + ID string `json:"id,omitempty"` + // Realm name. + // +kubebuilder:validation:Required + Realm string `json:"realm"` + // Realm enabled flag. + // +optional + Enabled bool `json:"enabled"` + // Realm display name. + // +optional + DisplayName string `json:"displayName"` + // Realm HTML display name. + // +optional + DisplayNameHTML string `json:"displayNameHtml,omitempty"` + // Realm Password Policy + // +optional + PasswordPolicy string `json:"passwordPolicy,omitempty"` + // A set of Keycloak Users. + // +optional + Users []*KeycloakAPIUser `json:"users,omitempty"` + // A set of Keycloak Clients. + // +optional + Clients []*KeycloakAPIClient `json:"clients,omitempty"` + // A set of Identity Providers. + // +optional + IdentityProviders []*KeycloakIdentityProvider `json:"identityProviders,omitempty"` + // A set of Event Listeners. + // +optional + EventsListeners []string `json:"eventsListeners,omitempty"` + // Enable events recording + // TODO: change to values and use kubebuilder default annotation once supported + // +optional + EventsEnabled *bool `json:"eventsEnabled,omitempty"` + // Enabled event types + // +optional + EnabledEventTypes []string `json:"enabledEventTypes,omitempty"` + // Enable events recording + // TODO: change to values and use kubebuilder default annotation once supported + // +optional + AdminEventsEnabled *bool `json:"adminEventsEnabled,omitempty"` + // Enable admin events details + // TODO: change to values and use kubebuilder default annotation once supported + // +optional + AdminEventsDetailsEnabled *bool `json:"adminEventsDetailsEnabled,omitempty"` + + // Client scopes + // +optional + ClientScopes []KeycloakClientScope `json:"clientScopes,omitempty"` + + // Authentication flows + // +optional + AuthenticationFlows []KeycloakAPIAuthenticationFlow `json:"authenticationFlows,omitempty"` + + // Authenticator config + // +optional + AuthenticatorConfig []KeycloakAPIAuthenticatorConfig `json:"authenticatorConfig,omitempty"` + + // Point keycloak to an external user provider to validate + // credentials or pull in identity information. + // +optional + UserFederationProviders []KeycloakAPIUserFederationProvider `json:"userFederationProviders,omitempty"` + + // User federation mappers are extension points triggered by the + // user federation at various points. + // +optional + UserFederationMappers []KeycloakAPIUserFederationMapper `json:"userFederationMappers,omitempty"` + + // User registration + // +optional + RegistrationAllowed *bool `json:"registrationAllowed,omitempty"` + // Email as username + // +optional + RegistrationEmailAsUsername *bool `json:"registrationEmailAsUsername,omitempty"` + // Edit username + // +optional + EditUsernameAllowed *bool `json:"editUsernameAllowed,omitempty"` + // Forgot password + // +optional + ResetPasswordAllowed *bool `json:"resetPasswordAllowed,omitempty"` + // Remember me + // +optional + RememberMe *bool `json:"rememberMe,omitempty"` + // Verify email + // +optional + VerifyEmail *bool `json:"verifyEmail,omitempty"` + // Login with email + // +optional + LoginWithEmailAllowed *bool `json:"loginWithEmailAllowed,omitempty"` + // Duplicate emails + // +optional + DuplicateEmailsAllowed *bool `json:"duplicateEmailsAllowed,omitempty"` + // Require SSL + // +optional + SslRequired string `json:"sslRequired,omitempty"` + + // Brute Force Detection + // +optional + BruteForceProtected *bool `json:"bruteForceProtected,omitempty"` + // Permanent Lockout + // +optional + PermanentLockout *bool `json:"permanentLockout,omitempty"` + // Max Login Failures + // +optional + FailureFactor *int32 `json:"failureFactor,omitempty"` + // Wait Increment + // +optional + WaitIncrementSeconds *int32 `json:"waitIncrementSeconds,omitempty"` + // Quick Login Check Milli Seconds + // +optional + QuickLoginCheckMilliSeconds *int64 `json:"quickLoginCheckMilliSeconds,omitempty"` + // Minimum Quick Login Wait + // +optional + MinimumQuickLoginWaitSeconds *int32 `json:"minimumQuickLoginWaitSeconds,omitempty"` + // Max Wait + // +optional + MaxFailureWaitSeconds *int32 `json:"maxFailureWaitSeconds,omitempty"` + // Failure Reset Time + // +optional + MaxDeltaTimeSeconds *int32 `json:"maxDeltaTimeSeconds,omitempty"` + + // Email + // +optional + SMTPServer map[string]string `json:"smtpServer,omitempty"` + + // Login Theme + // +optional + LoginTheme string `json:"loginTheme,omitempty"` + // Account Theme + // +optional + AccountTheme string `json:"accountTheme,omitempty"` + // Admin Console Theme + // +optional + AdminTheme string `json:"adminTheme,omitempty"` + // Email Theme + // +optional + EmailTheme string `json:"emailTheme,omitempty"` + // Internationalization Enabled + // +optional + InternationalizationEnabled *bool `json:"internationalizationEnabled,omitempty"` + // Supported Locales + // +optional + SupportedLocales []string `json:"supportedLocales,omitempty"` + // Default Locale + // +optional + DefaultLocale string `json:"defaultLocale,omitempty"` + + // Roles + // +optional + Roles *RolesRepresentation `json:"roles,omitempty"` + + // Scope Mappings + // +optional + ScopeMappings []ScopeMappingRepresentation `json:"scopeMappings,omitempty"` + // Client Scope Mappings + // +optional + ClientScopeMappings map[string]ScopeMappingRepresentationArray `json:"clientScopeMappings,omitempty"` + + // Access Token Lifespan For Implicit Flow + // +optional + AccessTokenLifespanForImplicitFlow *int32 `json:"accessTokenLifespanForImplicitFlow,omitempty"` + // Access Token Lifespan + // +optional + AccessTokenLifespan *int32 `json:"accessTokenLifespan,omitempty"` + + // User Managed Access Allowed + // +optional + UserManagedAccessAllowed *bool `json:"userManagedAccessAllowed,omitempty"` +} + +// RoleRepresentationArray ... +type RoleRepresentationArray []RoleRepresentation + +// RolesRepresentation ... +// https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_rolesrepresentation +type RolesRepresentation struct { + // Client Roles + // +optional + Client map[string]RoleRepresentationArray `json:"client,omitempty"` + + // Realm Roles + // +optional + Realm []RoleRepresentation `json:"realm,omitempty"` +} + +// RoleRepresentation ... +// https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_rolerepresentation +type RoleRepresentation struct { + // Role Attributes + // +optional + Attributes map[string][]string `json:"attributes,omitempty"` + + // Client Role + // +optional + ClientRole *bool `json:"clientRole,omitempty"` + + // Composite + // +optional + Composite *bool `json:"composite,omitempty"` + + // Composites + // +optional + Composites *RoleRepresentationComposites `json:"composites,omitempty"` + + // Container Id + // +optional + ContainerID string `json:"containerId,omitempty"` + + // Description + // +optional + Description string `json:"description,omitempty"` + + // Id + // +optional + ID string `json:"id,omitempty"` + + // Name + Name string `json:"name"` +} + +// ScopeMappingRepresentationArray ... +type ScopeMappingRepresentationArray []ScopeMappingRepresentation + +// ScopeMappingRepresentation ... +// https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_scopemappingrepresentation +type ScopeMappingRepresentation struct { + // Client + // +optional + Client string `json:"client,omitempty"` + + // Client Scope + // +optional + ClientScope string `json:"clientScope,omitempty"` + + // Roles + // +optional + Roles []string `json:"roles,omitempty"` + + // Self + // +optional + Self string `json:"self,omitempty"` +} + +// RoleRepresentationComposites ... +// https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_rolerepresentation-composites +type RoleRepresentationComposites struct { + // Map client => []role + // +optional + Client map[string][]string `json:"client,omitempty"` + + // Realm roles + // +optional + Realm []string `json:"realm,omitempty"` +} + +// KeycloakAPIUserFederationProvider ... +// https://www.keycloak.org/docs-api/10.0/rest-api/index.html#_userfederationproviderrepresentation +type KeycloakAPIUserFederationProvider struct { + // changedSyncPeriod optional integer(int32) + // lastSync int32 + + // User federation provider config. + // +optional + Config map[string]string `json:"config,omitempty"` + + // The display name of this provider instance. + // +optional + DisplayName string `json:"displayName,omitempty"` + + // +optional + FullSyncPeriod *int32 `json:"fullSyncPeriod,omitempty"` + + // The ID of this provider + // +optional + ID string `json:"id,omitempty"` + + // The priority of this provider when looking up users or adding a user. + // +optional + Priority *int32 `json:"priority,omitempty"` + + // The name of the user provider, such as "ldap", "kerberos" or a custom SPI. + // +optional + ProviderName string `json:"providerName,omitempty"` +} + +// KeycloakAPIUserFederationMapper ... +// https://www.keycloak.org/docs/11.0/server_admin/#_ldap_mappers +// https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_userfederationmapperrepresentation +type KeycloakAPIUserFederationMapper struct { + // User federation mapper config. + // +optional + Config map[string]string `json:"config,omitempty"` + + // +optional + Name string `json:"name,omitempty"` + + // +optional + ID string `json:"id,omitempty"` + + // +optional + FederationMapperType string `json:"federationMapperType,omitempty"` + + // The displayName for the user federation provider this mapper applies to. + FederationProviderDisplayName string `json:"federationProviderDisplayName,omitempty"` +} + +// KeycloakAPIAuthenticationFlow ... +type KeycloakAPIAuthenticationFlow struct { + // Alias + Alias string `json:"alias"` + + // Authentication executions + AuthenticationExecutions []KeycloakAPIAuthenticationExecution `json:"authenticationExecutions"` + + // Built in + // +optional + BuiltIn bool `json:"builtIn,omitempty"` + + // Description + // +optional + Description string `json:"description,omitempty"` + + // ID + // +optional + ID string `json:"id,omitempty"` + + // Provider ID + // +optional + ProviderID string `json:"providerId,omitempty"` + + // Top level + // +optional + TopLevel bool `json:"topLevel,omitempty"` +} + +// KeycloakAPIAuthenticationExecution ... +type KeycloakAPIAuthenticationExecution struct { + // Authenticator + Authenticator string `json:"authenticator,omitempty"` + + // Authenticator Config + // +optional + AuthenticatorConfig string `json:"authenticatorConfig,omitempty"` + + // Authenticator flow + // +optional + AuthenticatorFlow bool `json:"authenticatorFlow,omitempty"` + + // Flow Alias + // +optional + FlowAlias string `json:"flowAlias,omitempty"` + + // Priority + // +optional + Priority int32 `json:"priority,omitempty"` + + // Requirement [REQUIRED, OPTIONAL, ALTERNATIVE, DISABLED] + Requirement string `json:"requirement,omitempty"` + + // User setup allowed + // +optional + UserSetupAllowed bool `json:"userSetupAllowed,omitempty"` +} + +// KeycloakAPIAuthenticatorConfig ... +type KeycloakAPIAuthenticatorConfig struct { + // Alias + Alias string `json:"alias"` + + // Config + // +optional + Config map[string]string `json:"config,omitempty"` + + // ID + // +optional + ID string `json:"id,omitempty"` +} + +// RedirectorIdentityProviderOverride ... +type RedirectorIdentityProviderOverride struct { + // Identity Provider to be overridden. + IdentityProvider string `json:"identityProvider"` + // Flow to be overridden. + // +optional + ForFlow string `json:"forFlow,omitempty"` +} + +// KeycloakClientScope ... +type KeycloakClientScope struct { + // +optional + Attributes map[string]string `json:"attributes,omitempty"` + // +optional + Description string `json:"description,omitempty"` + // +optional + ID string `json:"id,omitempty"` + // +optional + Name string `json:"name,omitempty"` + // +optional + Protocol string `json:"protocol,omitempty"` + // Protocol Mappers. + // +optional + ProtocolMappers []KeycloakProtocolMapper `json:"protocolMappers,omitempty"` +} + +// KeycloakIdentityProvider ... +type KeycloakIdentityProvider struct { + // Identity Provider Alias. + // +optional + Alias string `json:"alias,omitempty"` + // Identity Provider Display Name. + // +optional + DisplayName string `json:"displayName,omitempty"` + // Identity Provider Internal ID. + // +optional + InternalID string `json:"internalId,omitempty"` + // Identity Provider ID. + // +optional + ProviderID string `json:"providerId,omitempty"` + // Identity Provider enabled flag. + // +optional + Enabled bool `json:"enabled,omitempty"` + // Identity Provider Trust Email. + // +optional + TrustEmail bool `json:"trustEmail,omitempty"` + // Identity Provider Store to Token. + // +optional + StoreToken bool `json:"storeToken,omitempty"` + // Adds Read Token role when creating this Identity Provider. + // +optional + AddReadTokenRoleOnCreate bool `json:"addReadTokenRoleOnCreate,omitempty"` + // Identity Provider First Broker Login Flow Alias. + // +optional + FirstBrokerLoginFlowAlias string `json:"firstBrokerLoginFlowAlias,omitempty"` + // Identity Provider Post Broker Login Flow Alias. + // +optional + PostBrokerLoginFlowAlias string `json:"postBrokerLoginFlowAlias,omitempty"` + // Identity Provider Link Only setting. + // +optional + LinkOnly bool `json:"linkOnly,omitempty"` + // Identity Provider config. + // +optional + Config map[string]string `json:"config,omitempty"` +} + +// KeycloakUserRole ... +type KeycloakUserRole struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Composite bool `json:"composite,omitempty"` + ClientRole bool `json:"clientRole,omitempty"` + ContainerID string `json:"containerId,omitempty"` +} + +// AuthenticatorConfig ... +type AuthenticatorConfig struct { + // Authenticator Config Alias. + // +optional + Alias string `json:"alias,omitempty"` + // Authenticator config. + // +optional + Config map[string]string `json:"config,omitempty"` + // Authenticator ID. + // +optional + ID string `json:"id,omitempty"` +} + +// KeycloakAPIPasswordReset ... +type KeycloakAPIPasswordReset struct { + // Password Reset Type. + // +optional + Type string `json:"type"` + // Password Reset Value. + // +optional + Value string `json:"value"` + // True if this Password Reset object is temporary. + // +optional + Temporary bool `json:"temporary"` +} + +// AuthenticationExecutionInfo ... +type AuthenticationExecutionInfo struct { + // Authentication Execution Info Alias. + // +optional + Alias string `json:"alias,omitempty"` + // Authentication Execution Info Config. + // +optional + AuthenticationConfig string `json:"authenticationConfig,omitempty"` + // True if Authentication Flow is enabled. + // +optional + AuthenticationFlow bool `json:"authenticationFlow,omitempty"` + // True if Authentication Execution Info is configurable. + // +optional + Configurable bool `json:"configurable,omitempty"` + // Authentication Execution Info Display Name. + // +optional + DisplayName string `json:"displayName,omitempty"` + // Authentication Execution Info Flow ID. + // +optional + FlowID string `json:"flowId,omitempty"` + // Authentication Execution Info ID. + // +optional + ID string `json:"id,omitempty"` + // Authentication Execution Info Index. + // +optional + Index int32 `json:"index,omitempty"` + // Authentication Execution Info Level. + // +optional + Level int32 `json:"level,omitempty"` + // Authentication Execution Info Provider ID. + // +optional + ProviderID string `json:"providerId,omitempty"` + // Authentication Execution Info Requirement. + // +optional + Requirement string `json:"requirement,omitempty"` + // Authentication Execution Info Requirement Choices. + // +optional + RequirementChoices []string `json:"requirementChoices,omitempty"` +} + +// TokenResponse ... +type TokenResponse struct { + // Token Response Access Token. + // +optional + AccessToken string `json:"access_token"` + // Token Response Expired In setting. + // +optional + ExpiresIn int `json:"expires_in"` + // Token Response Refresh Expires In setting. + // +optional + RefreshExpiresIn int `json:"refresh_expires_in"` + // Token Response Refresh Token. + // +optional + RefreshToken string `json:"refresh_token"` + // Token Response Token Type. + // +optional + TokenType string `json:"token_type"` + // Token Response Not Before Policy setting. + // +optional + NotBeforePolicy int `json:"not-before-policy"` + // Token Response Session State. + // +optional + SessionState string `json:"session_state"` + // Token Response Error. + // +optional + Error string `json:"error"` + // Token Response Error Description. + // +optional + ErrorDescription string `json:"error_description"` +} + +// +k8s:openapi-gen=true + +// KeycloakRealmStatus defines the observed state of KeycloakRealm +type KeycloakRealmStatus struct { + // Current phase of the operator. + Phase StatusPhase `json:"phase"` + // Human-readable message indicating details about current operator phase or error. + Message string `json:"message"` + // True if all resources are in a ready state and all work is done. + Ready bool `json:"ready"` + // A map of all the secondary resources types and names created for this CR. e.g "Deployment": [ "DeploymentName1", "DeploymentName2" ] + SecondaryResources map[string][]string `json:"secondaryResources,omitempty"` + // TODO + LoginURL string `json:"loginURL"` +} + +// +genclient +// +k8s:openapi-gen=true +// +kubebuilder:subresource:status +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// KeycloakRealm is the Schema for the keycloakrealms API +type KeycloakRealm struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KeycloakRealmSpec `json:"spec,omitempty"` + Status KeycloakRealmStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// KeycloakRealmList contains a list of KeycloakRealm +type KeycloakRealmList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []KeycloakRealm `json:"items"` +} + +func init() { + SchemeBuilder.Register(&KeycloakRealm{}, &KeycloakRealmList{}) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloakuser_types.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloakuser_types.go new file mode 100644 index 00000000000..9890a652333 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/keycloakuser_types.go @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + // UserFinalizer ... + UserFinalizer = "user.cleanup" +) + +var ( + // UserPhaseReconciled ... + UserPhaseReconciled StatusPhase = "reconciled" + // UserPhaseFailing ... + UserPhaseFailing StatusPhase = "failing" +) + +// KeycloakUserSpec defines the desired state of KeycloakUser. +// +k8s:openapi-gen=true +type KeycloakUserSpec struct { + // Selector for looking up KeycloakRealm Custom Resources. + // +kubebuilder:validation:Required + RealmSelector *metav1.LabelSelector `json:"realmSelector,omitempty"` + // Keycloak User REST object. + // +kubebuilder:validation:Required + User KeycloakAPIUser `json:"user"` +} + +// KeycloakUserStatus defines the observed state of KeycloakUser. +// +k8s:openapi-gen=true +type KeycloakUserStatus struct { + // Current phase of the operator. + Phase StatusPhase `json:"phase"` + // Human-readable message indicating details about current operator phase or error. + Message string `json:"message"` +} + +// KeycloakUser is the Schema for the keycloakusers API. +// +genclient +// +k8s:openapi-gen=true +// +kubebuilder:subresource:status +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type KeycloakUser struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KeycloakUserSpec `json:"spec,omitempty"` + Status KeycloakUserStatus `json:"status,omitempty"` +} + +// KeycloakAPIUser ... +type KeycloakAPIUser struct { + // User ID. + // +optional + ID string `json:"id,omitempty"` + // User Name. + // +optional + UserName string `json:"username,omitempty"` + // First Name. + // +optional + FirstName string `json:"firstName,omitempty"` + // Last Name. + // +optional + LastName string `json:"lastName,omitempty"` + // Email. + // +optional + Email string `json:"email,omitempty"` + // True if email has already been verified. + // +optional + EmailVerified bool `json:"emailVerified,omitempty"` + // User enabled flag. + // +optional + Enabled bool `json:"enabled,omitempty"` + // A set of Realm Roles. + // +optional + RealmRoles []string `json:"realmRoles,omitempty"` + // A set of Client Roles. + // +optional + ClientRoles map[string][]string `json:"clientRoles,omitempty"` + // A set of Required Actions. + // +optional + RequiredActions []string `json:"requiredActions,omitempty"` + // A set of Groups. + // +optional + Groups []string `json:"groups,omitempty"` + // A set of Federated Identities. + // +optional + FederatedIdentities []FederatedIdentity `json:"federatedIdentities,omitempty"` + // A set of Credentials. + // +optional + Credentials []KeycloakCredential `json:"credentials,omitempty"` + // A set of Attributes. + // +optional + Attributes map[string][]string `json:"attributes,omitempty"` +} + +// KeycloakCredential ... +type KeycloakCredential struct { + // Credential Type. + // +optional + Type string `json:"type,omitempty"` + // Credential Value. + // +optional + Value string `json:"value,omitempty"` + // True if this credential object is temporary. + // +optional + Temporary bool `json:"temporary,omitempty"` +} + +// FederatedIdentity ... +type FederatedIdentity struct { + // Federated Identity Provider. + // +optional + IdentityProvider string `json:"identityProvider,omitempty"` + // Federated Identity User ID. + // +optional + UserID string `json:"userId,omitempty"` + // Federated Identity User Name. + // +optional + UserName string `json:"userName,omitempty"` +} + +// KeycloakUserList contains a list of KeycloakUser +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type KeycloakUserList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []KeycloakUser `json:"items"` +} + +func init() { + SchemeBuilder.Register(&KeycloakUser{}, &KeycloakUserList{}) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/register.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/register.go new file mode 100644 index 00000000000..3fb1bbf01ff --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/register.go @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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: Boilerplate only. Ignore this file. + +// Package v1alpha1 contains API Schema definitions for the keycloak v1alpha1 API group +// +kubebuilder:skip +// +k8s:deepcopy-gen=package,register +// +groupName=keycloak.org +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "keycloak.org", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} + // AddToScheme ... + AddToScheme = SchemeBuilder.AddToScheme +) + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/zz_generated.deepcopy.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..825afba201a --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,1965 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright 2021 Red Hat, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/api/core/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthenticationExecutionInfo) DeepCopyInto(out *AuthenticationExecutionInfo) { + *out = *in + if in.RequirementChoices != nil { + in, out := &in.RequirementChoices, &out.RequirementChoices + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationExecutionInfo. +func (in *AuthenticationExecutionInfo) DeepCopy() *AuthenticationExecutionInfo { + if in == nil { + return nil + } + out := new(AuthenticationExecutionInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthenticatorConfig) DeepCopyInto(out *AuthenticatorConfig) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + *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 AuthenticatorConfig. +func (in *AuthenticatorConfig) DeepCopy() *AuthenticatorConfig { + if in == nil { + return nil + } + out := new(AuthenticatorConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupConfig) DeepCopyInto(out *BackupConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupConfig. +func (in *BackupConfig) DeepCopy() *BackupConfig { + if in == nil { + return nil + } + out := new(BackupConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClientMappingsRepresentation) DeepCopyInto(out *ClientMappingsRepresentation) { + *out = *in + if in.Mappings != nil { + in, out := &in.Mappings, &out.Mappings + *out = make([]RoleRepresentation, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientMappingsRepresentation. +func (in *ClientMappingsRepresentation) DeepCopy() *ClientMappingsRepresentation { + if in == nil { + return nil + } + out := new(ClientMappingsRepresentation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentSpec) DeepCopyInto(out *DeploymentSpec) { + *out = *in + in.Resources.DeepCopyInto(&out.Resources) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentSpec. +func (in *DeploymentSpec) DeepCopy() *DeploymentSpec { + if in == nil { + return nil + } + out := new(DeploymentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExperimentalSpec) DeepCopyInto(out *ExperimentalSpec) { + *out = *in + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Command != nil { + in, out := &in.Command, &out.Command + *out = make([]string, len(*in)) + copy(*out, *in) + } + 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.Volumes.DeepCopyInto(&out.Volumes) + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(v1.Affinity) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExperimentalSpec. +func (in *ExperimentalSpec) DeepCopy() *ExperimentalSpec { + if in == nil { + return nil + } + out := new(ExperimentalSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FederatedIdentity) DeepCopyInto(out *FederatedIdentity) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederatedIdentity. +func (in *FederatedIdentity) DeepCopy() *FederatedIdentity { + if in == nil { + return nil + } + out := new(FederatedIdentity) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Keycloak) DeepCopyInto(out *Keycloak) { + *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 Keycloak. +func (in *Keycloak) DeepCopy() *Keycloak { + if in == nil { + return nil + } + out := new(Keycloak) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Keycloak) 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 *KeycloakAPIAuthenticationExecution) DeepCopyInto(out *KeycloakAPIAuthenticationExecution) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakAPIAuthenticationExecution. +func (in *KeycloakAPIAuthenticationExecution) DeepCopy() *KeycloakAPIAuthenticationExecution { + if in == nil { + return nil + } + out := new(KeycloakAPIAuthenticationExecution) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakAPIAuthenticationFlow) DeepCopyInto(out *KeycloakAPIAuthenticationFlow) { + *out = *in + if in.AuthenticationExecutions != nil { + in, out := &in.AuthenticationExecutions, &out.AuthenticationExecutions + *out = make([]KeycloakAPIAuthenticationExecution, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakAPIAuthenticationFlow. +func (in *KeycloakAPIAuthenticationFlow) DeepCopy() *KeycloakAPIAuthenticationFlow { + if in == nil { + return nil + } + out := new(KeycloakAPIAuthenticationFlow) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakAPIAuthenticatorConfig) DeepCopyInto(out *KeycloakAPIAuthenticatorConfig) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + *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 KeycloakAPIAuthenticatorConfig. +func (in *KeycloakAPIAuthenticatorConfig) DeepCopy() *KeycloakAPIAuthenticatorConfig { + if in == nil { + return nil + } + out := new(KeycloakAPIAuthenticatorConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakAPIClient) DeepCopyInto(out *KeycloakAPIClient) { + *out = *in + if in.DefaultRoles != nil { + in, out := &in.DefaultRoles, &out.DefaultRoles + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.RedirectUris != nil { + in, out := &in.RedirectUris, &out.RedirectUris + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.WebOrigins != nil { + in, out := &in.WebOrigins, &out.WebOrigins + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Attributes != nil { + in, out := &in.Attributes, &out.Attributes + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.FullScopeAllowed != nil { + in, out := &in.FullScopeAllowed, &out.FullScopeAllowed + *out = new(bool) + **out = **in + } + if in.ProtocolMappers != nil { + in, out := &in.ProtocolMappers, &out.ProtocolMappers + *out = make([]KeycloakProtocolMapper, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Access != nil { + in, out := &in.Access, &out.Access + *out = make(map[string]bool, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.OptionalClientScopes != nil { + in, out := &in.OptionalClientScopes, &out.OptionalClientScopes + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.DefaultClientScopes != nil { + in, out := &in.DefaultClientScopes, &out.DefaultClientScopes + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.AuthorizationSettings != nil { + in, out := &in.AuthorizationSettings, &out.AuthorizationSettings + *out = new(KeycloakResourceServer) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakAPIClient. +func (in *KeycloakAPIClient) DeepCopy() *KeycloakAPIClient { + if in == nil { + return nil + } + out := new(KeycloakAPIClient) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakAPIPasswordReset) DeepCopyInto(out *KeycloakAPIPasswordReset) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakAPIPasswordReset. +func (in *KeycloakAPIPasswordReset) DeepCopy() *KeycloakAPIPasswordReset { + if in == nil { + return nil + } + out := new(KeycloakAPIPasswordReset) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakAPIRealm) DeepCopyInto(out *KeycloakAPIRealm) { + *out = *in + if in.Users != nil { + in, out := &in.Users, &out.Users + *out = make([]*KeycloakAPIUser, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(KeycloakAPIUser) + (*in).DeepCopyInto(*out) + } + } + } + if in.Clients != nil { + in, out := &in.Clients, &out.Clients + *out = make([]*KeycloakAPIClient, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(KeycloakAPIClient) + (*in).DeepCopyInto(*out) + } + } + } + if in.IdentityProviders != nil { + in, out := &in.IdentityProviders, &out.IdentityProviders + *out = make([]*KeycloakIdentityProvider, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(KeycloakIdentityProvider) + (*in).DeepCopyInto(*out) + } + } + } + if in.EventsListeners != nil { + in, out := &in.EventsListeners, &out.EventsListeners + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.EventsEnabled != nil { + in, out := &in.EventsEnabled, &out.EventsEnabled + *out = new(bool) + **out = **in + } + if in.EnabledEventTypes != nil { + in, out := &in.EnabledEventTypes, &out.EnabledEventTypes + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.AdminEventsEnabled != nil { + in, out := &in.AdminEventsEnabled, &out.AdminEventsEnabled + *out = new(bool) + **out = **in + } + if in.AdminEventsDetailsEnabled != nil { + in, out := &in.AdminEventsDetailsEnabled, &out.AdminEventsDetailsEnabled + *out = new(bool) + **out = **in + } + if in.ClientScopes != nil { + in, out := &in.ClientScopes, &out.ClientScopes + *out = make([]KeycloakClientScope, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.AuthenticationFlows != nil { + in, out := &in.AuthenticationFlows, &out.AuthenticationFlows + *out = make([]KeycloakAPIAuthenticationFlow, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.AuthenticatorConfig != nil { + in, out := &in.AuthenticatorConfig, &out.AuthenticatorConfig + *out = make([]KeycloakAPIAuthenticatorConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.UserFederationProviders != nil { + in, out := &in.UserFederationProviders, &out.UserFederationProviders + *out = make([]KeycloakAPIUserFederationProvider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.UserFederationMappers != nil { + in, out := &in.UserFederationMappers, &out.UserFederationMappers + *out = make([]KeycloakAPIUserFederationMapper, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.RegistrationAllowed != nil { + in, out := &in.RegistrationAllowed, &out.RegistrationAllowed + *out = new(bool) + **out = **in + } + if in.RegistrationEmailAsUsername != nil { + in, out := &in.RegistrationEmailAsUsername, &out.RegistrationEmailAsUsername + *out = new(bool) + **out = **in + } + if in.EditUsernameAllowed != nil { + in, out := &in.EditUsernameAllowed, &out.EditUsernameAllowed + *out = new(bool) + **out = **in + } + if in.ResetPasswordAllowed != nil { + in, out := &in.ResetPasswordAllowed, &out.ResetPasswordAllowed + *out = new(bool) + **out = **in + } + if in.RememberMe != nil { + in, out := &in.RememberMe, &out.RememberMe + *out = new(bool) + **out = **in + } + if in.VerifyEmail != nil { + in, out := &in.VerifyEmail, &out.VerifyEmail + *out = new(bool) + **out = **in + } + if in.LoginWithEmailAllowed != nil { + in, out := &in.LoginWithEmailAllowed, &out.LoginWithEmailAllowed + *out = new(bool) + **out = **in + } + if in.DuplicateEmailsAllowed != nil { + in, out := &in.DuplicateEmailsAllowed, &out.DuplicateEmailsAllowed + *out = new(bool) + **out = **in + } + if in.BruteForceProtected != nil { + in, out := &in.BruteForceProtected, &out.BruteForceProtected + *out = new(bool) + **out = **in + } + if in.PermanentLockout != nil { + in, out := &in.PermanentLockout, &out.PermanentLockout + *out = new(bool) + **out = **in + } + if in.FailureFactor != nil { + in, out := &in.FailureFactor, &out.FailureFactor + *out = new(int32) + **out = **in + } + if in.WaitIncrementSeconds != nil { + in, out := &in.WaitIncrementSeconds, &out.WaitIncrementSeconds + *out = new(int32) + **out = **in + } + if in.QuickLoginCheckMilliSeconds != nil { + in, out := &in.QuickLoginCheckMilliSeconds, &out.QuickLoginCheckMilliSeconds + *out = new(int64) + **out = **in + } + if in.MinimumQuickLoginWaitSeconds != nil { + in, out := &in.MinimumQuickLoginWaitSeconds, &out.MinimumQuickLoginWaitSeconds + *out = new(int32) + **out = **in + } + if in.MaxFailureWaitSeconds != nil { + in, out := &in.MaxFailureWaitSeconds, &out.MaxFailureWaitSeconds + *out = new(int32) + **out = **in + } + if in.MaxDeltaTimeSeconds != nil { + in, out := &in.MaxDeltaTimeSeconds, &out.MaxDeltaTimeSeconds + *out = new(int32) + **out = **in + } + if in.SMTPServer != nil { + in, out := &in.SMTPServer, &out.SMTPServer + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.InternationalizationEnabled != nil { + in, out := &in.InternationalizationEnabled, &out.InternationalizationEnabled + *out = new(bool) + **out = **in + } + if in.SupportedLocales != nil { + in, out := &in.SupportedLocales, &out.SupportedLocales + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Roles != nil { + in, out := &in.Roles, &out.Roles + *out = new(RolesRepresentation) + (*in).DeepCopyInto(*out) + } + if in.ScopeMappings != nil { + in, out := &in.ScopeMappings, &out.ScopeMappings + *out = make([]ScopeMappingRepresentation, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ClientScopeMappings != nil { + in, out := &in.ClientScopeMappings, &out.ClientScopeMappings + *out = make(map[string]ScopeMappingRepresentationArray, len(*in)) + for key, val := range *in { + var outVal []ScopeMappingRepresentation + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make(ScopeMappingRepresentationArray, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + (*out)[key] = outVal + } + } + if in.AccessTokenLifespanForImplicitFlow != nil { + in, out := &in.AccessTokenLifespanForImplicitFlow, &out.AccessTokenLifespanForImplicitFlow + *out = new(int32) + **out = **in + } + if in.AccessTokenLifespan != nil { + in, out := &in.AccessTokenLifespan, &out.AccessTokenLifespan + *out = new(int32) + **out = **in + } + if in.UserManagedAccessAllowed != nil { + in, out := &in.UserManagedAccessAllowed, &out.UserManagedAccessAllowed + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakAPIRealm. +func (in *KeycloakAPIRealm) DeepCopy() *KeycloakAPIRealm { + if in == nil { + return nil + } + out := new(KeycloakAPIRealm) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakAPIUser) DeepCopyInto(out *KeycloakAPIUser) { + *out = *in + if in.RealmRoles != nil { + in, out := &in.RealmRoles, &out.RealmRoles + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ClientRoles != nil { + in, out := &in.ClientRoles, &out.ClientRoles + *out = make(map[string][]string, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } + if in.RequiredActions != nil { + in, out := &in.RequiredActions, &out.RequiredActions + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Groups != nil { + in, out := &in.Groups, &out.Groups + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.FederatedIdentities != nil { + in, out := &in.FederatedIdentities, &out.FederatedIdentities + *out = make([]FederatedIdentity, len(*in)) + copy(*out, *in) + } + if in.Credentials != nil { + in, out := &in.Credentials, &out.Credentials + *out = make([]KeycloakCredential, len(*in)) + copy(*out, *in) + } + if in.Attributes != nil { + in, out := &in.Attributes, &out.Attributes + *out = make(map[string][]string, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakAPIUser. +func (in *KeycloakAPIUser) DeepCopy() *KeycloakAPIUser { + if in == nil { + return nil + } + out := new(KeycloakAPIUser) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakAPIUserFederationMapper) DeepCopyInto(out *KeycloakAPIUserFederationMapper) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + *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 KeycloakAPIUserFederationMapper. +func (in *KeycloakAPIUserFederationMapper) DeepCopy() *KeycloakAPIUserFederationMapper { + if in == nil { + return nil + } + out := new(KeycloakAPIUserFederationMapper) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakAPIUserFederationProvider) DeepCopyInto(out *KeycloakAPIUserFederationProvider) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.FullSyncPeriod != nil { + in, out := &in.FullSyncPeriod, &out.FullSyncPeriod + *out = new(int32) + **out = **in + } + if in.Priority != nil { + in, out := &in.Priority, &out.Priority + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakAPIUserFederationProvider. +func (in *KeycloakAPIUserFederationProvider) DeepCopy() *KeycloakAPIUserFederationProvider { + if in == nil { + return nil + } + out := new(KeycloakAPIUserFederationProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakAWSSpec) DeepCopyInto(out *KeycloakAWSSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakAWSSpec. +func (in *KeycloakAWSSpec) DeepCopy() *KeycloakAWSSpec { + if in == nil { + return nil + } + out := new(KeycloakAWSSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakBackup) DeepCopyInto(out *KeycloakBackup) { + *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 KeycloakBackup. +func (in *KeycloakBackup) DeepCopy() *KeycloakBackup { + if in == nil { + return nil + } + out := new(KeycloakBackup) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KeycloakBackup) 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 *KeycloakBackupList) DeepCopyInto(out *KeycloakBackupList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KeycloakBackup, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakBackupList. +func (in *KeycloakBackupList) DeepCopy() *KeycloakBackupList { + if in == nil { + return nil + } + out := new(KeycloakBackupList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KeycloakBackupList) 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 *KeycloakBackupSpec) DeepCopyInto(out *KeycloakBackupSpec) { + *out = *in + out.AWS = in.AWS + if in.InstanceSelector != nil { + in, out := &in.InstanceSelector, &out.InstanceSelector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.StorageClassName != nil { + in, out := &in.StorageClassName, &out.StorageClassName + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakBackupSpec. +func (in *KeycloakBackupSpec) DeepCopy() *KeycloakBackupSpec { + if in == nil { + return nil + } + out := new(KeycloakBackupSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakBackupStatus) DeepCopyInto(out *KeycloakBackupStatus) { + *out = *in + if in.SecondaryResources != nil { + in, out := &in.SecondaryResources, &out.SecondaryResources + *out = make(map[string][]string, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakBackupStatus. +func (in *KeycloakBackupStatus) DeepCopy() *KeycloakBackupStatus { + if in == nil { + return nil + } + out := new(KeycloakBackupStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakClient) DeepCopyInto(out *KeycloakClient) { + *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 KeycloakClient. +func (in *KeycloakClient) DeepCopy() *KeycloakClient { + if in == nil { + return nil + } + out := new(KeycloakClient) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KeycloakClient) 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 *KeycloakClientList) DeepCopyInto(out *KeycloakClientList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KeycloakClient, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakClientList. +func (in *KeycloakClientList) DeepCopy() *KeycloakClientList { + if in == nil { + return nil + } + out := new(KeycloakClientList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KeycloakClientList) 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 *KeycloakClientScope) DeepCopyInto(out *KeycloakClientScope) { + *out = *in + if in.Attributes != nil { + in, out := &in.Attributes, &out.Attributes + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.ProtocolMappers != nil { + in, out := &in.ProtocolMappers, &out.ProtocolMappers + *out = make([]KeycloakProtocolMapper, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakClientScope. +func (in *KeycloakClientScope) DeepCopy() *KeycloakClientScope { + if in == nil { + return nil + } + out := new(KeycloakClientScope) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakClientSpec) DeepCopyInto(out *KeycloakClientSpec) { + *out = *in + if in.RealmSelector != nil { + in, out := &in.RealmSelector, &out.RealmSelector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.Client != nil { + in, out := &in.Client, &out.Client + *out = new(KeycloakAPIClient) + (*in).DeepCopyInto(*out) + } + if in.Roles != nil { + in, out := &in.Roles, &out.Roles + *out = make([]RoleRepresentation, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ScopeMappings != nil { + in, out := &in.ScopeMappings, &out.ScopeMappings + *out = new(MappingsRepresentation) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakClientSpec. +func (in *KeycloakClientSpec) DeepCopy() *KeycloakClientSpec { + if in == nil { + return nil + } + out := new(KeycloakClientSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakClientStatus) DeepCopyInto(out *KeycloakClientStatus) { + *out = *in + if in.SecondaryResources != nil { + in, out := &in.SecondaryResources, &out.SecondaryResources + *out = make(map[string][]string, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakClientStatus. +func (in *KeycloakClientStatus) DeepCopy() *KeycloakClientStatus { + if in == nil { + return nil + } + out := new(KeycloakClientStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakCredential) DeepCopyInto(out *KeycloakCredential) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakCredential. +func (in *KeycloakCredential) DeepCopy() *KeycloakCredential { + if in == nil { + return nil + } + out := new(KeycloakCredential) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakDeploymentSpec) DeepCopyInto(out *KeycloakDeploymentSpec) { + *out = *in + in.DeploymentSpec.DeepCopyInto(&out.DeploymentSpec) + in.Experimental.DeepCopyInto(&out.Experimental) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakDeploymentSpec. +func (in *KeycloakDeploymentSpec) DeepCopy() *KeycloakDeploymentSpec { + if in == nil { + return nil + } + out := new(KeycloakDeploymentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakExternal) DeepCopyInto(out *KeycloakExternal) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakExternal. +func (in *KeycloakExternal) DeepCopy() *KeycloakExternal { + if in == nil { + return nil + } + out := new(KeycloakExternal) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakExternalAccess) DeepCopyInto(out *KeycloakExternalAccess) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakExternalAccess. +func (in *KeycloakExternalAccess) DeepCopy() *KeycloakExternalAccess { + if in == nil { + return nil + } + out := new(KeycloakExternalAccess) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakExternalDatabase) DeepCopyInto(out *KeycloakExternalDatabase) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakExternalDatabase. +func (in *KeycloakExternalDatabase) DeepCopy() *KeycloakExternalDatabase { + if in == nil { + return nil + } + out := new(KeycloakExternalDatabase) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakIdentityProvider) DeepCopyInto(out *KeycloakIdentityProvider) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + *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 KeycloakIdentityProvider. +func (in *KeycloakIdentityProvider) DeepCopy() *KeycloakIdentityProvider { + if in == nil { + return nil + } + out := new(KeycloakIdentityProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakList) DeepCopyInto(out *KeycloakList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Keycloak, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakList. +func (in *KeycloakList) DeepCopy() *KeycloakList { + if in == nil { + return nil + } + out := new(KeycloakList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KeycloakList) 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 *KeycloakPolicy) DeepCopyInto(out *KeycloakPolicy) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Policies != nil { + in, out := &in.Policies, &out.Policies + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ResourcesData != nil { + in, out := &in.ResourcesData, &out.ResourcesData + *out = make([]KeycloakResource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Scopes != nil { + in, out := &in.Scopes, &out.Scopes + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ScopesData != nil { + in, out := &in.ScopesData, &out.ScopesData + *out = make([]apiextensionsv1.JSON, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakPolicy. +func (in *KeycloakPolicy) DeepCopy() *KeycloakPolicy { + if in == nil { + return nil + } + out := new(KeycloakPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakProtocolMapper) DeepCopyInto(out *KeycloakProtocolMapper) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + *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 KeycloakProtocolMapper. +func (in *KeycloakProtocolMapper) DeepCopy() *KeycloakProtocolMapper { + if in == nil { + return nil + } + out := new(KeycloakProtocolMapper) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakRealm) DeepCopyInto(out *KeycloakRealm) { + *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 KeycloakRealm. +func (in *KeycloakRealm) DeepCopy() *KeycloakRealm { + if in == nil { + return nil + } + out := new(KeycloakRealm) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KeycloakRealm) 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 *KeycloakRealmList) DeepCopyInto(out *KeycloakRealmList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KeycloakRealm, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakRealmList. +func (in *KeycloakRealmList) DeepCopy() *KeycloakRealmList { + if in == nil { + return nil + } + out := new(KeycloakRealmList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KeycloakRealmList) 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 *KeycloakRealmSpec) DeepCopyInto(out *KeycloakRealmSpec) { + *out = *in + if in.InstanceSelector != nil { + in, out := &in.InstanceSelector, &out.InstanceSelector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.Realm != nil { + in, out := &in.Realm, &out.Realm + *out = new(KeycloakAPIRealm) + (*in).DeepCopyInto(*out) + } + if in.RealmOverrides != nil { + in, out := &in.RealmOverrides, &out.RealmOverrides + *out = make([]*RedirectorIdentityProviderOverride, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(RedirectorIdentityProviderOverride) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakRealmSpec. +func (in *KeycloakRealmSpec) DeepCopy() *KeycloakRealmSpec { + if in == nil { + return nil + } + out := new(KeycloakRealmSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakRealmStatus) DeepCopyInto(out *KeycloakRealmStatus) { + *out = *in + if in.SecondaryResources != nil { + in, out := &in.SecondaryResources, &out.SecondaryResources + *out = make(map[string][]string, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakRealmStatus. +func (in *KeycloakRealmStatus) DeepCopy() *KeycloakRealmStatus { + if in == nil { + return nil + } + out := new(KeycloakRealmStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakResource) DeepCopyInto(out *KeycloakResource) { + *out = *in + if in.Attributes != nil { + in, out := &in.Attributes, &out.Attributes + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Uris != nil { + in, out := &in.Uris, &out.Uris + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Scopes != nil { + in, out := &in.Scopes, &out.Scopes + *out = make([]apiextensionsv1.JSON, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakResource. +func (in *KeycloakResource) DeepCopy() *KeycloakResource { + if in == nil { + return nil + } + out := new(KeycloakResource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakResourceServer) DeepCopyInto(out *KeycloakResourceServer) { + *out = *in + if in.Policies != nil { + in, out := &in.Policies, &out.Policies + *out = make([]KeycloakPolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]KeycloakResource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Scopes != nil { + in, out := &in.Scopes, &out.Scopes + *out = make([]KeycloakScope, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakResourceServer. +func (in *KeycloakResourceServer) DeepCopy() *KeycloakResourceServer { + if in == nil { + return nil + } + out := new(KeycloakResourceServer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakScope) DeepCopyInto(out *KeycloakScope) { + *out = *in + if in.Policies != nil { + in, out := &in.Policies, &out.Policies + *out = make([]KeycloakPolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]KeycloakResource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakScope. +func (in *KeycloakScope) DeepCopy() *KeycloakScope { + if in == nil { + return nil + } + out := new(KeycloakScope) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakSpec) DeepCopyInto(out *KeycloakSpec) { + *out = *in + out.External = in.External + if in.Extensions != nil { + in, out := &in.Extensions, &out.Extensions + *out = make([]string, len(*in)) + copy(*out, *in) + } + out.ExternalAccess = in.ExternalAccess + out.ExternalDatabase = in.ExternalDatabase + out.PodDisruptionBudget = in.PodDisruptionBudget + in.KeycloakDeploymentSpec.DeepCopyInto(&out.KeycloakDeploymentSpec) + in.PostgresDeploymentSpec.DeepCopyInto(&out.PostgresDeploymentSpec) + out.Migration = in.Migration + if in.StorageClassName != nil { + in, out := &in.StorageClassName, &out.StorageClassName + *out = new(string) + **out = **in + } + out.MultiAvailablityZones = in.MultiAvailablityZones +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakSpec. +func (in *KeycloakSpec) DeepCopy() *KeycloakSpec { + if in == nil { + return nil + } + out := new(KeycloakSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakStatus) DeepCopyInto(out *KeycloakStatus) { + *out = *in + if in.SecondaryResources != nil { + in, out := &in.SecondaryResources, &out.SecondaryResources + *out = make(map[string][]string, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakStatus. +func (in *KeycloakStatus) DeepCopy() *KeycloakStatus { + if in == nil { + return nil + } + out := new(KeycloakStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakUser) DeepCopyInto(out *KeycloakUser) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakUser. +func (in *KeycloakUser) DeepCopy() *KeycloakUser { + if in == nil { + return nil + } + out := new(KeycloakUser) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KeycloakUser) 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 *KeycloakUserList) DeepCopyInto(out *KeycloakUserList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KeycloakUser, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakUserList. +func (in *KeycloakUserList) DeepCopy() *KeycloakUserList { + if in == nil { + return nil + } + out := new(KeycloakUserList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KeycloakUserList) 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 *KeycloakUserRole) DeepCopyInto(out *KeycloakUserRole) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakUserRole. +func (in *KeycloakUserRole) DeepCopy() *KeycloakUserRole { + if in == nil { + return nil + } + out := new(KeycloakUserRole) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakUserSpec) DeepCopyInto(out *KeycloakUserSpec) { + *out = *in + if in.RealmSelector != nil { + in, out := &in.RealmSelector, &out.RealmSelector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } + in.User.DeepCopyInto(&out.User) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakUserSpec. +func (in *KeycloakUserSpec) DeepCopy() *KeycloakUserSpec { + if in == nil { + return nil + } + out := new(KeycloakUserSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KeycloakUserStatus) DeepCopyInto(out *KeycloakUserStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeycloakUserStatus. +func (in *KeycloakUserStatus) DeepCopy() *KeycloakUserStatus { + if in == nil { + return nil + } + out := new(KeycloakUserStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MappingsRepresentation) DeepCopyInto(out *MappingsRepresentation) { + *out = *in + if in.ClientMappings != nil { + in, out := &in.ClientMappings, &out.ClientMappings + *out = make(map[string]ClientMappingsRepresentation, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + if in.RealmMappings != nil { + in, out := &in.RealmMappings, &out.RealmMappings + *out = make([]RoleRepresentation, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MappingsRepresentation. +func (in *MappingsRepresentation) DeepCopy() *MappingsRepresentation { + if in == nil { + return nil + } + out := new(MappingsRepresentation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MigrateConfig) DeepCopyInto(out *MigrateConfig) { + *out = *in + out.Backups = in.Backups +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MigrateConfig. +func (in *MigrateConfig) DeepCopy() *MigrateConfig { + if in == nil { + return nil + } + out := new(MigrateConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MultiAvailablityZonesConfig) DeepCopyInto(out *MultiAvailablityZonesConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MultiAvailablityZonesConfig. +func (in *MultiAvailablityZonesConfig) DeepCopy() *MultiAvailablityZonesConfig { + if in == nil { + return nil + } + out := new(MultiAvailablityZonesConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodDisruptionBudgetConfig) DeepCopyInto(out *PodDisruptionBudgetConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodDisruptionBudgetConfig. +func (in *PodDisruptionBudgetConfig) DeepCopy() *PodDisruptionBudgetConfig { + if in == nil { + return nil + } + out := new(PodDisruptionBudgetConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PostgresqlDeploymentSpec) DeepCopyInto(out *PostgresqlDeploymentSpec) { + *out = *in + in.DeploymentSpec.DeepCopyInto(&out.DeploymentSpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgresqlDeploymentSpec. +func (in *PostgresqlDeploymentSpec) DeepCopy() *PostgresqlDeploymentSpec { + if in == nil { + return nil + } + out := new(PostgresqlDeploymentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedirectorIdentityProviderOverride) DeepCopyInto(out *RedirectorIdentityProviderOverride) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedirectorIdentityProviderOverride. +func (in *RedirectorIdentityProviderOverride) DeepCopy() *RedirectorIdentityProviderOverride { + if in == nil { + return nil + } + out := new(RedirectorIdentityProviderOverride) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RoleRepresentation) DeepCopyInto(out *RoleRepresentation) { + *out = *in + if in.Attributes != nil { + in, out := &in.Attributes, &out.Attributes + *out = make(map[string][]string, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } + if in.ClientRole != nil { + in, out := &in.ClientRole, &out.ClientRole + *out = new(bool) + **out = **in + } + if in.Composite != nil { + in, out := &in.Composite, &out.Composite + *out = new(bool) + **out = **in + } + if in.Composites != nil { + in, out := &in.Composites, &out.Composites + *out = new(RoleRepresentationComposites) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleRepresentation. +func (in *RoleRepresentation) DeepCopy() *RoleRepresentation { + if in == nil { + return nil + } + out := new(RoleRepresentation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in RoleRepresentationArray) DeepCopyInto(out *RoleRepresentationArray) { + { + in := &in + *out = make(RoleRepresentationArray, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleRepresentationArray. +func (in RoleRepresentationArray) DeepCopy() RoleRepresentationArray { + if in == nil { + return nil + } + out := new(RoleRepresentationArray) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RoleRepresentationComposites) DeepCopyInto(out *RoleRepresentationComposites) { + *out = *in + if in.Client != nil { + in, out := &in.Client, &out.Client + *out = make(map[string][]string, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } + if in.Realm != nil { + in, out := &in.Realm, &out.Realm + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleRepresentationComposites. +func (in *RoleRepresentationComposites) DeepCopy() *RoleRepresentationComposites { + if in == nil { + return nil + } + out := new(RoleRepresentationComposites) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolesRepresentation) DeepCopyInto(out *RolesRepresentation) { + *out = *in + if in.Client != nil { + in, out := &in.Client, &out.Client + *out = make(map[string]RoleRepresentationArray, len(*in)) + for key, val := range *in { + var outVal []RoleRepresentation + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make(RoleRepresentationArray, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + (*out)[key] = outVal + } + } + if in.Realm != nil { + in, out := &in.Realm, &out.Realm + *out = make([]RoleRepresentation, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolesRepresentation. +func (in *RolesRepresentation) DeepCopy() *RolesRepresentation { + if in == nil { + return nil + } + out := new(RolesRepresentation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScopeMappingRepresentation) DeepCopyInto(out *ScopeMappingRepresentation) { + *out = *in + if in.Roles != nil { + in, out := &in.Roles, &out.Roles + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScopeMappingRepresentation. +func (in *ScopeMappingRepresentation) DeepCopy() *ScopeMappingRepresentation { + if in == nil { + return nil + } + out := new(ScopeMappingRepresentation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in ScopeMappingRepresentationArray) DeepCopyInto(out *ScopeMappingRepresentationArray) { + { + in := &in + *out = make(ScopeMappingRepresentationArray, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScopeMappingRepresentationArray. +func (in ScopeMappingRepresentationArray) DeepCopy() ScopeMappingRepresentationArray { + if in == nil { + return nil + } + out := new(ScopeMappingRepresentationArray) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TokenResponse) DeepCopyInto(out *TokenResponse) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenResponse. +func (in *TokenResponse) DeepCopy() *TokenResponse { + if in == nil { + return nil + } + out := new(TokenResponse) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeSpec) DeepCopyInto(out *VolumeSpec) { + *out = *in + if in.ConfigMaps != nil { + in, out := &in.ConfigMaps, &out.ConfigMaps + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Secrets != nil { + in, out := &in.Secrets, &out.Secrets + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1.KeyToPath, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSpec. +func (in *VolumeSpec) DeepCopy() *VolumeSpec { + if in == nil { + return nil + } + out := new(VolumeSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumesSpec) DeepCopyInto(out *VolumesSpec) { + *out = *in + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VolumeSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.DefaultMode != nil { + in, out := &in.DefaultMode, &out.DefaultMode + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumesSpec. +func (in *VolumesSpec) DeepCopy() *VolumesSpec { + if in == nil { + return nil + } + out := new(VolumesSpec) + in.DeepCopyInto(out) + return out +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb.go new file mode 100644 index 00000000000..3b26b3c81f8 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb.go @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package infrastructure + +import ( + v1 "k8s.io/api/apps/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" + mongodb "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/operator" +) + +const ( + // MongoDBOperatorName is the MongoDB Operator default name + MongoDBOperatorName = "mongodb-kubernetes-operator" + + // DefaultMongoDBAuthDatabase is the default authentication database in MongoDB + DefaultMongoDBAuthDatabase = "admin" + // DefaultMongoDBPasswordSecretRef is the default key for the secret reference in MongoDB + DefaultMongoDBPasswordSecretRef = "password" + + // MongoDBKind refers to MongoDB Kind + MongoDBKind = "MongoDB" + + // MongoDBAppSecretAuthDatabaseKey is the secret authentication database key set in the linked secret for an application + MongoDBAppSecretAuthDatabaseKey = "auth-database" + // MongoDBAppSecretDatabaseKey is the secret database key set in the linked secret for an application + MongoDBAppSecretDatabaseKey = "database" + // MongoDBAppSecretUsernameKey is the secret username key set in the linked secret for an application + MongoDBAppSecretUsernameKey = "username" + // MongoDBAppSecretPasswordKey is the secret password key set in the linked secret for an application + MongoDBAppSecretPasswordKey = "password" +) + +var ( + // MongoDBAPIVersion refers to MongoDB APIVersion + MongoDBAPIVersion = mongodb.SchemeBuilder.GroupVersion.String() + + mongoDBServerGroup = mongodb.GroupVersion.Group +) + +// MongoDBHandler ... +type MongoDBHandler interface { + IsMongoDBAvailable() bool + IsMongoDBOperatorAvailable(namespace string) (bool, error) + FetchMongoDBInstance(key types.NamespacedName) (*mongodb.MongoDBCommunity, error) +} + +type mongoDBHandler struct { + operator.Context +} + +// NewMongoDBHandler ... +func NewMongoDBHandler(context operator.Context) MongoDBHandler { + return &mongoDBHandler{ + context, + } +} + +// IsMongoDBAvailable checks if MongoDB CRD is available in the cluster +func (m *mongoDBHandler) IsMongoDBAvailable() bool { + return m.Client.HasServerGroup(mongoDBServerGroup) +} + +// IsMongoDBOperatorAvailable verify if MongoDB Operator is running in the given namespace and the CRD is available +func (m *mongoDBHandler) IsMongoDBOperatorAvailable(namespace string) (bool, error) { + m.Log.Debug("Checking if MongoDB Operator is available in the namespace", "namespace", namespace) + // first check for CRD + if m.IsMongoDBAvailable() { + m.Log.Debug("MongoDB CRDs available. Checking if MongoDB Operator is deployed in the namespace", "namespace", namespace) + // then check if there's an MongoDB Operator deployed + deployment := &v1.Deployment{ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: MongoDBOperatorName}} + exists := false + var err error + if exists, err = kubernetes.ResourceC(m.Client).Fetch(deployment); err != nil { + return false, nil + } + if exists { + m.Log.Debug("MongoDB Operator is available in the namespace", "namespace", namespace) + return true, nil + } + } else { + m.Log.Debug("Couldn't find MongoDB CRDs") + } + m.Log.Debug("Looks like MongoDB Operator is not available in the namespace", "namespace", namespace) + return false, nil +} + +func (m *mongoDBHandler) FetchMongoDBInstance(key types.NamespacedName) (*mongodb.MongoDBCommunity, error) { + m.Log.Debug("fetching deployed kogito mongoDB instance") + mongoDBInstance := &mongodb.MongoDBCommunity{} + if exists, err := kubernetes.ResourceC(m.Client).FetchWithKey(key, mongoDBInstance); err != nil { + m.Log.Error(err, "Error occurs while fetching kogito mongoDB instance") + return nil, err + } else if !exists { + m.Log.Debug("Kogito mongoDB instance is not exists") + return nil, nil + } else { + m.Log.Debug("Kogito mongoDB instance found", "instance", mongoDBInstance) + return mongoDBInstance, nil + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/group.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/group.go new file mode 100644 index 00000000000..9bd3ba30877 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/group.go @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// Package mongodb contains mongodb API versions. +// +// This file ensures Go source parsers acknowledge the mongodb package +// and any child packages. It can be removed if any other Go source files are +// added to this package. +package mongodb diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1/doc.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1/doc.go new file mode 100644 index 00000000000..c2d7094da53 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1/doc.go @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 mongodb v1 API group +// +k8s:deepcopy-gen=package,register +// +groupName=mongodbcommunity.mongodb.com +// +versionName=v1 +package v1 diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1/groupversion_info.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1/groupversion_info.go new file mode 100644 index 00000000000..31323f6957a --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1/groupversion_info.go @@ -0,0 +1,33 @@ +/* +Copyright 2021. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES 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 mongodbcommunity v1 API group +// +kubebuilder:object:generate=true +// +groupName=mongodbcommunity.mongodb.com +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: "mongodbcommunity.mongodb.com", 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/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1/mongodbcommunity_types.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1/mongodbcommunity_types.go new file mode 100644 index 00000000000..665950890c1 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1/mongodbcommunity_types.go @@ -0,0 +1,319 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + appsv1 "k8s.io/api/apps/v1" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// Type ... +type Type string + +const ( + // ReplicaSet ... + ReplicaSet Type = "ReplicaSet" +) + +// Phase ... +type Phase string + +const ( + // Running ... + Running Phase = "Running" + // Failed ... + Failed Phase = "Failed" + // Pending ... + Pending Phase = "Pending" +) + +// MongoDBCommunitySpec defines the desired state of MongoDB +type MongoDBCommunitySpec struct { + // Members is the number of members in the replica set + // +optional + Members int `json:"members"` + // Type defines which type of MongoDB deployment the resource should create + // +kubebuilder:validation:Enum=ReplicaSet + Type Type `json:"type"` + // Version defines which version of MongoDB will be used + Version string `json:"version"` + + // Arbiters is the number of arbiters (each counted as a member) in the replica set + // +optional + Arbiters int `json:"arbiters"` + + // FeatureCompatibilityVersion configures the feature compatibility version that will + // be set for the deployment + // +optional + FeatureCompatibilityVersion string `json:"featureCompatibilityVersion,omitempty"` + + // ReplicaSetHorizons Add this parameter and values if you need your database + // to be accessed outside of Kubernetes. This setting allows you to + // provide different DNS settings within the Kubernetes cluster and + // to the Kubernetes cluster. The Kubernetes Operator uses split horizon + // DNS for replica set members. This feature allows communication both + // within the Kubernetes cluster and from outside Kubernetes. + // +optional + ReplicaSetHorizons ReplicaSetHorizonConfiguration `json:"replicaSetHorizons,omitempty"` + + // Security configures security features, such as TLS, and authentication settings for a deployment + // +required + Security Security `json:"security"` + + // Users specifies the MongoDB users that should be configured in your deployment + // +required + Users []MongoDBUser `json:"users"` + + // +optional + StatefulSetConfiguration StatefulSetConfiguration `json:"statefulSet,omitempty"` + + // AdditionalMongodConfig is additional configuration that can be passed to + // each data-bearing mongod at runtime. Uses the same structure as the mongod + // configuration file: https://docs.mongodb.com/manual/reference/configuration-options/ + // +kubebuilder:validation:Type=object + // +optional + // +kubebuilder:pruning:PreserveUnknownFields + // +nullable + AdditionalMongodConfig MongodConfiguration `json:"additionalMongodConfig,omitempty"` +} + +// ReplicaSetHorizonConfiguration holds the split horizon DNS settings for +// replica set members. +type ReplicaSetHorizonConfiguration []map[string]string + +// CustomRole defines a custom MongoDB role. +type CustomRole struct { + // The name of the role. + Role string `json:"role"` + // The database of the role. + DB string `json:"db"` + // The privileges to grant the role. + Privileges []Privilege `json:"privileges"` + // An array of roles from which this role inherits privileges. + // +optional + Roles []Role `json:"roles"` + // The authentication restrictions the server enforces on the role. + // +optional + AuthenticationRestrictions []AuthenticationRestriction `json:"authenticationRestrictions,omitempty"` +} + +// Privilege defines the actions a role is allowed to perform on a given resource. +type Privilege struct { + Resource Resource `json:"resource"` + Actions []string `json:"actions"` +} + +// Resource specifies specifies the resources upon which a privilege permits actions. +// See https://docs.mongodb.com/manual/reference/resource-document for more. +type Resource struct { + // +optional + DB *string `json:"db,omitempty"` + // +optional + Collection *string `json:"collection,omitempty"` + // +optional + Cluster bool `json:"cluster,omitempty"` + // +optional + AnyResource bool `json:"anyResource,omitempty"` +} + +// AuthenticationRestriction specifies a list of IP addresses and CIDR ranges users +// are allowed to connect to or from. +type AuthenticationRestriction struct { + ClientSource []string `json:"clientSource"` + ServerAddress []string `json:"serverAddress"` +} + +// StatefulSetConfiguration holds the optional custom StatefulSet +// that should be merged into the operator created one. +type StatefulSetConfiguration struct { + // +kubebuilder:pruning:PreserveUnknownFields + SpecWrapper StatefulSetSpecWrapper `json:"spec"` +} + +// StatefulSetSpecWrapper is a wrapper around StatefulSetSpec with a custom implementation +// of MarshalJSON and UnmarshalJSON which delegate to the underlying Spec to avoid CRD pollution. +type StatefulSetSpecWrapper struct { + Spec appsv1.StatefulSetSpec `json:"-"` +} + +// DeepCopy ... +func (m *StatefulSetSpecWrapper) DeepCopy() *StatefulSetSpecWrapper { + return &StatefulSetSpecWrapper{ + Spec: m.Spec, + } +} + +// MongodConfiguration holds the optional mongod configuration +// that should be merged with the operator created one. +// +// The CRD generator does not support map[string]interface{} +// on the top level and hence we need to work around this with +// a wrapping struct. +type MongodConfiguration struct { + Object map[string]interface{} `json:"-"` +} + +// DeepCopy ... +func (m *MongodConfiguration) DeepCopy() *MongodConfiguration { + return &MongodConfiguration{ + Object: runtime.DeepCopyJSON(m.Object), + } +} + +// MongoDBUser ... +type MongoDBUser struct { + // Name is the username of the user + Name string `json:"name"` + + // DB is the database the user is stored in. Defaults to "admin" + // +optional + DB string `json:"db"` + + // PasswordSecretRef is a reference to the secret containing this user's password + PasswordSecretRef SecretKeyReference `json:"passwordSecretRef"` + + // Roles is an array of roles assigned to this user + Roles []Role `json:"roles"` + + // ScramCredentialsSecretName appended by string "scram-credentials" is the name of the secret object created by the mongoDB operator for storing SCRAM credentials + // +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + ScramCredentialsSecretName string `json:"scramCredentialsSecretName"` +} + +// SecretKeyReference is a reference to the secret containing the user's password +type SecretKeyReference struct { + // Name is the name of the secret storing this user's password + Name string `json:"name"` + + // Key is the key in the secret storing this password. Defaults to "password" + // +optional + Key string `json:"key"` +} + +// Role is the database role this user should have +type Role struct { + // DB is the database the role can act on + DB string `json:"db"` + // Name is the name of the role + Name string `json:"name"` +} + +// Security ... +type Security struct { + // +optional + Authentication Authentication `json:"authentication"` + // TLS configuration for both client-server and server-server communication + // +optional + TLS TLS `json:"tls"` + // User-specified custom MongoDB roles that should be configured in the deployment. + // +optional + Roles []CustomRole `json:"roles,omitempty"` +} + +// TLS is the configuration used to set up TLS encryption +type TLS struct { + Enabled bool `json:"enabled"` + + // Optional configures if TLS should be required or optional for connections + // +optional + Optional bool `json:"optional"` + + // CertificateKeySecret is a reference to a Secret containing a private key and certificate to use for TLS. + // The key and cert are expected to be PEM encoded and available at "tls.key" and "tls.crt". + // This is the same format used for the standard "kubernetes.io/tls" Secret type, but no specific type is required. + // +optional + CertificateKeySecret LocalObjectReference `json:"certificateKeySecretRef"` + + // CaConfigMap is a reference to a ConfigMap containing the certificate for the CA which signed the server certificates + // The certificate is expected to be available under the key "ca.crt" + // +optional + CaConfigMap LocalObjectReference `json:"caConfigMapRef"` +} + +// LocalObjectReference is a reference to another Kubernetes object by name. +// TODO: Replace with a type from the K8s API. CoreV1 has an equivalent +// +// "LocalObjectReference" type but it contains a TODO in its +// description that we don't want in our CRD. +type LocalObjectReference struct { + Name string `json:"name"` +} + +// Authentication ... +type Authentication struct { + // Modes is an array specifying which authentication methods should be enabled. + Modes []AuthMode `json:"modes"` + + // IgnoreUnknownUsers set to true will ensure any users added manually (not through the CRD) + // will not be removed. + + // TODO: defaults will work once we update to v1 CRD. + + // +optional + // +kubebuilder:default:=true + // +nullable + IgnoreUnknownUsers *bool `json:"ignoreUnknownUsers,omitempty"` +} + +// AuthMode ... +// +kubebuilder:validation:Enum=SCRAM;SCRAM-SHA-256;SCRAM-SHA-1 +type AuthMode string + +// MongoDBCommunityStatus defines the observed state of MongoDB +type MongoDBCommunityStatus struct { + MongoURI string `json:"mongoUri"` + Phase Phase `json:"phase"` + + CurrentStatefulSetReplicas int `json:"currentStatefulSetReplicas"` + CurrentMongoDBMembers int `json:"currentMongoDBMembers"` + + Message string `json:"message,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status + +// MongoDBCommunity is the Schema for the mongodbs API +// +kubebuilder:subresource:status +// +kubebuilder:resource:path=mongodbcommunity,scope=Namespaced,shortName=mdbc,singular=mongodbcommunity +// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="Current state of the MongoDB deployment" +// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".status.version",description="Version of MongoDB server" +type MongoDBCommunity struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec MongoDBCommunitySpec `json:"spec,omitempty"` + Status MongoDBCommunityStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// MongoDBCommunityList contains a list of MongoDB +type MongoDBCommunityList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []MongoDBCommunity `json:"items"` +} + +func init() { + SchemeBuilder.Register(&MongoDBCommunity{}, &MongoDBCommunityList{}) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1/zz_generated.deepcopy.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..c66b5372c57 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1/zz_generated.deepcopy.go @@ -0,0 +1,428 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright 2021 Red Hat, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 ( + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Authentication) DeepCopyInto(out *Authentication) { + *out = *in + if in.Modes != nil { + in, out := &in.Modes, &out.Modes + *out = make([]AuthMode, len(*in)) + copy(*out, *in) + } + if in.IgnoreUnknownUsers != nil { + in, out := &in.IgnoreUnknownUsers, &out.IgnoreUnknownUsers + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Authentication. +func (in *Authentication) DeepCopy() *Authentication { + if in == nil { + return nil + } + out := new(Authentication) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthenticationRestriction) DeepCopyInto(out *AuthenticationRestriction) { + *out = *in + if in.ClientSource != nil { + in, out := &in.ClientSource, &out.ClientSource + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ServerAddress != nil { + in, out := &in.ServerAddress, &out.ServerAddress + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthenticationRestriction. +func (in *AuthenticationRestriction) DeepCopy() *AuthenticationRestriction { + if in == nil { + return nil + } + out := new(AuthenticationRestriction) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomRole) DeepCopyInto(out *CustomRole) { + *out = *in + if in.Privileges != nil { + in, out := &in.Privileges, &out.Privileges + *out = make([]Privilege, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Roles != nil { + in, out := &in.Roles, &out.Roles + *out = make([]Role, len(*in)) + copy(*out, *in) + } + if in.AuthenticationRestrictions != nil { + in, out := &in.AuthenticationRestrictions, &out.AuthenticationRestrictions + *out = make([]AuthenticationRestriction, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomRole. +func (in *CustomRole) DeepCopy() *CustomRole { + if in == nil { + return nil + } + out := new(CustomRole) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LocalObjectReference) DeepCopyInto(out *LocalObjectReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalObjectReference. +func (in *LocalObjectReference) DeepCopy() *LocalObjectReference { + if in == nil { + return nil + } + out := new(LocalObjectReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongoDBCommunity) DeepCopyInto(out *MongoDBCommunity) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongoDBCommunity. +func (in *MongoDBCommunity) DeepCopy() *MongoDBCommunity { + if in == nil { + return nil + } + out := new(MongoDBCommunity) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MongoDBCommunity) 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 *MongoDBCommunityList) DeepCopyInto(out *MongoDBCommunityList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]MongoDBCommunity, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongoDBCommunityList. +func (in *MongoDBCommunityList) DeepCopy() *MongoDBCommunityList { + if in == nil { + return nil + } + out := new(MongoDBCommunityList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MongoDBCommunityList) 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 *MongoDBCommunitySpec) DeepCopyInto(out *MongoDBCommunitySpec) { + *out = *in + if in.ReplicaSetHorizons != nil { + in, out := &in.ReplicaSetHorizons, &out.ReplicaSetHorizons + *out = make(ReplicaSetHorizonConfiguration, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + } + } + in.Security.DeepCopyInto(&out.Security) + if in.Users != nil { + in, out := &in.Users, &out.Users + *out = make([]MongoDBUser, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.StatefulSetConfiguration.DeepCopyInto(&out.StatefulSetConfiguration) + in.AdditionalMongodConfig.DeepCopyInto(&out.AdditionalMongodConfig) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongoDBCommunitySpec. +func (in *MongoDBCommunitySpec) DeepCopy() *MongoDBCommunitySpec { + if in == nil { + return nil + } + out := new(MongoDBCommunitySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongoDBCommunityStatus) DeepCopyInto(out *MongoDBCommunityStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongoDBCommunityStatus. +func (in *MongoDBCommunityStatus) DeepCopy() *MongoDBCommunityStatus { + if in == nil { + return nil + } + out := new(MongoDBCommunityStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongoDBUser) DeepCopyInto(out *MongoDBUser) { + *out = *in + out.PasswordSecretRef = in.PasswordSecretRef + if in.Roles != nil { + in, out := &in.Roles, &out.Roles + *out = make([]Role, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongoDBUser. +func (in *MongoDBUser) DeepCopy() *MongoDBUser { + if in == nil { + return nil + } + out := new(MongoDBUser) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodConfiguration) DeepCopyInto(out *MongodConfiguration) { + clone := in.DeepCopy() + *out = *clone +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Privilege) DeepCopyInto(out *Privilege) { + *out = *in + in.Resource.DeepCopyInto(&out.Resource) + if in.Actions != nil { + in, out := &in.Actions, &out.Actions + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Privilege. +func (in *Privilege) DeepCopy() *Privilege { + if in == nil { + return nil + } + out := new(Privilege) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in ReplicaSetHorizonConfiguration) DeepCopyInto(out *ReplicaSetHorizonConfiguration) { + { + in := &in + *out = make(ReplicaSetHorizonConfiguration, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *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 ReplicaSetHorizonConfiguration. +func (in ReplicaSetHorizonConfiguration) DeepCopy() ReplicaSetHorizonConfiguration { + if in == nil { + return nil + } + out := new(ReplicaSetHorizonConfiguration) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Resource) DeepCopyInto(out *Resource) { + *out = *in + if in.DB != nil { + in, out := &in.DB, &out.DB + *out = new(string) + **out = **in + } + if in.Collection != nil { + in, out := &in.Collection, &out.Collection + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resource. +func (in *Resource) DeepCopy() *Resource { + if in == nil { + return nil + } + out := new(Resource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Role) DeepCopyInto(out *Role) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Role. +func (in *Role) DeepCopy() *Role { + if in == nil { + return nil + } + out := new(Role) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretKeyReference) DeepCopyInto(out *SecretKeyReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretKeyReference. +func (in *SecretKeyReference) DeepCopy() *SecretKeyReference { + if in == nil { + return nil + } + out := new(SecretKeyReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Security) DeepCopyInto(out *Security) { + *out = *in + in.Authentication.DeepCopyInto(&out.Authentication) + out.TLS = in.TLS + if in.Roles != nil { + in, out := &in.Roles, &out.Roles + *out = make([]CustomRole, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Security. +func (in *Security) DeepCopy() *Security { + if in == nil { + return nil + } + out := new(Security) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StatefulSetConfiguration) DeepCopyInto(out *StatefulSetConfiguration) { + *out = *in + in.SpecWrapper.DeepCopyInto(&out.SpecWrapper) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatefulSetConfiguration. +func (in *StatefulSetConfiguration) DeepCopy() *StatefulSetConfiguration { + if in == nil { + return nil + } + out := new(StatefulSetConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StatefulSetSpecWrapper) DeepCopyInto(out *StatefulSetSpecWrapper) { + clone := in.DeepCopy() + *out = *clone +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLS) DeepCopyInto(out *TLS) { + *out = *in + out.CertificateKeySecret = in.CertificateKeySecret + out.CaConfigMap = in.CaConfigMap +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLS. +func (in *TLS) DeepCopy() *TLS { + if in == nil { + return nil + } + out := new(TLS) + in.DeepCopyInto(out) + return out +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/testutil.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/testutil.go new file mode 100644 index 00000000000..f35a2256429 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/testutil.go @@ -0,0 +1,190 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package infrastructure + +import ( + buildfake "github.com/openshift/client-go/build/clientset/versioned/fake" + v1 "github.com/openshift/client-go/build/clientset/versioned/typed/build/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/discovery" + discfake "k8s.io/client-go/discovery/fake" + "k8s.io/client-go/rest" + clienttesting "k8s.io/client-go/testing" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + kogitocli "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/meta" + + imgfake "github.com/openshift/client-go/image/clientset/versioned/fake" +) + +// FakeClientBuilder create client object for tests +type FakeClientBuilder interface { + AddK8sObjects(objects ...runtime.Object) FakeClientBuilder + AddImageObjects(imageObjs ...runtime.Object) FakeClientBuilder + AddBuildObjects(buildObjs ...runtime.Object) FakeClientBuilder + OnOpenShift() FakeClientBuilder + SupportPrometheus() FakeClientBuilder + SupportOLM() FakeClientBuilder + Build() *kogitocli.Client +} + +// NewFakeClientBuilder provides new object FakeClientBuilder to build a FakeClient. +// Usage: NewFakeClientBuilder().AddK8sObjects(obj1, obj2).Build() +func NewFakeClientBuilder() FakeClientBuilder { + return &fakeClientStruct{} +} + +type fakeClientStruct struct { + objects []runtime.Object + imageObjs []runtime.Object + buildObjs []runtime.Object + openShift bool + prometheus bool + olm bool +} + +// AddK8sObjects ... +func (f *fakeClientStruct) AddK8sObjects(objects ...runtime.Object) FakeClientBuilder { + f.objects = objects + return f +} + +// AddImageObjects add image objects +func (f *fakeClientStruct) AddImageObjects(imageObjs ...runtime.Object) FakeClientBuilder { + f.imageObjs = imageObjs + return f +} + +// AddBuildObjects add build object +func (f *fakeClientStruct) AddBuildObjects(buildObjs ...runtime.Object) FakeClientBuilder { + f.buildObjs = buildObjs + return f +} + +func (f *fakeClientStruct) SupportPrometheus() FakeClientBuilder { + f.prometheus = true + return f +} + +func (f *fakeClientStruct) SupportOLM() FakeClientBuilder { + f.olm = true + return f +} + +// OnOpenShift ... +func (f *fakeClientStruct) OnOpenShift() FakeClientBuilder { + f.openShift = true + return f +} + +// Build ... +func (f *fakeClientStruct) Build() *kogitocli.Client { + // Create a fake client to mock API calls. + cli := fake.NewClientBuilder().WithScheme(meta.GetRegisteredSchema()).WithRuntimeObjects(f.objects...).Build() + // OpenShift Image Client Fake with image tag defined and image built + imgCli := imgfake.NewSimpleClientset(f.imageObjs...).ImageV1() + // OpenShift Build Client Fake with build for s2i defined, since we'll trigger a build during the reconcile phase + buildCli := newBuildFake(f.buildObjs...) + + return &kogitocli.Client{ + ControlCli: cli, + BuildCli: buildCli, + ImageCli: imgCli, + Discovery: f.createFakeDiscoveryClient(), + } +} + +// CreateFakeClient will create a fake client for mock test on Kubernetes env, use cases that depends on OpenShift should use CreateFakeClientOnOpenShift +// Deprecated: use NewFakeClientBuilder().Build() instead. +func CreateFakeClient(objects []runtime.Object, imageObjs []runtime.Object, buildObjs []runtime.Object) *kogitocli.Client { + return NewFakeClientBuilder().AddK8sObjects(objects...).AddImageObjects(imageObjs...).AddBuildObjects(buildObjs...).Build() +} + +// CreateFakeClientOnOpenShift same as CreateFakeClientWithDisco setting openshift flag to true +// Deprecated: use NewFakeClientBuilder().OnOpenShift().Build() instead. +func CreateFakeClientOnOpenShift(objects []runtime.Object, imageObjs []runtime.Object, buildObjs []runtime.Object) *kogitocli.Client { + return NewFakeClientBuilder().AddK8sObjects(objects...).AddImageObjects(imageObjs...).AddBuildObjects(buildObjs...).OnOpenShift().Build() +} + +// CreateFakeDiscoveryClient creates a fake discovery client that supports prometheus, infinispan, strimzi api +func (f *fakeClientStruct) createFakeDiscoveryClient() discovery.DiscoveryInterface { + disco := &discfake.FakeDiscovery{ + Fake: &clienttesting.Fake{ + Resources: []*metav1.APIResourceList{ + {GroupVersion: "infinispan.org/v1"}, + {GroupVersion: "kafka.strimzi.io/v1beta2"}, + {GroupVersion: "keycloak.org/v1alpha1"}, + {GroupVersion: "mongodbcommunity.mongodb.com/v1"}, + {GroupVersion: "app.kiegroup.org/v1beta1"}, + }, + }, + } + + if f.prometheus { + disco.Fake.Resources = append(disco.Fake.Resources, + &metav1.APIResourceList{GroupVersion: "monitoring.coreos.com/v1alpha1"}) + } + + if f.openShift { + disco.Fake.Resources = append(disco.Fake.Resources, + &metav1.APIResourceList{GroupVersion: "openshift.io/v1"}, + &metav1.APIResourceList{GroupVersion: "build.openshift.io/v1"}) + } + + if f.olm { + disco.Fake.Resources = append(disco.Fake.Resources, + &metav1.APIResourceList{GroupVersion: "operators.coreos.com/v1"}) + } + return disco +} + +// ToRuntimeObjects converts RHSysUtils array KubernetesResource into k8s runtime.Object array +func ToRuntimeObjects(resources ...client.Object) []runtime.Object { + var k8sObject []runtime.Object + for _, resource := range resources { + k8sObject = append(k8sObject, resource) + } + return k8sObject +} + +func newBuildFake(objects ...runtime.Object) v1.BuildV1Interface { + return &buildFakeWithMockREST{ + innerClient: buildfake.NewSimpleClientset(objects...).BuildV1(), + } +} + +type buildFakeWithMockREST struct { + innerClient v1.BuildV1Interface +} + +func (b *buildFakeWithMockREST) Builds(namespace string) v1.BuildInterface { + return b.innerClient.Builds(namespace) +} + +func (b *buildFakeWithMockREST) BuildConfigs(namespace string) v1.BuildConfigInterface { + return b.innerClient.BuildConfigs(namespace) +} + +func (b *buildFakeWithMockREST) RESTClient() rest.Interface { + return &rest.RESTClient{} +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/installer.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/installer.go new file mode 100644 index 00000000000..f03d5357a2e --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/installer.go @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" +) + +// InstallerType defines the type of installer for services +type InstallerType string + +const ( + cliInstallerKey = "cli" + crInstallerKey = "cr" +) + +var ( + // CLIInstallerType defines the CLI installer + CLIInstallerType InstallerType = cliInstallerKey + // CRInstallerType defines the CR installer + CRInstallerType InstallerType = crInstallerKey +) + +// GetDefaultInstallerType returns the default installer type for the tests +func GetDefaultInstallerType() InstallerType { + if config.IsCrDeploymentOnly() { + return CRInstallerType + } + return CLIInstallerType +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/kafka.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/kafka.go new file mode 100644 index 00000000000..ea49ff6e58e --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/kafka.go @@ -0,0 +1,174 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" + infrastructure "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +// DeployKafkaInstance deploys an instance of Kafka +func DeployKafkaInstance(namespace string, kafka *v1beta2.Kafka) error { + GetLogger(namespace).Info("Creating Kafka instance %s.", "name", kafka.Name) + + if err := kubernetes.ResourceC(kubeClient).Create(kafka); err != nil { + return fmt.Errorf("Error while creating Kafka: %v ", err) + } + + return nil +} + +// DeployKafkaTopic deploys a Kafka topic +func DeployKafkaTopic(namespace, kafkaTopicName, kafkaInstanceName string) error { + GetLogger(namespace).Info("Creating Kafka", "topic", kafkaTopicName, "instanceName", kafkaInstanceName) + + kafkaTopic := &v1beta2.KafkaTopic{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: kafkaTopicName, + Labels: map[string]string{"strimzi.io/cluster": kafkaInstanceName}, + }, + Spec: v1beta2.KafkaTopicSpec{ + Replicas: 1, + Partitions: 1, + }, + } + + if err := kubernetes.ResourceC(kubeClient).Create(kafkaTopic); err != nil { + return fmt.Errorf("Error while creating Kafka Topic: %v ", err) + } + + return nil +} + +// ScaleKafkaInstanceDown scales a Kafka instance down by killing its pod temporarily +func ScaleKafkaInstanceDown(namespace, kafkaInstanceName string) error { + GetLogger(namespace).Info("Scaling Kafka Instance down", "instance name", kafkaInstanceName) + pods, err := GetKafkaPods(namespace, kafkaInstanceName) + if err != nil { + return err + } else if len(pods.Items) != 1 { + return fmt.Errorf("Kafka instance should have just one kafka pod running") + } + if err = DeleteObject(&pods.Items[0]); err != nil { + return fmt.Errorf("Error scaling Kafka instance down by deleting a kafka pod. The nested error is: %v", err) + } + + return nil +} + +// GetKafkaPods return the Kafka pods (suffixed with `-kafka`) +func GetKafkaPods(namespace, kafkaInstanceName string) (*v1.PodList, error) { + return GetPodsWithLabels(namespace, map[string]string{"strimzi.io/name": kafkaInstanceName + "-kafka"}) +} + +// WaitForMessagesOnTopic waits for at least a certain number of messages are present on the given topic +func WaitForMessagesOnTopic(namespace, kafkaInstanceName, topic string, numberOfMsg int, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("%d message(s) available on topic %s withing %d minutes", numberOfMsg, topic, timeoutInMin), timeoutInMin, + func() (bool, error) { + messages, err := GetMessagesOnTopic(namespace, kafkaInstanceName, topic) + if err != nil { + return false, err + } + GetLogger(namespace).Info(fmt.Sprintf("Got %d messages", len(messages))) + for _, msg := range messages { + GetLogger(namespace).Debug(fmt.Sprintf("Got message: %s", msg)) + } + return len(messages) >= numberOfMsg, nil + }) +} + +// GetMessagesOnTopic gets all messages for a topic +func GetMessagesOnTopic(namespace, kafkaInstanceName, topic string) ([]string, error) { + kafkaInstance, err := GetKafkaInstance(namespace, kafkaInstanceName) + if err != nil { + return nil, err + } + GetLogger(namespace).Debug("Got kafka instance", "instance", kafkaInstance.Name) + bootstrapServer := infrastructure.ResolveKafkaServerURI(kafkaInstance) + if len(bootstrapServer) <= 0 { + GetLogger(namespace).Debug("Not able resolve URI for given kafka instance") + return nil, fmt.Errorf("not able resolve URI for given kafka instance %s", kafkaInstance.Name) + } + GetLogger(namespace).Debug("Got bootstrapServer", "server", bootstrapServer) + + var kafkaPods *v1.PodList + kafkaPods, err = GetKafkaPods(namespace, kafkaInstanceName) + if err != nil { + return nil, fmt.Errorf("Error while retrieving Kafka pods: %v", err) + } else if len(kafkaPods.Items) <= 0 { + return nil, fmt.Errorf("No pods found for Kafka instance") + } + args := []string{"exec", kafkaPods.Items[0].Name} + args = append(args, "-n", namespace) + args = append(args, "--") + args = append(args, "bin/kafka-console-consumer.sh") + args = append(args, "--bootstrap-server", bootstrapServer) + args = append(args, "--topic", topic) + args = append(args, "--from-beginning") + args = append(args, "--timeout-ms", "10000") + + var output string + output, err = CreateCommand("kubectl", args...).WithLoggerContext(namespace).Execute() + if err != nil { + return nil, err + } + GetLogger(namespace).Debug("Got output", "output", output) + lines := strings.Split(output, "\n") + + var messages []string + var result map[string]interface{} + for _, line := range lines { + err = json.Unmarshal([]byte(line), &result) + if err == nil { + messages = append(messages, line) + } + } + + return messages, nil +} + +// GetKafkaInstance retrieves the Kafka instance +func GetKafkaInstance(namespace, kafkaInstanceName string) (*v1beta2.Kafka, error) { + key := types.NamespacedName{ + Namespace: namespace, + Name: kafkaInstanceName, + } + kafkaInstance := &v1beta2.Kafka{} + if exists, err := kubernetes.ResourceC(kubeClient).FetchWithKey(key, kafkaInstance); err != nil { + GetLogger(namespace).Error(err, "Error occurs while fetching kogito kafka instance") + return nil, err + } else if !exists { + GetLogger(namespace).Error(err, "kafka instance does not exist") + return nil, nil + } else { + GetLogger(namespace).Debug("kafka instance found") + return kafkaInstance, nil + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/keycloak.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/keycloak.go new file mode 100644 index 00000000000..48880d4d2d2 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/keycloak.go @@ -0,0 +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. + */ + +package framework + +import ( + "encoding/json" + "fmt" + "regexp" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" + + keycloak "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1" +) + +const ( + keycloakKey = "keycloak" +) + +// DeployKeycloakInstance deploys an instance of Keycloak +func DeployKeycloakInstance(namespace string) error { + GetLogger(namespace).Info("Creating Keycloak instance.") + + keycloak := &keycloak.Keycloak{ + ObjectMeta: createKeycloakMeta(namespace, keycloakKey), + Spec: keycloak.KeycloakSpec{ + Instances: 1, + ExternalAccess: keycloak.KeycloakExternalAccess{ + Enabled: true, + }, + }, + } + + if err := kubernetes.ResourceC(kubeClient).Create(keycloak); err != nil { + return fmt.Errorf("Error while creating Keycloak: %v ", err) + } + + return WaitForPodsWithLabel(namespace, LabelAppKey, keycloakKey, 2, 10) +} + +// DeployKeycloakRealm deploys a realm configuration of Keycloak +func DeployKeycloakRealm(namespace, realmName string) error { + GetLogger(namespace).Info("Creating Keycloak realm", "realmName", realmName) + + realm := &keycloak.KeycloakRealm{ + ObjectMeta: createKeycloakMeta(namespace, realmName), + Spec: keycloak.KeycloakRealmSpec{ + InstanceSelector: &metav1.LabelSelector{ + MatchLabels: createKeycloakLabel(namespace), + }, + Realm: &keycloak.KeycloakAPIRealm{ + ID: realmName, + Realm: realmName, + Enabled: true, + }, + }, + } + + return kubernetes.ResourceC(kubeClient).Create(realm) +} + +// DeployKeycloakClient deploys a client configuration of Keycloak +func DeployKeycloakClient(namespace, clientName string) error { + GetLogger(namespace).Info("Creating Keycloak client", "clientName", clientName) + trueValue := true + client := &keycloak.KeycloakClient{ + ObjectMeta: createKeycloakMeta(namespace, clientName), + Spec: keycloak.KeycloakClientSpec{ + RealmSelector: &metav1.LabelSelector{ + MatchLabels: createKeycloakLabel(namespace), + }, + Client: &keycloak.KeycloakAPIClient{ + ID: clientName, + ClientID: clientName, + Name: clientName, + Enabled: true, + StandardFlowEnabled: true, + DirectAccessGrantsEnabled: true, + ServiceAccountsEnabled: true, + PublicClient: true, + RedirectUris: []string{"*"}, + Protocol: "openid-connect", + FullScopeAllowed: &trueValue, + }, + }, + } + + return kubernetes.ResourceC(kubeClient).Create(client) +} + +// DeployKeycloakUser deploys a realm configuration of Keycloak +func DeployKeycloakUser(namespace, userName, password string) error { + GetLogger(namespace).Info("Creating Keycloak user %s.", "userName", userName) + user := &keycloak.KeycloakUser{ + ObjectMeta: createKeycloakMeta(namespace, userName), + Spec: keycloak.KeycloakUserSpec{ + RealmSelector: &metav1.LabelSelector{ + MatchLabels: createKeycloakLabel(namespace), + }, + User: keycloak.KeycloakAPIUser{ + ID: userName, + UserName: userName, + Email: userName + "@a.com", + EmailVerified: true, + Enabled: true, + Credentials: []keycloak.KeycloakCredential{ + { + Type: "password", + Value: password, + Temporary: false, + }, + }, + }, + }, + } + + return kubernetes.ResourceC(kubeClient).Create(user) +} + +// GetAccessTokenFromKeycloak gets the access token for a user +func GetAccessTokenFromKeycloak(namespace, server, userName, password, realm, clientName string) (string, error) { + path := fmt.Sprintf("auth/realms/%s/protocol/openid-connect/token", realm) + body := fmt.Sprintf("client_id=%s&username=%s&password=%s&grant_type=password", clientName, userName, password) + GetLogger(namespace).Info(fmt.Sprintf("Getting access token for '%s' and server '%s/%s'.", body, server, path)) + + requestInfo := NewPOSTHTTPRequestInfo(server, path, "x-www-form-urlencoded", body) + requestInfo.Unsecure = true + + var target map[string]json.RawMessage + if err := ExecuteHTTPRequestWithUnmarshalledResponse(namespace, requestInfo, &target); err != nil { + return "", err + } + + var accessToken string + if err := json.Unmarshal(target["access_token"], &accessToken); err != nil { + return "", err + } + + return accessToken, nil +} + +// RetrieveKeycloakEndpointURI retrieves the keycloak endpoint +func RetrieveKeycloakEndpointURI(namespace string) (string, error) { + uri, err := WaitAndRetrieveEndpointURI(namespace, keycloakKey) + if err != nil { + return "", err + } + + return regexp.MustCompile(":[0-9]+").ReplaceAllString(uri, ""), nil +} + +func createKeycloakMeta(namespace, name string) metav1.ObjectMeta { + return metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + Labels: createKeycloakLabel(namespace), + } +} + +func createKeycloakLabel(namespace string) map[string]string { + return map[string]string{"app": "keycloak-in-" + namespace} +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/knative.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/knative.go new file mode 100644 index 00000000000..ad94810262b --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/knative.go @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + + 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" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" +) + +// DeployBroker deploys Knative Broker +func DeployBroker(namespace, name string) error { + GetLogger(namespace).Info("Creating Knative Broker", "name", name) + + broker := &eventingv1.Broker{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + } + + if err := kubernetes.ResourceC(kubeClient).Create(broker); err != nil { + return fmt.Errorf("Error while creating Broker: %v ", err) + } + + return nil +} + +// WaitForBrokerResource waits until the Broker ready status is True +func WaitForBrokerResource(namespace, name string, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("Broker %s status to be Success", name), timeoutInMin, + func() (bool, error) { + broker, err := getBrokerResource(namespace, name) + if err != nil { + return false, err + } + if broker == nil { + return false, nil + } + + for _, condition := range broker.Status.Conditions { + if condition.Type == apis.ConditionReady && condition.Status == corev1.ConditionTrue { + return true, nil + } + } + return false, nil + }) +} + +// retrieves the Broker resource +func getBrokerResource(namespace, name string) (*eventingv1.Broker, error) { + broker := &eventingv1.Broker{} + if exists, err := kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: name, Namespace: namespace}, broker); err != nil && !errors.IsNotFound(err) { + return nil, fmt.Errorf("Error while trying to look for Broker %s: %v ", name, err) + } else if !exists { + return nil, nil + } + return broker, nil +} + +// CreateTrigger creates Knative Trigger +func CreateTrigger(namespace, name, brokerName, serviceName string) error { + GetLogger(namespace).Info("Creating Knative Trigger", "name", name, "Broker name", brokerName, "Service name", serviceName) + + // Check that the service exists + if _, err := GetService(namespace, serviceName); err != nil { + return err + } + + trigger := &eventingv1.Trigger{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + Spec: eventingv1.TriggerSpec{ + Broker: brokerName, + Subscriber: duckv1.Destination{ + Ref: &duckv1.KReference{ + APIVersion: corev1.SchemeGroupVersion.Version, + Kind: "Service", + Name: serviceName, + }, + }, + }, + } + + if err := kubernetes.ResourceC(kubeClient).Create(trigger); err != nil { + return fmt.Errorf("Error while creating Trigger: %v ", err) + } + + return nil +} + +// WaitForTrigger waits until the Trigger ready status is True +func WaitForTrigger(namespace, name string, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("Trigger %s status to be Success", name), timeoutInMin, + func() (bool, error) { + trigger, err := getTriggerResource(namespace, name) + if err != nil { + return false, err + } + if trigger == nil { + return false, nil + } + + for _, condition := range trigger.Status.Conditions { + if condition.Type == apis.ConditionReady && condition.Status == corev1.ConditionTrue { + return true, nil + } + } + return false, nil + }) +} + +// retrieves the Trigger resource +func getTriggerResource(namespace, name string) (*eventingv1.Trigger, error) { + trigger := &eventingv1.Trigger{} + if exists, err := kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: name, Namespace: namespace}, trigger); err != nil && !errors.IsNotFound(err) { + return nil, fmt.Errorf("Error while trying to look for Trigger %s: %v ", name, err) + } else if !exists { + return nil, nil + } + return trigger, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitodataindex.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitodataindex.go new file mode 100644 index 00000000000..185aa04f9ed --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitodataindex.go @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + bddtypes "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/types" +) + +const ( + // DataIndexInfinispanImageName is the image name for the Data Index Service with Infinispan + DataIndexInfinispanImageName = "kogito-data-index-infinispan" + // DataIndexMongoDBImageName is the image name for the Data Index Service with MongoDB + DataIndexMongoDBImageName = "kogito-data-index-mongodb" + // DataIndexPostgresqlImageName is the image name for the Data Index Service with PostgreSQL + DataIndexPostgresqlImageName = "kogito-data-index-postgresql" + // DefaultDataIndexImageName is just the image name for the Data Index Service + DefaultDataIndexImageName = DataIndexInfinispanImageName + // DefaultDataIndexName is the default name for the Data Index instance service + DefaultDataIndexName = "data-index" +) + +// InstallKogitoDataIndexService install the Kogito Data Index service +func InstallKogitoDataIndexService(namespace string, installerType InstallerType, dataIndex *bddtypes.KogitoServiceHolder) error { + // Persistence is already configured internally by the Data Index service, so we don't need to add any additional persistence step here. + return InstallService(dataIndex, installerType, "data-index") +} + +// WaitForKogitoDataIndexService wait for Kogito Data Index to be deployed +func WaitForKogitoDataIndexService(namespace string, replicas int, timeoutInMin int) error { + if err := WaitForDeploymentRunning(namespace, getDataIndexServiceName(), replicas, timeoutInMin); err != nil { + return err + } + + // Data Index can be restarted after the deployment of KogitoRuntime, so 2 pods can run in parallel for a while. + // We need to wait for only one (wait until the old one is deleted) + return WaitForPodsWithLabel(namespace, LabelAppKey, getDataIndexServiceName(), replicas, timeoutInMin) +} + +func getDataIndexServiceName() string { + return DefaultDataIndexName +} + +// GetKogitoDataIndexResourceStub Get basic KogitoDataIndex stub with all needed fields initialized +func GetKogitoDataIndexResourceStub(namespace string, replicas int) *v1beta1.KogitoSupportingService { + return &v1beta1.KogitoSupportingService{ + ObjectMeta: NewObjectMetadata(namespace, getDataIndexServiceName()), + Spec: v1beta1.KogitoSupportingServiceSpec{ + ServiceType: api.DataIndex, + // This should be changed to `ephemeral` once inmemory data-index is available + KogitoServiceSpec: NewKogitoServiceSpec(int32(replicas), config.GetServiceImageTag(config.DataIndexImageType, config.InfinispanPersistenceType), DefaultDataIndexImageName), + }, + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitojobsservice.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitojobsservice.go new file mode 100644 index 00000000000..adb2ba04923 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitojobsservice.go @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" + bddtypes "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/types" +) + +const ( + // DefaultJobsServiceImageName is the default image name for the Jobs Service image + DefaultJobsServiceImageName = "kogito-jobs-service-ephemeral" + // JobsServiceInfinispanImageName is the image name for the Jobs Service Service with Infinispan + JobsServiceInfinispanImageName = "kogito-jobs-service-infinispan" + // JobsServiceMongoDBImageName is the image name for the Jobs Service Service with MongoDB + JobsServiceMongoDBImageName = "kogito-jobs-service-mongodb" + // JobsServicePostgresqlImageName is the image name for the Jobs Service Service with PostgreSQL + JobsServicePostgresqlImageName = "kogito-jobs-service-postgresql" + // DefaultJobsServiceName is the default name for the Jobs Services instance service + DefaultJobsServiceName = "jobs-service" +) + +// InstallKogitoJobsService install the Kogito Jobs Service component +func InstallKogitoJobsService(installerType InstallerType, jobsService *bddtypes.KogitoServiceHolder) error { + return InstallService(jobsService, installerType, "jobs-service") +} + +// WaitForKogitoJobsService wait for Kogito Jobs Service to be deployed +func WaitForKogitoJobsService(namespace string, replicas int, timeoutInMin int) error { + return WaitForService(namespace, getJobsServiceName(), replicas, timeoutInMin) +} + +// SetKogitoJobsServiceReplicas sets the number of replicas for the Kogito Jobs Service +func SetKogitoJobsServiceReplicas(namespace string, nbPods int32) error { + GetLogger(namespace).Info("Set Kogito jobs service props", "replica number", nbPods) + kogitoJobsService, err := GetKogitoJobsService(namespace) + if err != nil { + return err + } else if kogitoJobsService == nil { + return fmt.Errorf("No Kogito jobs service found in namespace %s", namespace) + } + kogitoJobsService.Spec.Replicas = &nbPods + return kubernetes.ResourceC(kubeClient).Update(kogitoJobsService) +} + +// GetKogitoJobsService retrieves the running jobs service +func GetKogitoJobsService(namespace string) (*v1beta1.KogitoSupportingService, error) { + service := &v1beta1.KogitoSupportingService{} + if exists, err := kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: getJobsServiceName(), Namespace: namespace}, service); err != nil && !errors.IsNotFound(err) { + return nil, fmt.Errorf("Error while trying to look for Kogito jobs service: %v ", err) + } else if !exists { + return nil, nil + } + return service, nil +} + +// WaitForKogitoJobsServiceLogContainsTextWithinMinutes waits until any pods contains a text +func WaitForKogitoJobsServiceLogContainsTextWithinMinutes(namespace, logText string, timeoutInMin int) error { + return WaitForAnyPodsByDeploymentToContainTextInLog(namespace, getJobsServiceName(), logText, timeoutInMin) +} + +func getJobsServiceName() string { + return DefaultJobsServiceName +} + +// GetKogitoJobsServiceResourceStub Get basic KogitoJobsService stub with all needed fields initialized +func GetKogitoJobsServiceResourceStub(namespace string, replicas int) *v1beta1.KogitoSupportingService { + return &v1beta1.KogitoSupportingService{ + ObjectMeta: NewObjectMetadata(namespace, getJobsServiceName()), + Spec: v1beta1.KogitoSupportingServiceSpec{ + ServiceType: api.JobsService, + KogitoServiceSpec: NewKogitoServiceSpec(int32(replicas), config.GetServiceImageTag(config.JobServiceImageType, config.EphemeralPersistenceType), DefaultJobsServiceImageName), + }, + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitomgmtconsole.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitomgmtconsole.go new file mode 100644 index 00000000000..c88aa861ecd --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitomgmtconsole.go @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + bddtypes "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/types" +) + +const ( + // DefaultMgmtConsoleName ... + DefaultMgmtConsoleName = "management-console" + // DefaultMgmtConsoleImageName ... + DefaultMgmtConsoleImageName = "kogito-management-console" +) + +// InstallKogitoManagementConsole install the Kogito Management Console component +func InstallKogitoManagementConsole(installerType InstallerType, managementConsole *bddtypes.KogitoServiceHolder) error { + return InstallService(managementConsole, installerType, "mgmt-console") +} + +// WaitForKogitoManagementConsoleService wait for Kogito Management Console to be deployed +func WaitForKogitoManagementConsoleService(namespace string, replicas int, timeoutInMin int) error { + return WaitForService(namespace, getManagementConsoleServiceName(), replicas, timeoutInMin) +} + +func getManagementConsoleServiceName() string { + return DefaultMgmtConsoleName +} + +// GetKogitoManagementConsoleResourceStub Get basic KogitoManagementConsole stub with all needed fields initialized +func GetKogitoManagementConsoleResourceStub(namespace string, replicas int) *v1beta1.KogitoSupportingService { + return &v1beta1.KogitoSupportingService{ + ObjectMeta: NewObjectMetadata(namespace, getManagementConsoleServiceName()), + Spec: v1beta1.KogitoSupportingServiceSpec{ + ServiceType: api.MgmtConsole, + KogitoServiceSpec: NewKogitoServiceSpec(int32(replicas), config.GetServiceImageTag(config.ManagementConsoleImageType, config.EphemeralPersistenceType), DefaultMgmtConsoleImageName), + }, + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitoserviceutils.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitoserviceutils.go new file mode 100644 index 00000000000..b8c56284889 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitoserviceutils.go @@ -0,0 +1,193 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" + bddtypes "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/types" +) + +// InstallService install the Kogito Service component +func InstallService(serviceHolder *bddtypes.KogitoServiceHolder, installerType InstallerType, cliDeploymentName string) error { + return installOrDeployService(serviceHolder, installerType, "install", cliDeploymentName) +} + +// DeployService deploy the Kogito Service component +func DeployService(serviceHolder *bddtypes.KogitoServiceHolder, installerType InstallerType) error { + return installOrDeployService(serviceHolder, installerType, "deploy", serviceHolder.GetName()) +} + +// InstallOrDeployService the Kogito Service component +func installOrDeployService(serviceHolder *bddtypes.KogitoServiceHolder, installerType InstallerType, cliDeployCommand, cliDeploymentName string) error { + GetLogger(serviceHolder.GetNamespace()).Info("Installing kogito service", "name", serviceHolder.GetName(), "installerType", installerType, "replicas", *serviceHolder.GetSpec().GetReplicas()) + var err error + switch installerType { + case CLIInstallerType: + if err = cliInstall(serviceHolder, cliDeployCommand, cliDeploymentName); err != nil { + return err + } + if err = patchKogitoProbes(serviceHolder); err != nil { + return err + } + case CRInstallerType: + err = crInstall(serviceHolder) + default: + panic(fmt.Errorf("Unknown installer type %s", installerType)) + } + + if err == nil { + err = OnKogitoServiceDeployed(serviceHolder.GetNamespace(), serviceHolder) + } + + return err +} + +// WaitForService waits that the service has a certain number of replicas +func WaitForService(namespace string, serviceName string, replicas int, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, serviceName+" running", timeoutInMin, + func() (bool, error) { + deployment, err := GetDeployment(namespace, serviceName) + if err != nil { + return false, err + } + if deployment == nil { + return false, nil + } + return deployment.Status.Replicas == int32(replicas) && deployment.Status.AvailableReplicas == int32(replicas), nil + }) +} + +// NewObjectMetadata creates a new Object Metadata object. +func NewObjectMetadata(namespace string, name string) metav1.ObjectMeta { + return metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + } +} + +// NewKogitoServiceSpec creates a new Kogito Service Spec object. +func NewKogitoServiceSpec(replicas int32, fullImage string, defaultImageName string) v1beta1.KogitoServiceSpec { + return v1beta1.KogitoServiceSpec{ + Replicas: &replicas, + Image: NewImageOrDefault(fullImage, defaultImageName), + // Sets insecure image registry as service images can be stored in insecure registries + InsecureImageRegistry: true, + // Extends the probe interval for slow test environment + Probes: v1beta1.KogitoProbe{ + ReadinessProbe: corev1.Probe{ + FailureThreshold: 12, + }, + LivenessProbe: corev1.Probe{ + FailureThreshold: 12, + }, + StartupProbe: corev1.Probe{ + FailureThreshold: 12, + }, + }, + } +} + +// NewImageOrDefault Returns Image parsed from provided image tag or created from configuration options +func NewImageOrDefault(fullImage string, defaultImageName string) string { + if len(fullImage) > 0 { + return fullImage + } + image := &api.Image{ + Domain: config.GetServicesImageRegistry(), + Name: defaultImageName, + Tag: config.GetServicesImageVersion(), + } + // Update image name with suffix if provided + if len(config.GetServicesImageNameSuffix()) > 0 { + image.Name = fmt.Sprintf("%s-%s", image.Name, config.GetServicesImageNameSuffix()) + } + AppendImageDefaultValues(image) + + return ConvertImageToImageTag(*image) +} + +func crInstall(serviceHolder *bddtypes.KogitoServiceHolder) error { + if err := kubernetes.ResourceC(kubeClient).CreateIfNotExists(serviceHolder.KogitoService); err != nil { + return fmt.Errorf("Error creating service: %v", err) + } + return nil +} + +func cliInstall(serviceHolder *bddtypes.KogitoServiceHolder, cliDeployCommand, cliDeploymentName string) error { + return fmt.Errorf("not supported") +} + +// OnKogitoServiceDeployed is called when a service deployed. +func OnKogitoServiceDeployed(namespace string, service api.KogitoService) error { + if !IsOpenshift() { + return ExposeServiceOnKubernetes(namespace, service.GetName()) + } + + return nil +} + +// Kogito CLI doesn't contain all the probe configuration options which are needed to alter the deployments for slow environments. Therefore it is needed to patch CRs directly. +func patchKogitoProbes(serviceHolder *bddtypes.KogitoServiceHolder) error { + var patched api.KogitoService + var err error + for i := 0; i < 3; i++ { + patched, err = newKogitoService(serviceHolder.KogitoService) + if err != nil { + return err + } + + // Fetch deployed service + var exists bool + if exists, err = kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Namespace: serviceHolder.GetNamespace(), Name: serviceHolder.GetName()}, patched); err != nil { + return fmt.Errorf("Error fetching service %s in namespace %s: %v", serviceHolder.GetName(), serviceHolder.GetNamespace(), err) + } else if !exists { + return fmt.Errorf("Service %s in namespace %s doesn't exist", serviceHolder.GetName(), serviceHolder.GetNamespace()) + } + + // Set probe configuration + patched.GetSpec().SetProbes(serviceHolder.GetSpec().GetProbes()) + + // Update deployed service + if err = kubernetes.ResourceC(kubeClient).Update(patched); err == nil { + return nil + } + } + return fmt.Errorf("Error updating service %s in namespace %s: %v", patched.GetName(), patched.GetNamespace(), err) +} + +// Return new empty KogitoService based on same type as parameter +func newKogitoService(s api.KogitoService) (api.KogitoService, error) { + switch v := s.GetSpec().(type) { + case *v1beta1.KogitoSupportingServiceSpec: + return &v1beta1.KogitoSupportingService{}, nil + default: + return nil, fmt.Errorf("Type %T not defined", v) + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitotaskconsole.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitotaskconsole.go new file mode 100644 index 00000000000..4e4c7eb418d --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/kogitotaskconsole.go @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api/app/v1beta1" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + bddtypes "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/types" +) + +const ( + // DefaultTaskConsoleName ... + DefaultTaskConsoleName = "task-console" + // DefaultTaskConsoleImageName ... + DefaultTaskConsoleImageName = "kogito-task-console" +) + +// InstallKogitoTaskConsole install the Kogito Task Console component +func InstallKogitoTaskConsole(installerType InstallerType, taskConsole *bddtypes.KogitoServiceHolder) error { + return InstallService(taskConsole, installerType, "task-console") +} + +// WaitForKogitoTaskConsoleService wait for Kogito Task Console to be deployed +func WaitForKogitoTaskConsoleService(namespace string, replicas int, timeoutInMin int) error { + return WaitForService(namespace, getTaskConsoleServiceName(), replicas, timeoutInMin) +} + +func getTaskConsoleServiceName() string { + return DefaultTaskConsoleName +} + +// GetKogitoTaskConsoleResourceStub Get basic KogitoTaskConsole stub with all needed fields initialized +func GetKogitoTaskConsoleResourceStub(namespace string, replicas int) *v1beta1.KogitoSupportingService { + return &v1beta1.KogitoSupportingService{ + ObjectMeta: NewObjectMetadata(namespace, getTaskConsoleServiceName()), + Spec: v1beta1.KogitoSupportingServiceSpec{ + ServiceType: api.TaskConsole, + KogitoServiceSpec: NewKogitoServiceSpec(int32(replicas), config.GetServiceImageTag(config.TaskConsoleImageType, config.EphemeralPersistenceType), DefaultTaskConsoleImageName), + }, + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/kubernetes.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/kubernetes.go new file mode 100644 index 00000000000..b8555c0f7d7 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/kubernetes.go @@ -0,0 +1,679 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + "strings" + "sync" + "time" + + "sigs.k8s.io/controller-runtime/pkg/client" + + rbac "k8s.io/api/rbac/v1" + + apps "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + k8sv1beta1 "k8s.io/api/extensions/v1beta1" + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "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/apimachinery/pkg/util/intstr" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + kogitocli "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/meta" +) + +var ( + kubeClient *kogitocli.Client + mux = &sync.Mutex{} +) + +const ( + // LabelAppKey is the default label key to bind resources together in "Application Group" + LabelAppKey = "app" +) + +// podErrorReasons contains all the reasons to state a pod in error. +var podErrorReasons = []string{"InvalidImageName"} + +// InitKubeClient initializes the Kubernetes Client +func InitKubeClient(scheme *runtime.Scheme) error { + mux.Lock() + defer mux.Unlock() + if kubeClient == nil { + newClient, err := kogitocli.NewClientBuilder(scheme).UseControllerDynamicMapper().WithDiscoveryClient().WithBuildClient().WithKubernetesExtensionClient().Build() + if err != nil { + return fmt.Errorf("Error initializing kube client: %v", err) + } + kubeClient = newClient + } + return nil +} + +// WaitForPodsWithLabel waits for pods with specific label to be available and running +func WaitForPodsWithLabel(namespace, labelName, labelValue string, numberOfPods, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("%d Pods with label name '%s' and value '%s' available and running", numberOfPods, labelName, labelValue), timeoutInMin, + func() (bool, error) { + pods, err := GetPodsWithLabels(namespace, map[string]string{labelName: labelValue}) + if err != nil || (len(pods.Items) != numberOfPods) { + return false, err + } + + return CheckPodsAreReady(pods), nil + }, CheckPodsWithLabelInError(namespace, labelName, labelValue)) +} + +// WaitForPodsWithLabels waits for pods with specific label to be available and running +func WaitForPodsWithLabels(namespace string, labels map[string]string, numberOfPods, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("%d Pods with labels '%v' available and running", numberOfPods, labels), timeoutInMin, + func() (bool, error) { + pods, err := GetPodsWithLabels(namespace, labels) + if err != nil || (len(pods.Items) != numberOfPods) { + return false, err + } + + return CheckPodsAreReady(pods), nil + }, CheckPodsWithLabelsInError(namespace, labels)) +} + +// WaitForPodsInNamespace waits for pods in specific namespace to be available and running +func WaitForPodsInNamespace(namespace string, numberOfPods, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, "Pods in namespace available and running", timeoutInMin, + func() (bool, error) { + pods, err := GetPods(namespace) + if err != nil || (len(pods.Items) != numberOfPods) { + return false, err + } + + return CheckPodsAreReady(pods), nil + }, CheckPodsInNamespaceInError(namespace)) +} + +// GetPods retrieves all pods in namespace +func GetPods(namespace string) (*corev1.PodList, error) { + pods := &corev1.PodList{} + if err := kubernetes.ResourceC(kubeClient).ListWithNamespace(namespace, pods); err != nil { + return nil, err + } + return pods, nil +} + +// GetPodsByDeploymentConfig retrieves pods with a deploymentconfig label set to +func GetPodsByDeploymentConfig(namespace string, dcName string) (*corev1.PodList, error) { + return GetPodsWithLabels(namespace, map[string]string{"deploymentconfig": dcName}) +} + +// GetPodsByDeployment retrieves pods belonging to a Deployment +func GetPodsByDeployment(namespace string, dName string) (pods []corev1.Pod, err error) { + pods = []corev1.Pod{} + + // Get ReplicaSet related to the Deployment + replicaSet, err := GetActiveReplicaSetByDeployment(namespace, dName) + if err != nil { + return nil, err + } + + // Fetch all pods in namespace + podList := &corev1.PodList{} + if err := kubernetes.ResourceC(kubeClient).ListWithNamespace(namespace, podList); err != nil { + return nil, err + } + + // Find which pods belong to the ReplicaSet + for _, pod := range podList.Items { + for _, ownerReference := range pod.OwnerReferences { + if ownerReference.Kind == "ReplicaSet" && ownerReference.Name == replicaSet.GetName() { + pods = append(pods, pod) + } + } + } + + return +} + +// GetActiveReplicaSetByDeployment retrieves active ReplicaSet belonging to a Deployment +func GetActiveReplicaSetByDeployment(namespace string, dName string) (*apps.ReplicaSet, error) { + replicaSets := &apps.ReplicaSetList{} + if err := kubernetes.ResourceC(kubeClient).ListWithNamespace(namespace, replicaSets); err != nil { + return nil, err + } + + // Find ReplicaSet owned by Deployment with active Pods + for _, replicaSet := range replicaSets.Items { + for _, ownerReference := range replicaSet.OwnerReferences { + if ownerReference.Kind == "Deployment" && ownerReference.Name == dName && replicaSet.Status.AvailableReplicas > 0 { + return &replicaSet, nil + } + } + } + + return nil, fmt.Errorf("No ReplicaSet belonging to Deployment %s found", dName) +} + +// GetPodsWithLabels retrieves pods based on label name and value +func GetPodsWithLabels(namespace string, labels map[string]string) (*corev1.PodList, error) { + pods := &corev1.PodList{} + if err := kubernetes.ResourceC(kubeClient).ListWithNamespaceAndLabel(namespace, pods, labels); err != nil { + return nil, err + } + return pods, nil +} + +// CheckPodsAreReady returns true if all pods are ready +func CheckPodsAreReady(pods *corev1.PodList) bool { + for _, pod := range pods.Items { + if !IsPodStatusConditionReady(&pod) { + return false + } + } + return true +} + +// IsPodRunning returns true if pod is running +func IsPodRunning(pod *corev1.Pod) bool { + return pod.Status.Phase == corev1.PodRunning +} + +// IsPodStatusConditionReady returns true if all pod's containers are ready (really running) +func IsPodStatusConditionReady(pod *corev1.Pod) bool { + for _, condition := range pod.Status.Conditions { + if condition.Type == corev1.ContainersReady { + return condition.Status == corev1.ConditionTrue + } + } + return false +} + +// WaitForDeploymentRunning waits for a deployment to be running, with a specific number of pod +func WaitForDeploymentRunning(namespace, dName string, podNb int, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("Deployment %s running", dName), timeoutInMin, + func() (bool, error) { + if dc, err := GetDeployment(namespace, dName); err != nil { + return false, err + } else if dc == nil { + return false, nil + } else { + GetLogger(namespace).Debug("Deployment has", "available replicas", dc.Status.AvailableReplicas) + return dc.Status.Replicas == int32(podNb) && dc.Status.AvailableReplicas == int32(podNb), nil + } + }) +} + +// GetDeployment retrieves deployment with specified name in namespace +func GetDeployment(namespace, deploymentName string) (*apps.Deployment, error) { + deployment := &apps.Deployment{} + if exists, err := kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: deploymentName, Namespace: namespace}, deployment); err != nil { + return nil, err + } else if !exists { + return nil, nil + } + return deployment, nil +} + +// GetDeploymentWaiting waits for a deployment to be available, then returns it +func GetDeploymentWaiting(namespace, deploymentName string, timeoutInMin int) (deployment *apps.Deployment, err error) { + err = WaitForOnOpenshift(namespace, fmt.Sprintf("Deployment %s is available", deploymentName), timeoutInMin, + func() (bool, error) { + if dc, err := GetDeployment(namespace, deploymentName); err != nil { + return false, err + } else if dc == nil { + return false, nil + } + return true, nil + }) + if err != nil { + return + } + return GetDeployment(namespace, deploymentName) +} + +// LoadResource loads the resource from provided URI and creates it in the cluster +func LoadResource(namespace, uri string, resourceRef client.Object, beforeCreate func(object interface{})) error { + GetLogger(namespace).Debug("loadResource", "uri", uri) + + data, err := ReadFromURI(uri) + if err != nil { + return fmt.Errorf("Unable to read from URI %s: %v", uri, err) + } + + if err = kubernetes.ResourceC(kubeClient).CreateFromYamlContent(data, namespace, resourceRef, beforeCreate); err != nil { + return fmt.Errorf("Error while creating resources from file '%s': %v ", uri, err) + } + return nil +} + +// WaitForAllPodsByDeploymentConfigToContainTextInLog waits for pods of specified deployment config to contain specified text in log +func WaitForAllPodsByDeploymentConfigToContainTextInLog(namespace, dcName, logText string, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("Pods for deployment config '%s' contain text '%s'", dcName, logText), timeoutInMin, + func() (bool, error) { + pods, err := GetPodsByDeploymentConfig(namespace, dcName) + if err != nil { + return false, err + } + + // Container name is equal to deployment config name + return checkAllPodsContainingTextInLog(namespace, pods.Items, dcName, logText) + }, CheckPodsByDeploymentConfigInError(namespace, dcName)) +} + +// WaitForAllPodsByDeploymentToContainTextInLog waits for pods of specified deployment to contain specified text in log +func WaitForAllPodsByDeploymentToContainTextInLog(namespace, dName, logText string, timeoutInMin int) error { + return waitForPodsByDeploymentToContainTextInLog(namespace, dName, logText, timeoutInMin, checkAllPodsContainingTextInLog) +} + +// WaitForAnyPodsByDeploymentToContainTextInLog waits for pods of specified deployment to contain specified text in log +func WaitForAnyPodsByDeploymentToContainTextInLog(namespace, dName, logText string, timeoutInMin int) error { + return waitForPodsByDeploymentToContainTextInLog(namespace, dName, logText, timeoutInMin, checkAnyPodsContainingTextInLog) +} + +func waitForPodsByDeploymentToContainTextInLog(namespace, dName, logText string, timeoutInMin int, predicate func(string, []corev1.Pod, string, string) (bool, error)) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("Pods for deployment '%s' contain text '%s'", dName, logText), timeoutInMin, + func() (bool, error) { + pods, err := GetPodsByDeployment(namespace, dName) + if err != nil { + return false, err + } + + // Container name is equal to deployment config name + return predicate(namespace, pods, dName, logText) + }, CheckPodsByDeploymentInError(namespace, dName)) +} + +func checkAnyPodsContainingTextInLog(namespace string, pods []corev1.Pod, containerName, text string) (bool, error) { + for _, pod := range pods { + containsText, err := isPodContainingTextInLog(namespace, &pod, containerName, text) + if err != nil { + return false, err + } else if containsText { + return true, nil + } + } + + return false, nil +} + +func checkAllPodsContainingTextInLog(namespace string, pods []corev1.Pod, containerName, text string) (bool, error) { + for _, pod := range pods { + containsText, err := isPodContainingTextInLog(namespace, &pod, containerName, text) + if err != nil || !containsText { + return false, err + } + } + return true, nil +} + +func isPodContainingTextInLog(namespace string, pod *corev1.Pod, containerName, text string) (bool, error) { + log, err := kubernetes.PodC(kubeClient).GetLogs(namespace, pod.GetName(), containerName) + return strings.Contains(log, text), err +} + +// GetStatefulSet returns the given StatefulSet +func GetStatefulSet(namespace, name string) (*apps.StatefulSet, error) { + statefulset := &apps.StatefulSet{} + if exists, err := kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: name, Namespace: namespace}, statefulset); err != nil && !errors.IsNotFound(err) { + return nil, fmt.Errorf("Error while trying to look for Infinispan %s: %v ", name, err) + } else if errors.IsNotFound(err) || !exists { + return nil, nil + } + return statefulset, nil +} + +// IsCrdAvailable returns whether the crd is available on cluster +func IsCrdAvailable(crdName string) (bool, error) { + crdEntity := &apiextensionsv1beta1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: crdName, + }, + } + return kubernetes.ResourceC(kubeClient).Fetch(crdEntity) +} + +// CreateObject creates object +func CreateObject(o client.Object) error { + return kubernetes.ResourceC(kubeClient).Create(o) +} + +// GetObjectsInNamespace returns list of objects in specific namespace based on type +func GetObjectsInNamespace(namespace string, list client.ObjectList) error { + return kubernetes.ResourceC(kubeClient).ListWithNamespace(namespace, list) +} + +// GetObjectWithKey returns object matching provided key +func GetObjectWithKey(key types.NamespacedName, o client.Object) (exists bool, err error) { + return kubernetes.ResourceC(kubeClient).FetchWithKey(key, o) +} + +// UpdateObject updates object +func UpdateObject(o client.Object) error { + return kubernetes.ResourceC(kubeClient).Update(o) +} + +// DeleteObject deletes object +func DeleteObject(o client.Object) error { + return kubernetes.ResourceC(kubeClient).Delete(o) +} + +// CreateSecret creates a new secret +func CreateSecret(namespace, name string, secretContent map[string]string) error { + GetLogger(namespace).Info("Create Secret %s", "name", name) + + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Type: corev1.SecretTypeOpaque, + StringData: secretContent, + } + + return kubernetes.ResourceC(kubeClient).Create(secret) +} + +// CheckPodHasImagePullSecretWithPrefix checks that a pod has an image pull secret starting with the given prefix +func CheckPodHasImagePullSecretWithPrefix(pod *corev1.Pod, imagePullSecretPrefix string) bool { + for _, secretRef := range pod.Spec.ImagePullSecrets { + if strings.HasPrefix(secretRef.Name, imagePullSecretPrefix) { + return true + } + } + return false +} + +// CheckPodsByDeploymentConfigInError returns a function that checks the pods error state. +func CheckPodsByDeploymentConfigInError(namespace string, dcName string) func() (bool, error) { + return func() (bool, error) { + pods, err := GetPodsByDeploymentConfig(namespace, dcName) + if err != nil { + return true, err + + } + return checkPodsInError(pods.Items) + } +} + +// CheckPodsByDeploymentInError returns a function that checks the pods error state. +func CheckPodsByDeploymentInError(namespace string, dName string) func() (bool, error) { + return func() (bool, error) { + pods, err := GetPodsByDeployment(namespace, dName) + if err != nil { + return true, err + + } + return checkPodsInError(pods) + } +} + +// CheckPodsWithLabelInError returns a function that checks the pods error state. +func CheckPodsWithLabelInError(namespace, labelName, labelValue string) func() (bool, error) { + return func() (bool, error) { + pods, err := GetPodsWithLabels(namespace, map[string]string{labelName: labelValue}) + if err != nil { + return true, err + + } + return checkPodsInError(pods.Items) + } +} + +// CheckPodsWithLabelsInError returns a function that checks the pods error state. +func CheckPodsWithLabelsInError(namespace string, labels map[string]string) func() (bool, error) { + return func() (bool, error) { + pods, err := GetPodsWithLabels(namespace, labels) + if err != nil { + return true, err + + } + return checkPodsInError(pods.Items) + } +} + +// CheckPodsInNamespaceInError returns a function that checks the pods error state. +func CheckPodsInNamespaceInError(namespace string) func() (bool, error) { + return func() (bool, error) { + pods, err := GetPods(namespace) + if err != nil { + return true, err + + } + return checkPodsInError(pods.Items) + } +} + +func checkPodsInError(pods []corev1.Pod) (bool, error) { + for _, pod := range pods { + if hasErrors, err := isPodInError(&pod); hasErrors { + return true, err + } + } + + return false, nil +} + +func isPodInError(pod *corev1.Pod) (bool, error) { + if IsPodRunning(pod) { + return false, nil + } + + for _, status := range pod.Status.ContainerStatuses { + for _, reason := range podErrorReasons { + if status.State.Waiting != nil && status.State.Waiting.Reason == reason { + return true, fmt.Errorf("Error in pod, reason: %s", reason) + } + } + + } + + return false, nil +} + +func checkPodContainerHasEnvVariableWithValue(pod *corev1.Pod, containerName, envVarName, envVarValue string) bool { + for _, container := range pod.Spec.Containers { + if container.Name == containerName { + for _, env := range container.Env { + if env.Name == envVarName { + return env.Value == envVarValue + } + } + } + } + return false +} + +// GetIngressURI returns the ingress URI +func GetIngressURI(namespace, serviceName string) (string, error) { + ingress := &k8sv1beta1.Ingress{} + if exists, err := kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: serviceName, Namespace: namespace}, ingress); err != nil { + return "", err + } else if !exists { + return "", fmt.Errorf("Ingress %s does not exist in namespace %s", serviceName, namespace) + } else if len(ingress.Spec.Rules) == 0 { + return "", fmt.Errorf("Ingress %s does not have any rules", serviceName) + } + + return fmt.Sprintf("http://%s:80", ingress.Spec.Rules[0].Host), nil +} + +// ExposeServiceOnKubernetes adds ingress CR to expose a service +func ExposeServiceOnKubernetes(namespace, serviceName string) error { + // Needed to retrieve service port to be used + service, err := GetService(namespace, serviceName) + if err != nil { + return err + } + if len(service.Spec.Ports) > 1 { + return fmt.Errorf("Service with name %s contains multiple ports, it is not clear which one should be exposed", serviceName) + } + port := service.Spec.Ports[0].Port + + host := serviceName + if !config.IsLocalCluster() { + host += fmt.Sprintf(".%s.%s", namespace, config.GetDomainSuffix()) + } + + ingress := k8sv1beta1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: serviceName, + Namespace: namespace, + Annotations: map[string]string{"nginx.ingress.kubernetes.io/rewrite-target": "/"}, + }, + Spec: k8sv1beta1.IngressSpec{ + Rules: []k8sv1beta1.IngressRule{ + { + Host: host, + IngressRuleValue: k8sv1beta1.IngressRuleValue{ + HTTP: &k8sv1beta1.HTTPIngressRuleValue{ + Paths: []k8sv1beta1.HTTPIngressPath{ + { + Path: "/", + Backend: k8sv1beta1.IngressBackend{ + ServiceName: serviceName, + ServicePort: intstr.FromInt(int(port)), + }, + }, + }, + }, + }, + }, + }, + }, + } + return kubernetes.ResourceC(kubeClient).Create(&ingress) +} + +// WaitForOnKubernetes is a specific method +func WaitForOnKubernetes(namespace, display string, timeoutInMin int, condition func() (bool, error)) error { + return WaitFor(namespace, display, GetKubernetesDurationFromTimeInMin(timeoutInMin), condition) +} + +// GetKubernetesDurationFromTimeInMin will calculate the time depending on the configured cluster load factor +func GetKubernetesDurationFromTimeInMin(timeoutInMin int) time.Duration { + return time.Duration(timeoutInMin*config.GetLoadFactor()) * time.Minute +} + +// IsOpenshift returns whether the cluster is running on Openshift +func IsOpenshift() bool { + return kubeClient.IsOpenshift() +} + +// GetService return Service based on namespace and name +func GetService(namespace, name string) (*corev1.Service, error) { + service := &corev1.Service{} + if exits, err := kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: name, Namespace: namespace}, service); err != nil { + return nil, err + } else if !exits { + return nil, fmt.Errorf("Service with name %s doesn't exist in given namespace %s", name, namespace) + } + return service, nil +} + +// GetClusterRole return ClusterRole based on name +func GetClusterRole(name string) (*rbac.ClusterRole, error) { + clusterRole := &rbac.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } + if exits, err := kubernetes.ResourceC(kubeClient).Fetch(clusterRole); err != nil { + return nil, err + } else if !exits { + return nil, fmt.Errorf("ClusterRole with name %s doesn't exist", name) + } + return clusterRole, nil +} + +// GetClusterRoleBinding return ClusterRoleBinding based on name +func GetClusterRoleBinding(name string) (*rbac.ClusterRoleBinding, error) { + clusterRoleBinding := &rbac.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } + if exits, err := kubernetes.ResourceC(kubeClient).Fetch(clusterRoleBinding); err != nil { + return nil, err + } else if !exits { + return nil, fmt.Errorf("ClusterRoleBinding with name %s doesn't exist", name) + } + return clusterRoleBinding, nil +} + +// CreateServiceAccount creates ServiceAccount +func CreateServiceAccount(namespace, name string) error { + GetLogger(namespace).Info("Create ServiceAccount", "name", name) + + secret := &corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + } + + return kubernetes.ResourceC(kubeClient).Create(secret) +} + +// CreateConfigMap creates ConfigMap +func CreateConfigMap(namespace, name string, data map[string]string, binaryData map[string][]byte) error { + GetLogger(namespace).Info("Create ConfigMap", "name", name) + + configMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + Data: data, + BinaryData: binaryData, + } + + return kubernetes.ResourceC(kubeClient).Create(configMap) +} + +// IsConfigMapExist returns true if ConfigMap exists +func IsConfigMapExist(key types.NamespacedName) (bool, error) { + exists, err := GetObjectWithKey(key, &corev1.ConfigMap{}) + if err != nil { + return false, fmt.Errorf("Error fetching ConfigMap %s in namespace %s: %v", key.Name, key.Namespace, err) + } + return exists, nil +} + +// PruneNamespaces prunes namespaces stored in the "logs/namespace_history.log" file +func PruneNamespaces() error { + // Create kube client + if err := InitKubeClient(meta.GetRegisteredSchema()); err != nil { + return err + } + + namespaces := GetNamespacesInHistory() + for _, namespace := range namespaces { + if len(namespace) > 0 { + err := DeleteNamespace(namespace) + if err != nil { + GetMainLogger().Error(err, "Error in deleting namespace") + } + } + } + + ClearNamespaceHistory() + return nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/logger/logger.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/logger/logger.go new file mode 100644 index 00000000000..851ab94ad74 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/logger/logger.go @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package logger + +import ( + "io" + "os" + "time" + + "github.com/go-logr/logr" + "github.com/go-logr/zapr" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + logf "sigs.k8s.io/controller-runtime/pkg/log" + logzap "sigs.k8s.io/controller-runtime/pkg/log/zap" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/env" +) + +var ( + defaultOutput = os.Stdout +) + +// Opts describe logger options +type Opts struct { + // Verbose will increase logging + Verbose bool + // Output specifies where to log + Output io.Writer +} + +// Logger shared logger struct +type Logger struct { + logr.Logger +} + +// Debug alternative for info format with DEBUG named and correct log level +func (l Logger) Debug(message string, keysAndValues ...interface{}) { + l.Logger.WithName("DEBUG").V(1).Info(message, keysAndValues...) +} + +// Warn alternative for info format with sprintf and WARN named. +func (l Logger) Warn(message string, keysAndValues ...interface{}) { + l.Logger.WithName("WARNING").V(0).Info(message, keysAndValues...) +} + +// GetLoggerWithOptions returns a custom named logger with given options +func GetLoggerWithOptions(name string, options *Opts) Logger { + if options == nil { + options = getDefaultOpts() + } else if options.Output == nil { + options.Output = defaultOutput + } + return getLogger(name, options) +} + +func getDefaultOpts() *Opts { + return &Opts{ + Verbose: env.GetBoolOSEnv("DEBUG"), + Output: defaultOutput, + } +} + +func getLogger(name string, options *Opts) Logger { + // Set log level... override default w/ command-line variable if set. + // The logger instantiated here can be changed to any logger + // implementing the logr.Logger interface. This logger will + // be propagated through the whole operator, generating + // uniform and structured logs. + logger := Logger{ + createLogger(options).WithName(name), + } + return logger +} + +func createLogger(options *Opts) (logger Logger) { + log := Logger{ + Logger: createZAPLogger(options), + } + + logf.SetLogger(log.Logger) + return log +} + +// createZAPLogger is a Logger implementation. +// If development is true, a Zap development config will be used, +// otherwise a Zap production config will be used +// (stacktraces on errors, sampling). +func createZAPLogger(options *Opts) logr.Logger { + // this basically mimics NewConfig, but with a custom sink + sink := zapcore.AddSync(options.Output) + + var enc zapcore.Encoder + var lvl zap.AtomicLevel + var opts []zap.Option + + if options.Verbose { + encCfg := zap.NewDevelopmentEncoderConfig() + enc = zapcore.NewConsoleEncoder(encCfg) + lvl = zap.NewAtomicLevelAt(zap.DebugLevel) + opts = append(opts, zap.Development(), zap.AddStacktrace(zap.ErrorLevel)) + } else { + encCfg := zap.NewProductionEncoderConfig() + encCfg.TimeKey = "T" + encCfg.EncodeTime = zapcore.ISO8601TimeEncoder + enc = zapcore.NewJSONEncoder(encCfg) + lvl = zap.NewAtomicLevelAt(zap.InfoLevel) + opts = append(opts, zap.WrapCore(func(core zapcore.Core) zapcore.Core { + return zapcore.NewSamplerWithOptions(core, time.Second, 100, 100) + })) + } + opts = append(opts, zap.AddCallerSkip(1), zap.ErrorOutput(sink)) + log := zap.New(zapcore.NewCore(&logzap.KubeAwareEncoder{Encoder: enc, Verbose: options.Verbose}, sink, lvl)) + log = log.WithOptions(opts...) + return zapr.NewLogger(log) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/logging.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/logging.go new file mode 100644 index 00000000000..14217a4f7c1 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/logging.go @@ -0,0 +1,488 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "encoding/csv" + "encoding/json" + "errors" + "fmt" + "io" + "os" + "reflect" + "strings" + "sync" + "time" + + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/env" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/logger" + + "io/ioutil" + + "k8s.io/api/events/v1beta1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" +) + +const ( + defaultLogFolder = "logs" + logSuffix = ".log" + defaultResultsFileName = "results.csv" +) + +var ( + logFolder = defaultLogFolder + + monitoredNamespaces sync.Map + loggerOpts sync.Map +) + +// GetMainLogger returns the main logger +func GetMainLogger() logger.Logger { + return GetLogger("main") +} + +// GetLogger retrieves the logger for a namespace +func GetLogger(namespace string) logger.Logger { + opts, err := getOrCreateLoggerOpts(namespace) + if err != nil { + fallbackLog := log.Log.WithName(namespace) + fallbackLog.Error(err, "Error getting logger", "namespace", namespace) + return logger.Logger{ + Logger: fallbackLog, + } + } + return logger.GetLoggerWithOptions(namespace, opts) +} + +// FlushLogger flushes a specific logger +func FlushLogger(namespace string) error { + opts, exists := getLoggerOpts(namespace) + if !exists { + return fmt.Errorf("Logger %s does not exist... skipping", namespace) + } + if writer, ok := opts.Output.(io.Closer); ok { + err := writer.Close() + loggerOpts.Delete(namespace) + return err + } + return nil +} + +// FlushAllRemainingLoggers flushes all remaining loggers +func FlushAllRemainingLoggers() { + loggerOpts.Range(func(logName, _ interface{}) bool { + if err := FlushLogger(logName.(string)); err != nil { + GetMainLogger().Error(err, "Error flushing logger", "logName", logName) + } + return true + }) +} + +func getLoggerOpts(logName string) (*logger.Opts, bool) { + opts, exists := loggerOpts.Load(logName) + if exists { + return opts.(*logger.Opts), exists + } + return nil, exists +} + +func getOrCreateLoggerOpts(logName string) (*logger.Opts, error) { + opts, exists := getLoggerOpts(logName) + if !exists { + if err := createPrefixedLogFolder(logName); err != nil { + return nil, fmt.Errorf("Error while creating log folder: %v", err) + } + + fileWriter, err := os.Create(getLogFile(logName, "test-run")) + if err != nil { + return nil, fmt.Errorf("Error while creating filewriter: %v", err) + } + + opts = &logger.Opts{ + Output: io.MultiWriter(os.Stdout, fileWriter), + Verbose: env.GetBoolOSEnv("DEBUG"), + } + loggerOpts.Store(logName, opts) + } + + return opts, nil +} + +// RenameLogFolder changes the name of the log folder for a specific namespace +func RenameLogFolder(namespace string, newLogFolderNames ...string) error { + if len(newLogFolderNames) > 1 { + newParentFolderName := strings.Join(newLogFolderNames[0:len(newLogFolderNames)-1], "/") + if err := CreateFolder(GetNamespacedLogFolder(newParentFolderName)); err != nil { + return err + } + } + return os.Rename(GetNamespacedLogFolder(namespace), GetNamespacedLogFolder(strings.Join(newLogFolderNames, "/"))) +} + +// StartPodLogCollector monitors a namespace and stores logs of all pods running in the namespace +func StartPodLogCollector(namespace string) error { + if isNamespaceMonitored(namespace) { + return errors.New("namespace is already monitored") + } + + if err := createPrefixedLogFolder(namespace); err != nil { + return fmt.Errorf("Error while creating log folder: %v", err) + } + + monitoredNamespace := &monitoredNamespace{ + pods: make(map[string]*monitoredPod), + stopMonitoring: make(chan bool), + } + monitoredNamespaces.Store(namespace, monitoredNamespace) + + scanningPeriod := time.NewTicker(5 * time.Second) + defer scanningPeriod.Stop() + for { + select { + case <-monitoredNamespace.stopMonitoring: + return nil + case <-scanningPeriod.C: + if pods, err := GetPods(namespace); err != nil { + GetLogger(namespace).Error(err, "Error while getting pods", "namespace", namespace) + } else { + for _, pod := range pods.Items { + if !isPodMonitored(namespace, pod.Name) && IsPodRunning(&pod) { + initMonitoredPod(namespace, pod.Name) + for _, container := range pod.Spec.Containers { + initMonitoredContainer(namespace, pod.Name, container.Name) + go storeContainerLogWithFollow(namespace, pod.Name, container.Name) + } + } + } + } + } + } +} + +// ReportPerformanceMetric reports a new metric with its value and unit to a results file. If the file does not exist, +// it will be created. It depends on the existence of the log folder which is created by the framework before the tests +// are run. +func ReportPerformanceMetric(metric, value, unit string) { + resultsFile, err := getOrCreateResultsFile() + if err != nil { + GetMainLogger().Error(err, "Error when retrieving the results file") + return + } + defer func() { + err = resultsFile.Close() + if err != nil { + GetMainLogger().Error(err, "Error while closing the results file") + } + }() + + if err = writeCsvValue(resultsFile, []string{metric, value, unit}); err != nil { + GetMainLogger().Error(err, "Error writing a new measurement to the results file") + } +} + +func isNamespaceMonitored(namespace string) bool { + _, exists := monitoredNamespaces.Load(namespace) + return exists +} + +func getOrCreateResultsFile() (*os.File, error) { + resultsFilePath := GetLogFolder() + "/" + defaultResultsFileName + resultsFile, err := os.OpenFile(resultsFilePath, os.O_APPEND|os.O_WRONLY, 0) + if err != nil { + if os.IsNotExist(err) { + resultsFile, err = os.Create(resultsFilePath) + if err != nil { + return nil, fmt.Errorf("Error creating results file: %v", err) + } + if err = writeCsvValue(resultsFile, []string{"Metric", "Value", "Unit"}); err != nil { + return nil, fmt.Errorf("Error while writing header into the results file: %v", err) + } + } else { + return nil, fmt.Errorf("Error while trying opening the results file: %v", err) + } + } + return resultsFile, nil +} + +func writeCsvValue(file *os.File, row []string) error { + csvWriter := csv.NewWriter(file) + if err := csvWriter.Write(row); err != nil { + return fmt.Errorf("Error while writing %s into the results file: %v", row, err) + } + csvWriter.Flush() + return nil +} + +func getLogFile(namespace, filename string) string { + return GetNamespacedLogFolder(namespace) + "/" + filename + logSuffix +} + +// GetLogFolder returns the main log folder +func GetLogFolder() string { + return logFolder +} + +// GetNamespacedLogFolder retrieves the log folder for a specific namespace +func GetNamespacedLogFolder(namespace string) string { + return logFolder + "/" + namespace +} + +func createPrefixedLogFolder(namespace string) error { + return CreateFolder(GetNamespacedLogFolder(namespace)) +} + +func isPodMonitored(namespace, podName string) bool { + _, exists := getMonitoredNamespace(namespace).pods[podName] + return exists +} + +func initMonitoredPod(namespace, podName string) { + monitoredPod := &monitoredPod{ + containers: make(map[string]*monitoredContainer), + } + getMonitoredNamespace(namespace).pods[podName] = monitoredPod +} + +func initMonitoredContainer(namespace, podName, containerName string) { + monitoredContainer := &monitoredContainer{loggingFinished: false} + getMonitoredNamespace(namespace).pods[podName].containers[containerName] = monitoredContainer +} + +func storeContainerLogWithFollow(namespace, podName, containerName string) { + log, err := getContainerLogWithFollow(namespace, podName, containerName) + if err != nil { + GetLogger(namespace).Error(err, "Error while retrieving log of pod", "podName", podName) + return + } + + if isContainerLoggingFinished(namespace, podName, containerName) { + GetLogger(namespace).Debug("Logging already finished, retrieved log will be ignored.", "container", containerName, "podName", podName) + } else { + markContainerLoggingAsFinished(namespace, podName, containerName) + if err := writeLogIntoTheFile(namespace, podName, containerName, log); err != nil { + GetLogger(namespace).Error(err, "Error while writing log into the file") + } + } +} + +// Log is returned once container is terminated +func getContainerLogWithFollow(namespace, podName, containerName string) (string, error) { + return kubernetes.PodC(kubeClient).GetLogsWithFollow(namespace, podName, containerName) +} + +func isContainerLoggingFinished(namespace, podName, containerName string) bool { + monitoredContainer := getMonitoredNamespace(namespace).pods[podName].containers[containerName] + return monitoredContainer.loggingFinished +} + +func markContainerLoggingAsFinished(namespace, podName, containerName string) { + monitoredContainer := getMonitoredNamespace(namespace).pods[podName].containers[containerName] + monitoredContainer.loggingFinished = true +} + +func writeLogIntoTheFile(namespace, podName, containerName, log string) error { + return ioutil.WriteFile(getLogFile(namespace, podName+"-"+containerName), []byte(log), 0644) +} + +// StopPodLogCollector waits until all logs are stored on disc +func StopPodLogCollector(namespace string) error { + if !isNamespaceMonitored(namespace) { + return errors.New("namespace is not monitored") + } + stopNamespaceMonitoring(namespace) + storeUnfinishedContainersLog(namespace) + return nil +} + +func stopNamespaceMonitoring(namespace string) { + getMonitoredNamespace(namespace).stopMonitoring <- true + close(getMonitoredNamespace(namespace).stopMonitoring) +} + +// Write log of all containers of pods in namespace which didn't store their log yet +func storeUnfinishedContainersLog(namespace string) { + for podName, pod := range getMonitoredNamespace(namespace).pods { + for containerName, container := range pod.containers { + if !container.loggingFinished { + storeContainerLog(namespace, podName, containerName) + } + } + } +} + +// Write container log into filesystem +func storeContainerLog(namespace string, podName, containerName string) { + if isContainerLoggingFinished(namespace, podName, containerName) { + GetLogger(namespace).Info("Logging already finished, retrieved log will be ignored.", "container", containerName, "podName", podName) + } else { + log, err := GetContainerLog(namespace, podName, containerName) + if err != nil { + GetLogger(namespace).Error(err, "Error while retrieving log", "container", containerName, "podName", podName) + return + } + + markContainerLoggingAsFinished(namespace, podName, containerName) + if err := writeLogIntoTheFile(namespace, podName, containerName, log); err != nil { + GetLogger(namespace).Error(err, "Error while writing log into the file") + } + } +} + +// GetContainerLog exported for Zookeeper workaround, can be unexported once https://github.com/strimzi/strimzi-kafka-operator/issues/3092 is fixed +func GetContainerLog(namespace, podName, containerName string) (string, error) { + return kubernetes.PodC(kubeClient).GetLogs(namespace, podName, containerName) +} + +func getMonitoredNamespace(namespace string) *monitoredNamespace { + loadedNamespace, exists := monitoredNamespaces.Load(namespace) + if exists { + return loadedNamespace.(*monitoredNamespace) + } + return nil +} + +type monitoredNamespace struct { + pods map[string]*monitoredPod + stopMonitoring chan bool +} + +type monitoredPod struct { + containers map[string]*monitoredContainer +} + +type monitoredContainer struct { + loggingFinished bool +} + +///////////////////////////////////////////////////////////////////////// +// Events logging +///////////////////////////////////////////////////////////////////////// + +const ( + eventLastSeenKey = "LAST_SEEN" + eventFirstSeenKey = "FIRST_SEEN" + eventCountKey = "COUNT" + eventNameKey = "NAME" + eventKindKey = "KIND" + eventSubObjectKey = "SUBOBJECT" + eventTypeKey = "TYPE" + eventReasonKey = "REASON" + eventActionKey = "ACTION" + eventControllerKey = "CONTROLLER" + eventInstanceKey = "INSTANCE" + eventMessageKey = "MESSAGE" +) + +var eventKeys = []string{ + eventLastSeenKey, + eventFirstSeenKey, + eventCountKey, + eventNameKey, + eventKindKey, + eventSubObjectKey, + eventTypeKey, + eventReasonKey, + eventActionKey, + eventControllerKey, + eventInstanceKey, + eventMessageKey, +} + +// BumpEvents will bump all events into events.log file +func BumpEvents(namespace string) error { + eventList, err := kubernetes.EventC(kubeClient).GetEvents(namespace) + if err != nil { + return fmt.Errorf("Error retrieving events from namespace %s: %v", namespace, err) + } + fileWriter, err := os.Create(getLogFile(namespace, "events")) + if err != nil { + return fmt.Errorf("Error while creating filewriter: %v", err) + } + + if err := PrintDataMap(eventKeys, mapEvents(eventList), fileWriter); err != nil { + return err + } + + if err := fileWriter.Close(); err != nil { + return fmt.Errorf("Error while closing filewriter: %v", err) + } + return nil +} + +func mapEvents(eventList *v1beta1.EventList) []map[string]string { + eventMaps := []map[string]string{} + + for _, event := range eventList.Items { + eventMap := make(map[string]string) + eventMap[eventLastSeenKey] = getDefaultIfNull(event.DeprecatedLastTimestamp.Format("2006-01-02 15:04:05")) + eventMap[eventFirstSeenKey] = getDefaultIfNull(event.DeprecatedFirstTimestamp.Format("2006-01-02 15:04:05")) + eventMap[eventNameKey] = getDefaultIfNull(event.GetName()) + eventMap[eventKindKey] = getDefaultIfNull(event.TypeMeta.Kind) + eventMap[eventSubObjectKey] = getDefaultIfNull(event.Regarding.FieldPath) + eventMap[eventTypeKey] = getDefaultIfNull(event.Type) + eventMap[eventReasonKey] = getDefaultIfNull(event.Reason) + eventMap[eventActionKey] = getDefaultIfNull(event.Action) + eventMap[eventControllerKey] = getDefaultIfNull(event.ReportingController) + eventMap[eventInstanceKey] = getDefaultIfNull(event.ReportingInstance) + eventMap[eventMessageKey] = getDefaultIfNull(event.Note) + + eventMaps = append(eventMaps, eventMap) + } + return eventMaps +} + +func getDefaultIfNull(value string) string { + if len(value) <= 0 { + return "-" + } + return value +} + +// LogKubernetesObjects log Kubernetes objects for test analysis +func LogKubernetesObjects(namespace string, runtimeObjects ...client.ObjectList) error { + for _, runtimeObject := range runtimeObjects { + objectName := reflect.TypeOf(runtimeObject).Elem().Name() + + // Fetch list + err := kubernetes.ResourceC(kubeClient).ListWithNamespace(namespace, runtimeObject) + if err != nil { + GetLogger(namespace).Warn("Error logging Kubernetes objects", "namespace", namespace, "error message", err.Error()) + continue + } + + // Format JSON to readable format + json, err := json.MarshalIndent(runtimeObject, "", " ") + if err != nil { + return fmt.Errorf("Error marshalling %s in namespace %s: %v", objectName, namespace, err) + } + + // Write to log folder + err = ioutil.WriteFile(getLogFile(namespace, objectName), []byte(json), 0644) + if err != nil { + return fmt.Errorf("Error storing %s into the file: %v", objectName, err) + } + } + + return nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/maven.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/maven.go new file mode 100644 index 00000000000..c2b444aa966 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/maven.go @@ -0,0 +1,277 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + "io/ioutil" + "strings" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" +) + +const ( + mavenCommandName = "mvn" + + defaultRemoteMavenRepository = "https://repository.apache.org/content/groups/public/" + mainRepositoryID = "main-repository" + stagingRepositoryID = "staging-repository" +) + +// CreateMavenCommand methods initializes the basic data to run maven commands. +func CreateMavenCommand(directory string) MavenCommand { + return &mavenCommandStruct{directory: directory} +} + +// MavenCommand wraps information about the maven command to execute. +type MavenCommand interface { + // WithLoggerContext method attaches a logger context to trace all the command logs when executing it. + WithLoggerContext(loggerContext string) MavenCommand + // Execute command and returns the outputs. + Execute(targets ...string) (string, error) + + // SkipTests will skip testing automatically + SkipTests() MavenCommand + // UpdateArtifacts will force the update of local artifacts + UpdateArtifacts() MavenCommand + // Profiles sets the profiles to execute + Profiles(profiles ...string) MavenCommand + // Options adds additional command line options for the Maven command + Options(options ...string) MavenCommand +} + +type mavenCommandStruct struct { + directory string + loggerContext string + + profiles []string + otherOptions []string + skipTests bool + updateArtifacts bool +} + +func (mvnCmd *mavenCommandStruct) WithLoggerContext(loggerContext string) MavenCommand { + mvnCmd.loggerContext = loggerContext + return mvnCmd +} + +func (mvnCmd *mavenCommandStruct) InDirectory(directory string) MavenCommand { + mvnCmd.directory = directory + return mvnCmd +} + +func (mvnCmd *mavenCommandStruct) SkipTests() MavenCommand { + mvnCmd.skipTests = true + return mvnCmd +} + +func (mvnCmd *mavenCommandStruct) UpdateArtifacts() MavenCommand { + mvnCmd.updateArtifacts = true + return mvnCmd +} + +func (mvnCmd *mavenCommandStruct) Profiles(profiles ...string) MavenCommand { + mvnCmd.profiles = append(mvnCmd.profiles, profiles...) + return mvnCmd +} + +func (mvnCmd *mavenCommandStruct) Options(options ...string) MavenCommand { + mvnCmd.otherOptions = append(mvnCmd.otherOptions, options...) + return mvnCmd +} + +func (mvnCmd *mavenCommandStruct) Execute(targets ...string) (string, error) { + var args []string + + // Setup settings.xml + if err := mvnCmd.setSettingsXML(); err != nil { + return "", err + } + + if !config.IsDisableMavenNativeBuildInContainer() { + mvnCmd.otherOptions = append(mvnCmd.otherOptions, "-Dquarkus.native.container-build=true", fmt.Sprintf("-Dquarkus.native.container-runtime=%s", config.GetContainerEngine())) + if len(config.GetNativeBuilderImage()) > 0 { + mvnCmd.otherOptions = append(mvnCmd.otherOptions, fmt.Sprintf("-Dquarkus.native.builder-image=%s", config.GetNativeBuilderImage())) + } + } + + if mvnCmd.skipTests { + mvnCmd.otherOptions = append(mvnCmd.otherOptions, "-DskipTests") + } + + if mvnCmd.updateArtifacts { + mvnCmd.otherOptions = append(mvnCmd.otherOptions, "-U") + } + + args = append(args, targets...) + if len(mvnCmd.profiles) > 0 { + args = append(args, fmt.Sprintf("-P%s", strings.Join(mvnCmd.profiles, ","))) + } + if len(mvnCmd.otherOptions) > 0 { + args = append(args, mvnCmd.otherOptions...) + } + + // Maven download artifacts configuration + // Same configuration as in https://github.com/kiegroup/kogito-pipelines/blob/main/.ci/pull-request-config.yaml#L6 + args = append(args, "-Dhttp.keepAlive=false", "-Dmaven.wagon.http.pool=false", "-Dmaven.wagon.httpconnectionManager.ttlSeconds=120", "-Dmaven.wagon.http.retryHandler.count=3") + + cmd := CreateCommand(mavenCommandName, args...).InDirectory(mvnCmd.directory) + + // Set logger context if exists + if len(mvnCmd.loggerContext) > 0 { + cmd.WithLoggerContext(mvnCmd.loggerContext) + } + + return cmd.Execute() +} + +// setSettingsXML Creates settings.xml with content based on test configuration +func (mvnCmd *mavenCommandStruct) setSettingsXML() error { + settings := &mavenSettings{} + + // Setup Maven mirror if defined + if mavenMirrorURL := config.GetMavenMirrorURL(); len(mavenMirrorURL) > 0 { + settings.SetMirrorURL(mavenMirrorURL) + mvnCmd.otherOptions = append(mvnCmd.otherOptions, "-Denforcer.skip") + } + + // Setup custom Maven repository if defined + if customMavenRepoURL := config.GetCustomMavenRepoURL(); len(customMavenRepoURL) > 0 { + mvnCmd.otherOptions = append(mvnCmd.otherOptions, "-Denforcer.skip") + + if !config.IsCustomMavenRepoReplaceDefault() { + settings.AddRepository(mainRepositoryID, defaultRemoteMavenRepository, false) + } + settings.AddRepository(stagingRepositoryID, customMavenRepoURL, true) + } else { + settings.AddRepository(mainRepositoryID, defaultRemoteMavenRepository, false) + } + + // Create settings.xml in directory + if err := ioutil.WriteFile(fmt.Sprintf("%s/settings.xml", mvnCmd.directory), []byte(settings.Generate()), 0644); err != nil { + return err + } + + // Add option to get copied settings.xml file + mvnCmd.otherOptions = append(mvnCmd.otherOptions, "-ssettings.xml") + + return nil +} + +type mavenRepository struct { + ID string + URL string + ignoreInMirror bool +} + +type mavenSettings struct { + mirrorURL string + + repositories []mavenRepository +} + +func (settings *mavenSettings) SetMirrorURL(mirrorURL string) *mavenSettings { + settings.mirrorURL = mirrorURL + return settings +} + +func (settings *mavenSettings) AddRepository(repoID, repoURL string, ignoreInMirror bool) *mavenSettings { + settings.repositories = append(settings.repositories, mavenRepository{ + ID: repoID, + URL: repoURL, + ignoreInMirror: ignoreInMirror, + }) + return settings +} + +func (settings *mavenSettings) Generate() string { + settingsContent := settingsMainContent + + if len(settings.mirrorURL) > 0 { + mavenMirrorContent := fmt.Sprintf(mavenMirrorXMLContentTpl, settings.mirrorURL) + settingsContent = strings.ReplaceAll(settingsContent, "", mavenMirrorContent) + } + + if len(settings.repositories) > 0 { + settingsContent = strings.ReplaceAll(settingsContent, "", profilesXMLContent) + } + for _, repo := range settings.repositories { + repositoryContent := fmt.Sprintf(repositoryXMLContentTpl, repo.ID, repo.ID, repo.URL) + settingsContent = strings.ReplaceAll(settingsContent, "", fmt.Sprintf("\n%s\n", repositoryContent)) + settingsContent = strings.ReplaceAll(settingsContent, "", fmt.Sprintf("\n%s\n", repositoryContent)) + + if repo.ignoreInMirror { + // Ignore repo in mirror if exists + settingsContent = strings.ReplaceAll(settingsContent, "", fmt.Sprintf(",!%s", repo.ID)) + } + } + + return settingsContent +} + +const ( + repositoryXMLContentTpl = ` + %s + %s + %s + default + + true + always + + + true + always + ` + + mavenMirrorXMLContentTpl = ` + + + mirror-central + external:* + %s + + ` + + settingsMainContent = ` + + + + + +` + + profilesXMLContent = ` + + + default + + + + + + + + default + ` +) diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/mongodb.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/mongodb.go new file mode 100644 index 00000000000..aa7f84ec46a --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/mongodb.go @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + + v1 "k8s.io/api/apps/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/operator" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/meta" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" + mongodb "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1" +) + +const ( + membersSize = 1 + + mongoDBVersion = "4.2.6" +) + +// DeployMongoDBInstance deploys an instance of Mongo DB +func DeployMongoDBInstance(namespace string, instance *mongodb.MongoDBCommunity) error { + GetLogger(namespace).Info("Creating MongoDB instance") + + if err := kubernetes.ResourceC(kubeClient).Create(instance); err != nil { + return fmt.Errorf("Error while creating MongoDB: %v ", err) + } + + return nil +} + +// CreateMongoDBSecret creates a new secret for MongoDB instance +func CreateMongoDBSecret(namespace, name, password string) error { + GetLogger(namespace).Info("Create MongoDB Secret", "secret", name) + return kubernetes.ResourceC(kubeClient).Create(GetMongoDBSecret(namespace, name, password)) +} + +// GetMongoDBSecret returns a MongoDB secret structure +func GetMongoDBSecret(namespace, secretName, password string) *corev1.Secret { + return &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: namespace, + }, + Type: corev1.SecretTypeOpaque, + StringData: map[string]string{ + infrastructure.DefaultMongoDBPasswordSecretRef: password, + }, + } +} + +// MongoDBUserCred holds information to create a MongoDB user in MongoDB, secretName containing the password +type MongoDBUserCred struct { + Name string + AuthDatabase string + SecretName string + Databases []string +} + +// GetMongoDBStub returns the preconfigured MongoDB stub with set namespace, name and secretName +func GetMongoDBStub(openshift bool, namespace, name string, users []MongoDBUserCred) *mongodb.MongoDBCommunity { + // Taken from https://github.com/mongodb/mongodb-kubernetes-operator/blob/v0.7.0/config/samples/mongodb.com_v1_mongodbcommunity_openshift_cr.yaml + stub := &mongodb.MongoDBCommunity{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + Spec: mongodb.MongoDBCommunitySpec{ + Members: membersSize, + Type: mongodb.ReplicaSet, + Version: mongoDBVersion, + Security: mongodb.Security{Authentication: mongodb.Authentication{Modes: []mongodb.AuthMode{"SCRAM"}}}, + StatefulSetConfiguration: mongodb.StatefulSetConfiguration{ + SpecWrapper: mongodb.StatefulSetSpecWrapper{ + Spec: v1.StatefulSetSpec{ + ServiceName: "example-openshift-mongodb-svc", + Selector: &metav1.LabelSelector{}, + }, + }, + }, + }, + } + for _, user := range users { + userStub := mongodb.MongoDBUser{ + Name: user.Name, + PasswordSecretRef: mongodb.SecretKeyReference{ + Name: user.SecretName, + }, + ScramCredentialsSecretName: user.Name, + } + if len(user.AuthDatabase) > 0 { + userStub.DB = user.AuthDatabase + } else { + // Need to set default else the MongoDB deployment is failing ... + userStub.DB = infrastructure.DefaultMongoDBAuthDatabase + } + for _, database := range user.Databases { + roles := []mongodb.Role{ + { + Name: "dbOwner", + DB: database, + }, + { + Name: "clusterAdmin", + DB: database, + }, + { + Name: "userAdminAnyDatabase", + DB: database, + }, + } + userStub.Roles = append(userStub.Roles, roles...) + } + stub.Spec.Users = append(stub.Spec.Users, userStub) + } + + return stub +} + +// IsMongoDBAvailable checks if MongoDB CRD is available in the cluster +func IsMongoDBAvailable(namespace string) bool { + context := operator.Context{ + Client: kubeClient, + Log: GetLogger(namespace), + Scheme: meta.GetRegisteredSchema(), + } + return infrastructure.NewMongoDBHandler(context).IsMongoDBAvailable() +} + +// SetMongoDBReplicas sets the number of replicas for an MongoDB instance +func SetMongoDBReplicas(namespace, name string, nbPods int) error { + GetLogger(namespace).Info("Set MongoDB props for", "name", name, "replica number", nbPods) + statefulset, err := GetStatefulSet(namespace, name) + if err != nil { + return err + } else if statefulset == nil { + return fmt.Errorf("No Mongodb StatefulSet found with name %s in namespace %s", name, namespace) + } + replicas := int32(nbPods) + statefulset.Spec.Replicas = &replicas + return UpdateObject(statefulset) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/namespace.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/namespace.go new file mode 100644 index 00000000000..d82cfeb5943 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/namespace.go @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + "os" + "strings" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" +) + +const ( + namespaceLogFile = "logs/namespace_history.log" +) + +// CreateNamespace creates a new namespace +func CreateNamespace(namespace string) error { + GetLogger(namespace).Info("Creating namespace", "namespace", namespace) + _, err := kubernetes.NamespaceC(kubeClient).Create(namespace) + if err != nil { + return fmt.Errorf("Cannot create namespace %s: %v", namespace, err) + } + OnNamespacePostCreated(namespace) + return nil +} + +// CreateNamespaceIfNotExists creates a new namespace if not exists, returns true if namespaces already existed +func CreateNamespaceIfNotExists(namespace string) (exists bool, err error) { + GetLogger(namespace).Info("Creating namespace", "namespace", namespace) + _, err = kubernetes.NamespaceC(kubeClient).Create(namespace) + if err != nil { + if errors.IsAlreadyExists(err) { + return true, nil + } + return false, fmt.Errorf("Cannot create namespace %s: %v", namespace, err) + } + OnNamespacePostCreated(namespace) + return false, nil +} + +// DeleteNamespace deletes a namespace +func DeleteNamespace(namespace string) error { + ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}} + GetLogger(namespace).Info("Deleting namespace", "namespace", namespace) + err := kubernetes.ResourceC(kubeClient).Delete(ns) + if err != nil { + return fmt.Errorf("Cannot delete namespace %s: %v", namespace, err) + } + OnNamespacePostDeleted(namespace) + return nil +} + +// IsNamespace checks whether a namespace exists +func IsNamespace(namespace string) (bool, error) { + ns, err := kubernetes.NamespaceC(kubeClient).Fetch(namespace) + if err != nil { + return false, fmt.Errorf("Cannot checking namespace %s: %v", namespace, err) + } + return ns != nil, nil +} + +// OperateOnNamespaceIfExists do some operations on the namespace if that one exists +func OperateOnNamespaceIfExists(namespace string, operate func(namespace string) error) error { + if ok, er := IsNamespace(namespace); er != nil { + return fmt.Errorf("Error while checking namespace: %v", er) + } else if ok { + return operate(namespace) + } + GetLogger(namespace).Warn("Namespace not found for operation") + return nil +} + +// GetNamespacesInHistory retrieves all the namespaces in the history. +func GetNamespacesInHistory() []string { + input, err := os.ReadFile(namespaceLogFile) + if err != nil { + // file does not exist + return []string{} + } + + return strings.Split(string(input), "\n") +} + +// ClearNamespaceHistory clears all the namespace history content. +func ClearNamespaceHistory() { + os.Remove(namespaceLogFile) +} + +// OnNamespacePostCreated hook when a namespace has been created +func OnNamespacePostCreated(namespace string) { + if err := addNamespaceToHistory(namespace); err != nil { + GetLogger(namespace).Warn("Error updating namespace history", "error", err) + } +} + +// OnNamespacePostDeleted hook when a namespace has been deleted +func OnNamespacePostDeleted(namespace string) { + if err := removeNamespaceFromHistory(namespace); err != nil { + GetLogger(namespace).Warn("Error removing namespace of history", "error", err) + } +} + +func addNamespaceToHistory(namespace string) error { + return AddLineToFile(namespace, namespaceLogFile) +} + +func removeNamespaceFromHistory(namespace string) error { + namespaces := GetNamespacesInHistory() + var newNamespaces []string + for _, oldNamespace := range namespaces { + if namespace != oldNamespace { + newNamespaces = append(newNamespaces, oldNamespace) + } + } + + output := strings.Join(newNamespaces, "\n") + return os.WriteFile(namespaceLogFile, []byte(output), permissionMode) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/openshift.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/openshift.go new file mode 100644 index 00000000000..328131102fe --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/openshift.go @@ -0,0 +1,248 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + "time" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + ocapps "github.com/openshift/api/apps/v1" + buildv1 "github.com/openshift/api/build/v1" + imagev1 "github.com/openshift/api/image/v1" + routev1 "github.com/openshift/api/route/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" +) + +const ( + dockerImageKind = "DockerImage" +) + +// WaitForBuildConfigCreated waits for a build config to be created +func WaitForBuildConfigCreated(namespace, buildConfigName string, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("BuildConfig %s created", buildConfigName), timeoutInMin, + func() (bool, error) { + if bc, err := getBuildConfig(namespace, buildConfigName); err != nil { + return false, err + } else if bc == nil { + return false, nil + } + return true, nil + }) +} + +// WaitForBuildConfigCreatedWithWebhooks waits for a build config to be created with webhooks +func WaitForBuildConfigCreatedWithWebhooks(namespace, buildConfigName string, expectedWebhooks []api.WebHookSecretInterface, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("BuildConfig %s created with webhooks", buildConfigName), timeoutInMin, + func() (bool, error) { + if bc, err := getBuildConfig(namespace, buildConfigName); err != nil { + return checkWebhooksInBuildConfig(namespace, bc.Spec.Triggers, expectedWebhooks), err + } else if bc == nil { + return false, nil + } + return true, nil + }) +} + +func checkWebhooksInBuildConfig(namespace string, actual []buildv1.BuildTriggerPolicy, expected []api.WebHookSecretInterface) bool { + for _, expectedWebhook := range expected { + for _, actualTrigger := range actual { + var typedTrigger *buildv1.WebHookTrigger + switch expectedWebhook.GetType() { + case api.GitHubWebHook: + typedTrigger = actualTrigger.GitHubWebHook + case api.GenericWebHook: + typedTrigger = actualTrigger.GenericWebHook + } + + if typedTrigger == nil || typedTrigger.SecretReference.Name != expectedWebhook.GetSecret() { + return false + } + } + } + + return true +} + +func getBuildConfig(namespace, buildConfigName string) (*buildv1.BuildConfig, error) { + bc := &buildv1.BuildConfig{} + if exists, err := kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: buildConfigName, Namespace: namespace}, bc); err != nil && !errors.IsNotFound(err) { + return nil, fmt.Errorf("Error while trying to look for BuildConfig %s: %v ", buildConfigName, err) + } else if errors.IsNotFound(err) || !exists { + return nil, nil + } + return bc, nil +} + +// WaitForDeploymentConfigRunning waits for a deployment config to be running, with a specific number of pod +func WaitForDeploymentConfigRunning(namespace, dcName string, podNb int, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("DeploymentConfig %s running", dcName), timeoutInMin, + func() (bool, error) { + if dc, err := GetDeploymentConfig(namespace, dcName); err != nil { + return false, err + } else if dc == nil { + return false, nil + } else { + GetLogger(namespace).Debug("Deployment config has", "available replicas", dc.Status.AvailableReplicas) + return dc.Status.AvailableReplicas == int32(podNb), nil + } + }, CheckPodsByDeploymentConfigInError(namespace, dcName)) +} + +// GetDeploymentConfig retrieves a deployment config +func GetDeploymentConfig(namespace, dcName string) (*ocapps.DeploymentConfig, error) { + dc := &ocapps.DeploymentConfig{} + if exists, err := kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: dcName, Namespace: namespace}, dc); err != nil && !errors.IsNotFound(err) { + return nil, fmt.Errorf("Error while trying to look for DeploymentConfig %s: %v ", dcName, err) + } else if errors.IsNotFound(err) || !exists { + return nil, nil + } + return dc, nil +} + +// WaitForRoute waits for a route to be available +func WaitForRoute(namespace, routeName string, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("Route %s available", routeName), timeoutInMin, + func() (bool, error) { + route, err := GetRoute(namespace, routeName) + if err != nil || route == nil { + return false, err + } + + return true, nil + }) +} + +// GetRoute retrieves a route +func GetRoute(namespace, routeName string) (*routev1.Route, error) { + route := &routev1.Route{} + if exists, err := + kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Name: routeName, Namespace: namespace}, route); err != nil { + return nil, err + } else if !exists { + return nil, nil + } else { + return route, nil + } +} + +func createHTTPRoute(namespace, serviceName string) error { + GetLogger(namespace).Info("Creating HTTP route", "serviceName", serviceName) + + route := &routev1.Route{ + ObjectMeta: metav1.ObjectMeta{ + Name: serviceName, + Namespace: namespace, + }, + Spec: routev1.RouteSpec{ + To: routev1.RouteTargetReference{ + Kind: "Service", + Name: serviceName, + }, + }, + } + if err := kubernetes.ResourceC(kubeClient).Create(route); err != nil { + return err + } + return nil +} + +// GetRouteURI retrieves a route URI +func GetRouteURI(namespace, serviceName string) (string, error) { + if err := WaitForRoute(namespace, serviceName, 2); err != nil { + return "", fmt.Errorf("Route %s does not exist in namespace %s: %v", serviceName, namespace, err) + } + + route, err := GetRoute(namespace, serviceName) + if err != nil || route == nil { + return "", err + } + host := route.Spec.Host + + protocol := "http" + port := "80" + if route.Spec.TLS != nil { + protocol = "https" + port = "443" + } + + uri := protocol + "://" + host + ":" + port + return uri, nil +} + +// CreateInsecureImageStream creates insecure ImageStream pointing to the passed image tag +func CreateInsecureImageStream(namespace, imageStreamName, imageTag, imageFullName string) error { + GetLogger(namespace).Info("Creating insecure ImageStream", "name", imageStreamName, "imageTag", imageTag, "imageFullName", imageFullName) + + imageStream := &imagev1.ImageStream{ + ObjectMeta: metav1.ObjectMeta{ + Name: imageStreamName, + Namespace: namespace, + }, + Spec: imagev1.ImageStreamSpec{ + Tags: []imagev1.TagReference{ + { + Name: imageTag, + ImportPolicy: imagev1.TagImportPolicy{ + Insecure: true, + }, + ReferencePolicy: imagev1.TagReferencePolicy{ + Type: imagev1.LocalTagReferencePolicy, + }, + From: &corev1.ObjectReference{ + Kind: dockerImageKind, + Name: imageFullName, + }, + }, + }, + }, + } + if err := kubernetes.ResourceC(kubeClient).Create(imageStream); err != nil { + return err + } + return nil +} + +// GetImageStreams returns ImageStreams in the namespace +func GetImageStreams(namespace string) (*imagev1.ImageStreamList, error) { + imageStreams := &imagev1.ImageStreamList{} + if err := GetObjectsInNamespace(namespace, imageStreams); err != nil { + return nil, err + } + return imageStreams, nil +} + +// WaitForOnOpenshift waits for a specification condition +func WaitForOnOpenshift(namespace, display string, timeoutInMin int, condition func() (bool, error), errorConditions ...func() (bool, error)) error { + return WaitFor(namespace, display, GetOpenshiftDurationFromTimeInMin(timeoutInMin), condition, errorConditions...) +} + +// GetOpenshiftDurationFromTimeInMin will calculate the time depending on the configured cluster load factor +func GetOpenshiftDurationFromTimeInMin(timeoutInMin int) time.Duration { + return time.Duration(timeoutInMin*config.GetLoadFactor()) * time.Minute +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/openshift_resources.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/openshift_resources.go new file mode 100644 index 00000000000..be3ca66d7ef --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/openshift_resources.go @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + "strings" + + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" + + "k8s.io/apimachinery/pkg/api/resource" +) + +// WaitForPodsByDeploymentConfigToHaveResources waits for pods to have the expected resources +func WaitForPodsByDeploymentConfigToHaveResources(namespace, dcName string, expected v1.ResourceRequirements, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("Pods for deployment config '%s' to have resources", dcName), timeoutInMin, + func() (bool, error) { + pods, err := GetPodsByDeploymentConfig(namespace, dcName) + if err != nil { + return false, err + } + + return checkResourcesInPods(pods.Items, expected) + }, CheckPodsByDeploymentConfigInError(namespace, dcName)) +} + +// WaitForPodsByDeploymentToHaveResources waits for pods to have the expected resources +func WaitForPodsByDeploymentToHaveResources(namespace, dName string, expected v1.ResourceRequirements, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("Pods for deployment '%s' to have resources", dName), timeoutInMin, + func() (bool, error) { + pods, err := GetPodsByDeployment(namespace, dName) + if err != nil { + return false, err + } + return checkResourcesInPods(pods, expected) + }, CheckPodsByDeploymentInError(namespace, dName)) +} + +// WaitForBuildConfigToHaveResources waits for build config to have the expected resources +func WaitForBuildConfigToHaveResources(namespace, buildConfigName string, expected v1.ResourceRequirements, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("BuildConfig '%s' to have resources", buildConfigName), timeoutInMin, + func() (bool, error) { + return checkResourcesInBuildConfig(namespace, buildConfigName, expected) + }) +} + +// ToResourceRequirements parses the requests and limits into corev1.ResourceRequirements +func ToResourceRequirements(requests string, limits string) corev1.ResourceRequirements { + return corev1.ResourceRequirements{Limits: toResourceList(limits), Requests: toResourceList(requests)} +} + +func toResourceList(resources string) corev1.ResourceList { + resourceList := corev1.ResourceList{} + options := strings.Split(resources, ",") + for _, option := range options { + assignment := strings.Split(option, "=") + resourceList[v1.ResourceName(assignment[0])] = resource.MustParse(assignment[1]) + } + + return resourceList +} + +func getResourceRequirements(cpu, memory string) corev1.ResourceRequirements { + return corev1.ResourceRequirements{ + Limits: corev1.ResourceList{"cpu": resource.MustParse(cpu), "memory": resource.MustParse(memory)}, + Requests: corev1.ResourceList{"cpu": resource.MustParse(cpu), "memory": resource.MustParse(memory)}, + } +} + +func checkResourcesInBuildConfig(namespace string, buildConfigName string, expected corev1.ResourceRequirements) (bool, error) { + bc, err := getBuildConfig(namespace, buildConfigName) + if err != nil { + return false, err + } else if bc == nil { + return false, nil + } + + return isResourceLimitsAndRequestsEqual(bc.Spec.CommonSpec.Resources, expected), nil +} + +func checkResourcesInPods(pods []v1.Pod, expected corev1.ResourceRequirements) (bool, error) { + if len(pods) == 0 { + return false, nil + } + + for _, pod := range pods { + if !checkContainersResources(pod.Spec.Containers, expected) { + return false, nil + } + } + + return true, nil +} + +func checkContainersResources(containers []v1.Container, expected corev1.ResourceRequirements) bool { + for _, container := range containers { + if !isResourceLimitsAndRequestsEqual(container.Resources, expected) { + return false + } + } + + return true +} + +func isResourceLimitsAndRequestsEqual(actual corev1.ResourceRequirements, expected corev1.ResourceRequirements) bool { + return isResourceRequirementsEqual(actual.Limits, expected.Limits) && isResourceRequirementsEqual(actual.Requests, expected.Requests) +} + +func isResourceRequirementsEqual(actual corev1.ResourceList, expected corev1.ResourceList) bool { + if expected == nil { + return true + } + + return actual != nil && isQuantityEqual(actual.Memory(), expected.Memory()) && isQuantityEqual(actual.Cpu(), expected.Cpu()) +} + +func isQuantityEqual(actual *resource.Quantity, expected *resource.Quantity) bool { + if expected == nil { + return true + } + expectedValue := expected.Value() + actualValue := actual.Value() + + return actual != nil && expectedValue == actualValue +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/operator.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/operator.go new file mode 100644 index 00000000000..26c1a54405d --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/operator.go @@ -0,0 +1,532 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/meta" + + v1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/operator" + + olmapiv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1" + olmapiv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1" +) + +const ( + kogitoOperatorTimeoutInMin = 5 + + // createdByBddLabel label marking resources created by BDD tests + createdByBddLabel = "kogito-operator-bdd-tests" + + kogitoOperatorDeploymentName = "kogito-operator-controller-manager" + + // kogitoCatalogSourceName name of the CatalogSource containing Kogito bundle for BDD tests + kogitoCatalogSourceName = "bdd-tests-kogito-catalog" + + // OpenShiftCatalogNamespace is the namespace for clusterwide installations on Openshift + OpenShiftCatalogNamespace = "openshift-marketplace" + // KubernetesCatalogNamespace is the namespace for clusterwide installations on Kubernetes + KubernetesCatalogNamespace = "olm" + + defaultOpenShiftClusterOperatorNamespace = "openshift-operators" + defaultKubernetesClusterOperatorNamespace = "operators" +) + +// OperatorCatalog OLM operator catalog +type OperatorCatalog struct { + source string + namespace string +} + +var ( + kogitoOperatorPullImageSecretPrefix = operator.Name + "-dockercfg" + + // KogitoOperatorMongoDBDependency is the MongoDB identifier for installation + KogitoOperatorMongoDBDependency = infrastructure.MongoDBKind + mongoDBOperatorTimeoutInMin = 10 + + kogitoOperatorCatalogSourceTimeoutInMin = 3 + + operatorGroupTimeoutInMin = 3 +) + +// IsKogitoOperatorRunning returns whether Kogito operator is running +func IsKogitoOperatorRunning(namespace string) (bool, error) { + exists, err := KogitoOperatorExists(namespace) + if err != nil { + if exists { + return false, nil + } + return false, err + } + + return exists, nil +} + +// KogitoOperatorExists returns whether Kogito operator exists and is running. If it is existing but not running, it returns true and an error +func KogitoOperatorExists(namespace string) (bool, error) { + GetLogger(namespace).Debug("Checking Operator", "Deployment", kogitoOperatorDeploymentName, "Namespace", namespace) + + operatorDeployment := &v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: kogitoOperatorDeploymentName, + Namespace: namespace, + }, + } + if exists, err := kubernetes.ResourceC(kubeClient).Fetch(operatorDeployment); err != nil { + return false, fmt.Errorf("Error while trying to look for Deploment %s: %v ", kogitoOperatorDeploymentName, err) + } else if !exists { + return false, nil + } + + if operatorDeployment.Status.AvailableReplicas == 0 { + return true, fmt.Errorf("%s Operator seems to be created in the namespace '%s', but there's no available pods replicas deployed ", operator.Name, namespace) + } + + return true, nil +} + +// WaitForKogitoOperatorRunning waits for Kogito operator running +func WaitForKogitoOperatorRunning(namespace string) error { + return WaitForOnOpenshift(namespace, "Kogito operator running", kogitoOperatorTimeoutInMin, + func() (bool, error) { + running, err := IsKogitoOperatorRunning(namespace) + if err != nil { + return false, err + } + + // If not running, make sure the image pull secret is present in pod + // If not present, delete the pod to allow its reconstruction with correct pull secret + // Note that this is specific to Openshift + if !running && IsOpenshift() { + podList, err := GetPodsWithLabels(namespace, map[string]string{"name": operator.Name}) + if err != nil { + GetLogger(namespace).Error(err, "Error while trying to retrieve Kogito Operator pods") + return false, nil + } + for _, pod := range podList.Items { + if !CheckPodHasImagePullSecretWithPrefix(&pod, kogitoOperatorPullImageSecretPrefix) { + // Delete pod as it has been misconfigured (missing pull secret) + GetLogger(namespace).Info("Kogito Operator pod does not have the image pull secret needed. Deleting it to renew it.") + err := kubernetes.ResourceC(kubeClient).Delete(&pod) + if err != nil { + GetLogger(namespace).Error(err, "Error while trying to delete Kogito Operator pod") + return false, nil + } + } + } + } + return running, nil + }) +} + +// RemoveKogitoOperatorDeployment remove the Kogito operator deployment in the given namespace +func RemoveKogitoOperatorDeployment(namespace string) error { + GetLogger(namespace).Debug("Removing Operator deployment", "Deployment", kogitoOperatorDeploymentName, "Namespace", namespace) + + operatorDeployment := &v1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: kogitoOperatorDeploymentName, + Namespace: namespace, + }, + } + if exists, err := kubernetes.ResourceC(kubeClient).Fetch(operatorDeployment); err != nil { + return fmt.Errorf("Error while trying to look for Deploment %s: %v ", kogitoOperatorDeploymentName, err) + } else if exists { + if err := kubernetes.ResourceC(kubeClient).Delete(operatorDeployment); err != nil { + return fmt.Errorf("Error while trying to remove Deploment %s: %v ", kogitoOperatorDeploymentName, err) + } + } else { + GetLogger(namespace).Warn("No operator deployment to delete", "Deployment", kogitoOperatorDeploymentName) + } + return nil +} + +// InstallOperator installs an operator via subscrition +func InstallOperator(namespace, subscriptionName, channel, startingCSV string, catalog OperatorCatalog) error { + GetLogger(namespace).Info("Subscribing to operator", "subscriptionName", subscriptionName, "catalogSource", catalog.source, "channel", channel) + if _, err := CreateOperatorGroupIfNotExists(namespace, namespace); err != nil { + return err + } + + if err := WaitForOperatorGroup(namespace, namespace); err != nil { + return err + } + + if _, err := CreateNamespacedSubscriptionIfNotExist(namespace, subscriptionName, subscriptionName, catalog, channel, startingCSV); err != nil { + return err + } + + return nil +} + +// InstallClusterWideOperator installs an operator for all namespaces via subscrition +func InstallClusterWideOperator(subscriptionName, channel, startingCSV string, catalog OperatorCatalog) error { + clusterOperatorNamespace := GetClusterOperatorNamespace() + GetLogger(clusterOperatorNamespace).Info("Subscribing to operator", "subscriptionName", subscriptionName, "catalogSource", catalog.source, "channel", channel, "namespace", clusterOperatorNamespace) + if _, err := CreateNamespacedSubscriptionIfNotExist(clusterOperatorNamespace, subscriptionName, subscriptionName, catalog, channel, startingCSV); err != nil { + return err + } + + return nil +} + +// WaitForOperatorRunning waits for an operator to be running +func WaitForOperatorRunning(namespace, operatorPackageName string, catalog OperatorCatalog, timeoutInMin int) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("%s operator running", operatorPackageName), timeoutInMin, + func() (bool, error) { + return IsOperatorRunning(namespace, operatorPackageName, catalog) + }, + func() (bool, error) { + return SubscriptionResolutionFails(namespace, operatorPackageName, catalog.source) + }) +} + +// WaitForClusterWideOperatorRunning waits for a cluster wide operator to be running +func WaitForClusterWideOperatorRunning(operatorPackageName string, catalog OperatorCatalog, timeoutInMin int) error { + clusterOperatorNamespace := GetClusterOperatorNamespace() + return WaitForOperatorRunning(clusterOperatorNamespace, operatorPackageName, catalog, timeoutInMin) +} + +// IsOperatorRunning checks whether an operator is running +func IsOperatorRunning(namespace, operatorPackageName string, catalog OperatorCatalog) (bool, error) { + exists, err := OperatorExistsUsingSubscription(namespace, operatorPackageName, catalog.source) + if err != nil { + if exists { + return false, nil + } + return false, err + } + return exists, nil +} + +// OperatorExistsUsingSubscription returns whether operator exists and is running. If it is existing but not running, it returns true and an error +// For this check informations from subscription are used. +func OperatorExistsUsingSubscription(namespace, operatorPackageName, operatorSource string) (bool, error) { + GetLogger(namespace).Debug("Checking Operator", "Subscription", operatorPackageName, "Namespace", namespace) + + subscription, err := getSubscription(kubeClient, namespace, operatorPackageName, operatorSource) + if err != nil { + return false, err + } else if subscription == nil { + return false, nil + } + GetLogger(namespace).Debug("Found", "Subscription", operatorPackageName) + + subscriptionCsv := subscription.Status.CurrentCSV + if subscriptionCsv == "" { + // Subscription doesn't contain current CSV yet, operator is still being installed. + GetLogger(namespace).Debug("Current CSV not found", "Subscription", operatorPackageName) + return false, nil + } + GetLogger(namespace).Debug("Found current CSV in", "Subscription", subscriptionCsv) + + operatorDeployments := &v1.DeploymentList{} + if err := kubernetes.ResourceC(kubeClient).ListWithNamespaceAndLabel(namespace, operatorDeployments, map[string]string{"olm.owner.kind": "ClusterServiceVersion", "olm.owner": subscriptionCsv}); err != nil { + return false, fmt.Errorf("Error while trying to fetch DC with label olm.owner: '%s' Operator installation: %s ", subscriptionCsv, err) + } + + if len(operatorDeployments.Items) == 0 { + return false, nil + } else if len(operatorDeployments.Items) == 1 && operatorDeployments.Items[0].Status.AvailableReplicas == 0 { + return true, fmt.Errorf("Operator based on Subscription '%s' seems to be created in the namespace '%s', but there's no available pods replicas deployed ", operatorPackageName, namespace) + } + return true, nil +} + +// SubscriptionResolutionFails returns true when Subscription fails to be resolved with error message +func SubscriptionResolutionFails(namespace, operatorPackageName, operatorSource string) (bool, error) { + GetLogger(namespace).Debug("Checking Subscription", "Subscription", operatorPackageName, "Namespace", namespace) + + subscription, err := getSubscription(kubeClient, namespace, operatorPackageName, operatorSource) + if err != nil { + return false, err + } else if subscription == nil { + return false, nil + } + GetLogger(namespace).Debug("Found", "Subscription", operatorPackageName) + + for _, condition := range subscription.Status.Conditions { + // TODO: replace with condition.Type == ResolutionFailed when OLM dependency gets updated + if condition.Reason == "ConstraintsNotSatisfiable" && condition.Status == corev1.ConditionTrue { + return true, fmt.Errorf("Subscription installation fails: %s", condition.Message) + } + } + return false, nil +} + +// CreateOperatorGroupIfNotExists creates an operator group if no exist +func CreateOperatorGroupIfNotExists(namespace, operatorGroupName string) (*olmapiv1.OperatorGroup, error) { + operatorGroup := &olmapiv1.OperatorGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: operatorGroupName, + Namespace: namespace, + }, + Spec: olmapiv1.OperatorGroupSpec{ + TargetNamespaces: []string{namespace}, + }, + } + if err := kubernetes.ResourceC(kubeClient).CreateIfNotExists(operatorGroup); err != nil { + return nil, fmt.Errorf("Error creating OperatorGroup %s: %v", operatorGroupName, err) + } + return operatorGroup, nil +} + +// WaitForOperatorGroup for an operator group to be available +func WaitForOperatorGroup(namespace, operatorGroupName string) error { + return WaitForOnOpenshift(namespace, fmt.Sprintf("%s OperatorGroup is ready", operatorGroupName), operatorGroupTimeoutInMin, + func() (bool, error) { + return isOperatorGroupReady(namespace, operatorGroupName) + }) +} + +func isOperatorGroupReady(namespace, operatorGroupName string) (bool, error) { + operatorGroup := &olmapiv1.OperatorGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: operatorGroupName, + Namespace: namespace, + }, + } + if exists, err := kubernetes.ResourceC(kubeClient).Fetch(operatorGroup); err != nil { + return false, fmt.Errorf("Error while trying to look for OperatorGroup %s: %v ", operatorGroupName, err) + } else if !exists { + return false, nil + } + + for _, ns := range operatorGroup.Status.Namespaces { + if ns == namespace { + return true, nil + } + } + return false, nil +} + +// CreateNamespacedSubscriptionIfNotExist create a namespaced subscription if not exists +func CreateNamespacedSubscriptionIfNotExist(namespace string, subscriptionName string, operatorName string, catalog OperatorCatalog, channel, startingCSV string) (*olmapiv1alpha1.Subscription, error) { + subscription := &olmapiv1alpha1.Subscription{ + ObjectMeta: metav1.ObjectMeta{ + Name: subscriptionName, + Namespace: namespace, + Labels: map[string]string{createdByBddLabel: ""}, + }, + Spec: &olmapiv1alpha1.SubscriptionSpec{ + Package: operatorName, + CatalogSource: catalog.source, + CatalogSourceNamespace: catalog.namespace, + Channel: channel, + StartingCSV: startingCSV, + }, + } + + if err := kubernetes.ResourceC(kubeClient).CreateIfNotExists(subscription); err != nil { + return nil, fmt.Errorf("Error creating Subscription %s: %v", subscriptionName, err) + } + + return subscription, nil +} + +// GetSubscription returns subscription +func GetSubscription(namespace, operatorPackageName string, catalog OperatorCatalog) (*olmapiv1alpha1.Subscription, error) { + subscription, err := getSubscription(kubeClient, namespace, operatorPackageName, catalog.source) + if err != nil { + return nil, err + } else if subscription == nil { + return nil, fmt.Errorf(" Subscription with name %s and operator source %s not found in namespace %s", operatorPackageName, catalog.source, namespace) + } + + return subscription, nil +} + +// GetClusterWideSubscription returns cluster wide subscription +func GetClusterWideSubscription(operatorPackageName string, catalog OperatorCatalog) (*olmapiv1alpha1.Subscription, error) { + return GetSubscription(GetClusterOperatorNamespace(), operatorPackageName, catalog) +} + +// DeleteSubscription deletes Subscription and related objects +func DeleteSubscription(subscription *olmapiv1alpha1.Subscription) error { + installedCsv := subscription.Status.InstalledCSV + suscriptionNamespace := subscription.Namespace + + // If created by BDD + if _, ok := subscription.Labels[createdByBddLabel]; ok { + // Delete Subscription + if err := kubernetes.ResourceC(kubeClient).Delete(subscription); err != nil { + return err + } + + // Delete related CSV + csv := &olmapiv1alpha1.ClusterServiceVersion{} + exists, err := kubernetes.ResourceC(kubeClient).FetchWithKey(types.NamespacedName{Namespace: suscriptionNamespace, Name: installedCsv}, csv) + if err != nil { + return err + } + if exists { + if err := kubernetes.ResourceC(kubeClient).Delete(csv); err != nil { + return err + } + } + } + + return nil +} + +// WaitForMongoDBOperatorRunning waits for MongoDB operator to be running +func WaitForMongoDBOperatorRunning(namespace string) error { + return WaitForOnOpenshift(namespace, "MongoDB operator running", mongoDBOperatorTimeoutInMin, + func() (bool, error) { + return isMongoDBOperatorRunning(namespace) + }) +} + +func isMongoDBOperatorRunning(namespace string) (bool, error) { + context := operator.Context{ + Client: kubeClient, + Log: GetLogger(namespace), + Scheme: meta.GetRegisteredSchema(), + } + mongoDBHandler := infrastructure.NewMongoDBHandler(context) + exists, err := mongoDBHandler.IsMongoDBOperatorAvailable(namespace) + if err != nil { + if exists { + return false, nil + } + return false, err + } + + return exists, nil +} + +// CreateKogitoOperatorCatalogSource create a Kogito operator catalog Source +func CreateKogitoOperatorCatalogSource() (*olmapiv1alpha1.CatalogSource, error) { + catalogNamespace := GetCustomKogitoOperatorCatalog().namespace + GetLogger(catalogNamespace).Info("Installing custom Kogito operator CatalogSource", "name", kogitoCatalogSourceName, "namespace", catalogNamespace) + + cs := &olmapiv1alpha1.CatalogSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: GetCustomKogitoOperatorCatalog().source, + Namespace: GetCustomKogitoOperatorCatalog().namespace, + }, + Spec: olmapiv1alpha1.CatalogSourceSpec{ + SourceType: olmapiv1alpha1.SourceTypeGrpc, + Image: config.GetOperatorCatalogImage(), + Description: "Catalog containing custom Kogito bundle used for BDD tests", + }, + } + + if err := kubernetes.ResourceC(kubeClient).CreateIfNotExists(cs); err != nil { + return nil, fmt.Errorf("Error creating CatalogSource %s: %v", kogitoCatalogSourceName, err) + } + + return cs, nil +} + +// WaitForKogitoOperatorCatalogSourceReady waits for Kogito operator CatalogSource to be ready +func WaitForKogitoOperatorCatalogSourceReady() error { + return WaitForOnOpenshift(GetCustomKogitoOperatorCatalog().namespace, "Kogito operator CatalogSource is ready", kogitoOperatorCatalogSourceTimeoutInMin, + func() (bool, error) { + return isKogitoOperatorCatalogSourceReady() + }) +} + +func isKogitoOperatorCatalogSourceReady() (bool, error) { + cs := &olmapiv1alpha1.CatalogSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: GetCustomKogitoOperatorCatalog().source, + Namespace: GetCustomKogitoOperatorCatalog().namespace, + }, + } + if exists, err := kubernetes.ResourceC(kubeClient).Fetch(cs); err != nil { + return false, fmt.Errorf("Error while trying to look for CatalogSource %s: %v ", kogitoCatalogSourceName, err) + } else if !exists { + return false, nil + } + + if cs.Status.GRPCConnectionState == nil || cs.Status.GRPCConnectionState.LastObservedState != "READY" { + return false, nil + } + return true, nil +} + +// DeleteKogitoOperatorCatalogSource delete a Kogito operator catalog Source +func DeleteKogitoOperatorCatalogSource() error { + GetLogger(GetCustomKogitoOperatorCatalog().namespace).Info("Deleting custom Kogito operator CatalogSource", "name", kogitoCatalogSourceName, "namespace", GetCustomKogitoOperatorCatalog().namespace) + + cs := &olmapiv1alpha1.CatalogSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: GetCustomKogitoOperatorCatalog().source, + Namespace: GetCustomKogitoOperatorCatalog().namespace, + }, + } + + if err := kubernetes.ResourceC(kubeClient).Delete(cs); err != nil { + return fmt.Errorf("Error deleting CatalogSource %s: %v", kogitoCatalogSourceName, err) + } + + return nil +} + +// GetClusterOperatorNamespace returns namespace used to deploy cluster wide operators +func GetClusterOperatorNamespace() string { + if olmNamespace := config.GetOlmNamespace(); len(olmNamespace) > 0 { + return olmNamespace + } + if IsOpenshift() { + return defaultOpenShiftClusterOperatorNamespace + } + return defaultKubernetesClusterOperatorNamespace +} + +// GetCommunityCatalog returns OperatorCatalog with community operators +func GetCommunityCatalog() OperatorCatalog { + if IsOpenshift() { + return GetOperatorCatalog(OpenShiftCatalogNamespace, "community-operators") + } + return GetOperatorCatalog(KubernetesCatalogNamespace, "operatorhubio-catalog") +} + +// GetProductCatalog returns OperatorCatalog with red hat operators +func GetProductCatalog() OperatorCatalog { + return GetOperatorCatalog(OpenShiftCatalogNamespace, "redhat-operators") +} + +// GetCustomKogitoOperatorCatalog returns OperatorCatalog containing custom Kogito operator informations +func GetCustomKogitoOperatorCatalog() OperatorCatalog { + if IsOpenshift() { + return GetOperatorCatalog(OpenShiftCatalogNamespace, kogitoCatalogSourceName) + } + return GetOperatorCatalog(KubernetesCatalogNamespace, kogitoCatalogSourceName) +} + +// GetOperatorCatalog creates the operator catalog based given on Source and namespace +func GetOperatorCatalog(namespace, source string) OperatorCatalog { + return OperatorCatalog{ + source: source, + namespace: namespace, + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/operator/context.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/operator/context.go new file mode 100644 index 00000000000..1abf7b9e593 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/operator/context.go @@ -0,0 +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. + */ + +package operator + +import ( + "k8s.io/apimachinery/pkg/runtime" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/logger" +) + +// Context ... +type Context struct { + Client *client.Client + Log logger.Logger + Scheme *runtime.Scheme + Version string + Labels map[string]string + DeploymentIdentifier string +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/operator/operator.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/operator/operator.go new file mode 100644 index 00000000000..ef645f93837 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/operator/operator.go @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package operator + +const ( + // Name is the name of the Kogito Operator deployed in a namespace + Name = "kogito-operator" + // KogitoHomeDir path for Kogito home mounted within the pod of a Kogito Service + KogitoHomeDir = "/home/kogito" + // KogitoRuntimeKey ... + KogitoRuntimeKey = "kogito.kie.org/runtime" + // KogitoSupportingServiceKey ... + KogitoSupportingServiceKey = "kogito.kie.org/supporting.service" +) diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/postgresql.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/postgresql.go new file mode 100644 index 00000000000..688e1ebe5ca --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/postgresql.go @@ -0,0 +1,181 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + + apps "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + // Equals to PostgreSQL 12.7, using digest for image mirroring + postgresqlImage = "docker.io/library/postgres@sha256:d36e6b8b3e1fae1d36f2fb785005714ad9094c22103c7d5bc5c21635fbb3a0a7" + + postgresqlPort = 5432 + postgresqlPersistentVolumeCapacity = "1Gi" + + postgresqlLabelName = "app" + postgresqlLabelValue = "postgres" +) + +// WaitForPostgresqlInstance waits for Postgresql instance pods to be up +func WaitForPostgresqlInstance(namespace string, nbPods, timeoutInMin int) error { + return WaitForPodsWithLabel(namespace, postgresqlLabelName, postgresqlLabelValue, nbPods, timeoutInMin) +} + +// CreatePostgresqlInstance creates a new Postgresql instance +func CreatePostgresqlInstance(namespace, name string, nbPods int, username, password, databaseName string) error { + + pvc := getPostgresqlPersistentVolumeClaimResource(namespace, name) + if err := CreateObject(pvc); err != nil { + return err + } + + d := getPostgresqlDeploymentResource(namespace, name, nbPods, username, password, databaseName) + if err := CreateObject(d); err != nil { + return err + } + + s := getPostgresqlServiceResource(namespace, name) + if err := CreateObject(s); err != nil { + return err + } + + return nil +} + +func getPostgresqlDeploymentResource(namespace, name string, nbPods int, username, password, databaseName string) *apps.Deployment { + replicas := int32(nbPods) + return &apps.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: apps.DeploymentSpec{ + Replicas: &replicas, + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{postgresqlLabelName: postgresqlLabelValue}, + }, + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{postgresqlLabelName: postgresqlLabelValue}, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: name, + Image: postgresqlImage, + Ports: []v1.ContainerPort{ + {ContainerPort: postgresqlPort}, + }, + Env: []v1.EnvVar{ + {Name: "POSTGRES_USER", Value: username}, + {Name: "POSTGRES_PASSWORD", Value: password}, + {Name: "POSTGRES_DB", Value: databaseName}, + // Needed due to issues with owner of /var/lib/postgresql/data folder + {Name: "PGDATA", Value: "/var/lib/postgresql/data/pgdata"}, + }, + VolumeMounts: []v1.VolumeMount{ + {MountPath: "/var/lib/postgresql/data", Name: name}, + }, + LivenessProbe: &v1.Probe{ + InitialDelaySeconds: 30, + PeriodSeconds: 10, + TimeoutSeconds: 5, + SuccessThreshold: 1, + FailureThreshold: 6, + ProbeHandler: v1.ProbeHandler{ + Exec: &v1.ExecAction{ + Command: []string{"bash", "-ec", "PGPASSWORD=$POSTGRES_PASSWORD psql -w -U '" + username + "' -d '" + databaseName + "' -h 127.0.0.1 -c 'SELECT 1'"}, + }, + }, + }, + ReadinessProbe: &v1.Probe{ + InitialDelaySeconds: 5, + PeriodSeconds: 10, + TimeoutSeconds: 5, + SuccessThreshold: 1, + FailureThreshold: 6, + ProbeHandler: v1.ProbeHandler{ + Exec: &v1.ExecAction{ + Command: []string{"bash", "-ec", "PGPASSWORD=$POSTGRES_PASSWORD psql -w -U '" + username + "' -d '" + databaseName + "' -h 127.0.0.1 -c 'SELECT 1'"}, + }, + }, + }, + }, + }, + Volumes: []v1.Volume{ + { + Name: name, + VolumeSource: v1.VolumeSource{PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ClaimName: name}}, + }, + }, + }, + }, + }, + } +} + +func getPostgresqlServiceResource(namespace, name string) *corev1.Service { + return &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: v1.ServiceSpec{ + Ports: []v1.ServicePort{{Port: postgresqlPort}}, + Selector: map[string]string{postgresqlLabelName: postgresqlLabelValue}, + }, + } +} + +func getPostgresqlPersistentVolumeClaimResource(namespace, name string) *corev1.PersistentVolumeClaim { + return &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: v1.PersistentVolumeClaimSpec{ + AccessModes: []v1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{corev1.ResourceStorage: resource.MustParse(postgresqlPersistentVolumeCapacity)}, + }, + }, + } +} + +// SetPostgresqlReplicas sets the number of replicas for an Postgresql instance +func SetPostgresqlReplicas(namespace, name string, nbPods int) error { + GetLogger(namespace).Info("Set Postgresql props for", "name", name, "replica number", nbPods) + deployment, err := GetDeployment(namespace, name) + if err != nil { + return err + } else if deployment == nil { + return fmt.Errorf("No Postgresql Deployment found with name %s in namespace %s", name, namespace) + } + replicas := int32(nbPods) + deployment.Spec.Replicas = &replicas + return UpdateObject(deployment) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/process.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/process.go new file mode 100644 index 00000000000..5b640533a21 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/process.go @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +// StartProcess starts new process instance +func StartProcess(namespace, routeURI, processName, bodyFormat, bodyContent string) (err error) { + requestInfo := NewPOSTHTTPRequestInfo(routeURI, processName, bodyFormat, bodyContent) + _, err = ExecuteHTTPRequest(namespace, requestInfo) + return +} + +// GetProcessInstances retrieves process instance of process name +func GetProcessInstances(namespace, routeURI, processName string) (foundProcessInstances []map[string]interface{}, err error) { + requestInfo := NewGETHTTPRequestInfo(routeURI, processName) + err = ExecuteHTTPRequestWithUnmarshalledResponse(namespace, requestInfo, &foundProcessInstances) + return +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/prometheus.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/prometheus.go new file mode 100644 index 00000000000..a8e8a6ad66f --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/prometheus.go @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + monv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" +) + +const ( + // Default Prometheus service name + defaultPrometheusService = "prometheus-operated" +) + +// DeployPrometheusInstance deploys an instance of Prometheus +func DeployPrometheusInstance(namespace, labelName, labelValue string) error { + GetLogger(namespace).Info("Creating Prometheus CR to spin up instance.") + + replicas := int32(1) + prometheusCR := &monv1.Prometheus{ + ObjectMeta: metav1.ObjectMeta{ + Name: "prometheus", + Namespace: namespace, + }, + Spec: monv1.PrometheusSpec{ + Replicas: &replicas, + // Default service account for Prometheus is created + ServiceAccountName: "prometheus-k8s", + ServiceMonitorSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{labelName: labelValue}, + }, + }, + } + if err := kubernetes.ResourceC(kubeClient).Create(prometheusCR); err != nil { + return fmt.Errorf("Error while creating Prometheus CR: %v ", err) + } + + if IsOpenshift() { + // Prometheus doesn't create route by default, need to create it manually + if err := createHTTPRoute(namespace, defaultPrometheusService); err != nil { + return fmt.Errorf("Error while creating Prometheus route: %v ", err) + } + } else { + // Need to expose Prometheus + if err := ExposeServiceOnKubernetes(namespace, defaultPrometheusService); err != nil { + return fmt.Errorf("Error while exposing Prometheus service: %v ", err) + } + } + + return nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/subscription.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/subscription.go new file mode 100644 index 00000000000..8fc086a3b79 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/subscription.go @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + olmapiv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/client/kubernetes" +) + +// getSubscription returns subscription or nil if no subscription is found. +func getSubscription(cli *client.Client, namespace, packageName, catalogSource string) (*olmapiv1alpha1.Subscription, error) { + log := GetLogger("subscription") + log.Debug("Trying to fetch Subscription", "namespace", namespace, "Package name", packageName, "CatalogSource", namespace, packageName, catalogSource) + + subs := &olmapiv1alpha1.SubscriptionList{} + if err := kubernetes.ResourceC(cli).ListWithNamespace(namespace, subs); err != nil { + return nil, err + } + + for _, sub := range subs.Items { + if sub.Spec.Package == packageName && + sub.Spec.CatalogSource == catalogSource { + return &sub, nil + } + } + + return nil, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/task.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/task.go new file mode 100644 index 00000000000..4c43ccb49fd --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/task.go @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + "strings" +) + +// Task Kogito process task representation +type Task struct { + ID string `json:"id"` + Name string `json:"name"` +} + +// GetTasks retrieves tasks of specific process instance +func GetTasks(namespace, routeURI, processName, processInstanceID string) (foundTasks []Task, err error) { + tasksEndpointPath := getTasksEndpointPath(processName, processInstanceID) + requestInfo := NewGETHTTPRequestInfo(routeURI, tasksEndpointPath) + err = ExecuteHTTPRequestWithUnmarshalledResponse(namespace, requestInfo, &foundTasks) + return +} + +// GetTasksByUser retrieves tasks of specific process instance and user +func GetTasksByUser(namespace, routeURI, processName, processInstanceID, user string) (foundTasks []Task, err error) { + tasksEndpointPath := getTasksEndpointPath(processName, processInstanceID) + "?user=" + user + requestInfo := NewGETHTTPRequestInfo(routeURI, tasksEndpointPath) + err = ExecuteHTTPRequestWithUnmarshalledResponse(namespace, requestInfo, &foundTasks) + return +} + +// CompleteTask completes task +func CompleteTask(namespace, routeURI, processName, processInstanceID, taskName, taskID, bodyFormat, bodyContent string) (err error) { + taskIDEndpointPath := getTaskIDEndpointPath(processName, processInstanceID, taskName, taskID) + return completeTask(namespace, routeURI, taskIDEndpointPath, bodyFormat, bodyContent) +} + +// CompleteTaskByUser completes task by user +func CompleteTaskByUser(namespace, routeURI, processName, processInstanceID, taskName, taskID, user, bodyFormat, bodyContent string) (err error) { + taskIDEndpointPath := getTaskIDEndpointPath(processName, processInstanceID, taskName, taskID) + "?user=" + user + return completeTask(namespace, routeURI, taskIDEndpointPath, bodyFormat, bodyContent) +} + +func completeTask(namespace, routeURI, taskEndpointPath, bodyFormat, bodyContent string) (err error) { + requestInfo := NewPOSTHTTPRequestInfo(routeURI, taskEndpointPath, bodyFormat, bodyContent) + _, err = ExecuteHTTPRequest(namespace, requestInfo) + return +} + +func getTasksEndpointPath(processName, processInstanceID string) string { + return fmt.Sprintf("%s/%s/tasks", processName, processInstanceID) +} + +func getTaskIDEndpointPath(processName, processInstanceID, taskName, taskID string) string { + taskName = strings.ReplaceAll(taskName, " ", "_") + return fmt.Sprintf("%s/%s/%s/%s", processName, processInstanceID, taskName, taskID) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/framework/util.go b/packages/kogito-serverless-operator/bddframework/pkg/framework/util.go new file mode 100644 index 00000000000..c1dfe5785cb --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/framework/util.go @@ -0,0 +1,404 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + "io" + "io/ioutil" + "math/rand" + "net/http" + "os" + "path/filepath" + "strings" + "time" + + "github.com/google/uuid" + "k8s.io/apimachinery/pkg/types" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/env" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/version" +) + +const ( + fileFlags = os.O_CREATE | os.O_WRONLY | os.O_APPEND + permissionMode = 0666 + customKogitoImagePrefix = "custom-" + labelKeyVersion = "version" + kogitoBuilderImageEnvVar = "BUILDER_IMAGE" + kogitoRuntimeJVMEnvVar = "RUNTIME_IMAGE" + kogitoRuntimeNativeEnvVar = "RUNTIME_NATIVE_IMAGE" + // defaultBuilderImage Builder Image for Kogito + defaultBuilderImage = "kogito-s2i-builder" + // defaultRuntimeJVM Runtime Image for Kogito with JRE + defaultRuntimeJVM = "kogito-runtime-jvm" + //defaultRuntimeNative Runtime Image for Kogito for Native Quarkus Application + defaultRuntimeNative = "kogito-runtime-native" + // imageRegistryEnvVar ... + imageRegistryEnvVar = "IMAGE_REGISTRY" + // defaultImageRegistry the default services image repository + defaultImageRegistry = "quay.io/kiegroup" +) + +// GenerateNamespaceName generates a namespace name, taking configuration into account (local or not) +func GenerateNamespaceName(prefix string) string { + rand.Seed(time.Now().UnixNano()) + ns := fmt.Sprintf("%s-%s", prefix, GenerateShortUID(4)) + if config.IsLocalTests() { + username := env.GetEnvUsername() + ns = fmt.Sprintf("%s-local-%s", username, ns) + } else if len(config.GetCiName()) > 0 { + ns = fmt.Sprintf("%s-%s", config.GetCiName(), ns) + } + return ns +} + +// ReadFromURI reads string content from given URI (URL or Filesystem) +func ReadFromURI(uri string) (string, error) { + var data []byte + if strings.HasPrefix(uri, "http") { + resp, err := http.Get(uri) + if err != nil { + return "", err + } + defer resp.Body.Close() + if data, err = ioutil.ReadAll(resp.Body); err != nil { + return "", err + } + } else { + // It should be a Filesystem uri + absPath, err := filepath.Abs(uri) + if err != nil { + return "", err + } + data, err = ioutil.ReadFile(absPath) + if err != nil { + return "", err + } + } + return string(data), nil +} + +// WaitFor waits for a specification condition to be met or until one error condition is met +func WaitFor(namespace, display string, timeout time.Duration, condition func() (bool, error), errorConditions ...func() (bool, error)) error { + GetLogger(namespace).Info(fmt.Sprintf("Wait %s for %s", timeout.String(), display)) + + timeoutChan := time.After(timeout) + tick := time.NewTicker(1 * time.Second) + defer tick.Stop() + + for { + select { + case <-timeoutChan: + return fmt.Errorf("Timeout waiting for %s", display) + case <-tick.C: + running, err := condition() + if err != nil { + GetLogger(namespace).Warn(fmt.Sprintf("Problem in condition execution, waiting for %s => %v", display, err)) + } + + if running { + GetLogger(namespace).Info(fmt.Sprintf("'%s' is successful", display)) + return nil + } + + for _, errorCondition := range errorConditions { + if hasErrors, err := errorCondition(); hasErrors { + GetLogger(namespace).Error(err, "Problem in condition execution", "display", display) + return err + } + } + } + } +} + +// PrintDataMap prints a formatted dataMap using the given writer +func PrintDataMap(keys []string, dataMaps []map[string]string, writer io.StringWriter) error { + // Get size of strings to be written, to be able to format correctly + maxStringSizeMap := make(map[string]int) + for _, key := range keys { + maxSize := len(key) + for _, dataMap := range dataMaps { + if len(dataMap[key]) > maxSize { + maxSize = len(dataMap[key]) + } + } + maxStringSizeMap[key] = maxSize + } + + // Write headers + for _, header := range keys { + if _, err := writer.WriteString(header); err != nil { + return fmt.Errorf("Error in writing the header: %v", err) + } + if _, err := writer.WriteString(getWhitespaceStr(maxStringSizeMap[header] - len(header) + 1)); err != nil { + return fmt.Errorf("Error in writing headers: %v", err) + } + if _, err := writer.WriteString(" | "); err != nil { + return fmt.Errorf("Error in writing headers : %v", err) + } + } + if _, err := writer.WriteString("\n"); err != nil { + return fmt.Errorf("Error in writing headers '|': %v", err) + + } + + // Write events + for _, dataMap := range dataMaps { + for _, key := range keys { + if _, err := writer.WriteString(dataMap[key]); err != nil { + return fmt.Errorf("Error in writing events: %v", err) + } + if _, err := writer.WriteString(getWhitespaceStr(maxStringSizeMap[key] - len(dataMap[key]) + 1)); err != nil { + return fmt.Errorf("Error in writing events: %v", err) + } + if _, err := writer.WriteString(" | "); err != nil { + return fmt.Errorf("Error in writing events: %v", err) + } + } + if _, err := writer.WriteString("\n"); err != nil { + return fmt.Errorf("Error in writing events: %v", err) + } + } + return nil +} + +func getWhitespaceStr(size int) string { + whiteSpaceStr := "" + for i := 0; i < size; i++ { + whiteSpaceStr += " " + } + return whiteSpaceStr +} + +// CreateFolder creates a folder and all its parents if not exist +func CreateFolder(folder string) error { + return os.MkdirAll(folder, os.ModePerm) +} + +// CreateTemporaryFolder creates a folder in default directory for temporary files +func CreateTemporaryFolder(folderPrefix string) (string, error) { + return ioutil.TempDir("", folderPrefix) +} + +// DeleteFolder deletes a folder and all its subfolders +func DeleteFolder(folder string) error { + return os.RemoveAll(folder) +} + +// CreateFile Creates file in folder with supplied content +func CreateFile(folder, fileName, fileContent string) error { + f, err := os.Create(folder + "/" + fileName) + if err != nil { + return fmt.Errorf("Error creating file %s in folder %s: %v ", fileName, folder, err) + } + + if _, err = f.WriteString(fileContent); err != nil { + f.Close() + return fmt.Errorf("Error writing to file %s in folder %s: %v ", fileName, folder, err) + } + + if err := f.Close(); err != nil { + return fmt.Errorf("Error closing file %s in folder %s: %v ", fileName, folder, err) + } + return nil +} + +// CreateTemporaryFile Creates file in default directory for temporary files with supplied content +func CreateTemporaryFile(filePattern, fileContent string) (string, error) { + f, err := ioutil.TempFile("", filePattern) + if err != nil { + return "", fmt.Errorf("Error creating file with pattern %s in temporary folder: %v ", filePattern, err) + } + + if _, err = f.WriteString(fileContent); err != nil { + f.Close() + return "", fmt.Errorf("Error writing to file %s in temporary folder: %v ", f.Name(), err) + } + + if err := f.Close(); err != nil { + return "", fmt.Errorf("Error closing file %s in temporary folder: %v ", f.Name(), err) + } + + return f.Name(), nil +} + +// DeleteFile deletes a file +func DeleteFile(folder, fileName string) error { + return os.Remove(folder + "/" + fileName) +} + +// GetKogitoBuildS2IImage returns the S2I builder image tag +func GetKogitoBuildS2IImage() string { + if len(config.GetBuildBuilderImageStreamTag()) > 0 { + return config.GetBuildBuilderImageStreamTag() + } + + return ConstructDefaultImageFullTag(GetDefaultBuilderImage()) +} + +// GetKogitoBuildRuntimeImage returns the Runtime image tag +func GetKogitoBuildRuntimeImage(native bool) string { + var imageName string + if native { + if len(config.GetBuildRuntimeNativeImageStreamTag()) > 0 { + return config.GetBuildRuntimeNativeImageStreamTag() + } + imageName = GetDefaultRuntimeNativeImage() + } else { + if len(config.GetBuildRuntimeJVMImageStreamTag()) > 0 { + return config.GetBuildRuntimeJVMImageStreamTag() + } + imageName = GetDefaultRuntimeJVMImage() + } + + return ConstructDefaultImageFullTag(imageName) +} + +// ConstructDefaultImageFullTag construct the full image tag (adding default registry and tag) +func ConstructDefaultImageFullTag(imageName string) string { + image := &api.Image{ + Name: imageName, + } + AppendImageDefaultValues(image) + + return ConvertImageToImageTag(*image) +} + +// AppendImageDefaultValues appends the image default values if none existing +func AppendImageDefaultValues(image *api.Image) { + if len(image.Domain) == 0 { + image.Domain = GetDefaultImageRegistry() + } + + if len(image.Tag) == 0 { + image.Tag = GetKogitoImageVersion(version.OperatorVersion) + } +} + +// AddLineToFile adds the given line to the given file +func AddLineToFile(line, filename string) error { + file, err := os.OpenFile(filename, fileFlags, permissionMode) + if err != nil { + return err + } + defer file.Close() + if _, err = file.WriteString(fmt.Sprintf("%s\n", line)); err != nil { + return err + } + + return nil +} + +// GetDefaultRuntimeNativeImage ... +func GetDefaultRuntimeNativeImage() string { + runtimeImage := os.Getenv(kogitoRuntimeNativeEnvVar) + if len(runtimeImage) == 0 { + runtimeImage = defaultRuntimeNative + } + return runtimeImage +} + +// GetDefaultRuntimeJVMImage ... +func GetDefaultRuntimeJVMImage() string { + runtimeImage := os.Getenv(kogitoRuntimeJVMEnvVar) + if len(runtimeImage) == 0 { + runtimeImage = defaultRuntimeJVM + } + return runtimeImage +} + +// GetDefaultBuilderImage ... +func GetDefaultBuilderImage() string { + builderImage := os.Getenv(kogitoBuilderImageEnvVar) + if len(builderImage) == 0 { + builderImage = defaultBuilderImage + } + return builderImage +} + +// GenerateUID generates a Unique ID to be used across test cases +func GenerateUID() types.UID { + uid, err := uuid.NewRandom() + if err != nil { + panic(err) + } + return types.UID(uid.String()) +} + +// GenerateShortUID same as GenerateUID, but returns a fraction of the generated UID instead. +// If count > than UID total length, returns the entire sequence. +func GenerateShortUID(count int) string { + if count == 0 { + return "" + } + uid := GenerateUID() + if count > len(uid) { + count = len(uid) + } + return string(uid)[:count] +} + +// ConvertImageToImageTag converts an Image into a plain string (domain/namespace/name:tag). +func ConvertImageToImageTag(image api.Image) string { + imageTag := "" + if len(image.Domain) > 0 { + imageTag += image.Domain + "/" + } + imageTag += image.Name + if len(image.Tag) > 0 { + imageTag += ":" + image.Tag + } + return imageTag +} + +// GetDefaultImageRegistry ... +func GetDefaultImageRegistry() string { + registry := os.Getenv(imageRegistryEnvVar) + if len(registry) == 0 { + registry = defaultImageRegistry + } + return registry +} + +// GetKogitoImageVersion gets the Kogito Runtime latest micro version based on the given version +// E.g. Operator version is 0.9.0, the latest image version is 0.9.x-latest +// unit test friendly unexported function +// in this case we are considering only micro updates, that's 0.9.0 -> 0.9, thus for 1.0.0 => 1.0 +// in the future this should be managed with carefully if we desire a behavior like 1.0.0 => 1, that's minor upgrades +func GetKogitoImageVersion(v string) string { + if len(v) == 0 { + return "latest" + } + + versionPrefix := strings.Split(v, ".") + length := len(versionPrefix) + if length > 0 { + lastIndex := 2 // micro updates + if length <= 2 { // guard against unusual cases + lastIndex = length + } + return strings.Join(versionPrefix[:lastIndex], ".") + } + return "latest" +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/gherkin/feature.go b/packages/kogito-serverless-operator/bddframework/pkg/gherkin/feature.go new file mode 100644 index 00000000000..70fcbfdf2cd --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/gherkin/feature.go @@ -0,0 +1,192 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 from here has been copied and a bit rearranged from github.com/cucumber/godog/suite.go +// as we needed the functionality to access features from the suite but it not possible +// Stay here as long as https://github.com/cucumber/godog/issues/222 is not solved + +package gherkin + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "strings" + + "github.com/cucumber/gherkin-go/v19" + "github.com/cucumber/messages-go/v16" +) + +// Feature represents a Gherkin feature +type Feature struct { + Document *messages.GherkinDocument + Pickles []*messages.Pickle +} + +// ParseFeatures parse features from given paths +func ParseFeatures(filter string, paths []string) ([]*Feature, error) { + if len(paths) == 0 { + inf, err := os.Stat("features") + if err == nil && inf.IsDir() { + paths = []string{"features"} + } + } + + features := make(map[string]*Feature) + for _, path := range paths { + fts, err := parsePath(path) + switch { + case os.IsNotExist(err): + return nil, fmt.Errorf(`feature path "%s" is not available`, path) + case os.IsPermission(err): + return nil, fmt.Errorf(`feature path "%s" is not accessible`, path) + case err != nil: + return nil, err + } + + for _, ft := range fts { + if _, duplicate := features[ft.Document.Feature.Name]; duplicate { + continue + } + features[ft.Document.Feature.Name] = ft + } + } + return filterFeatures(filter, features), nil +} + +func parsePath(path string) ([]*Feature, error) { + var features []*Feature + + fi, err := os.Stat(path) + if err != nil { + return features, err + } + + if fi.IsDir() { + return parseFeatureDir(path) + } + + newIDFunc := (&messages.Incrementing{}).NewId + ft, err := parseFeatureFile(path, newIDFunc) + if err != nil { + return features, err + } + + return append(features, ft), nil +} + +func parseFeatureFile(path string, newIDFunc func() string) (*Feature, error) { + reader, err := os.Open(path) + if err != nil { + return nil, err + } + defer reader.Close() + + var buf bytes.Buffer + ft, err := gherkin.ParseGherkinDocument(io.TeeReader(reader, &buf), newIDFunc) + if err != nil { + return nil, fmt.Errorf("%s - %v", path, err) + } + + pickles := gherkin.Pickles(*ft, path, newIDFunc) + + return &Feature{ + Document: ft, + Pickles: pickles, + }, nil +} + +func parseFeatureDir(dir string) ([]*Feature, error) { + var features []*Feature + return features, filepath.Walk(dir, func(p string, f os.FileInfo, err error) error { + if err != nil { + return err + } + + if f.IsDir() { + return nil + } + + if !strings.HasSuffix(p, ".feature") { + return nil + } + + feat, err := parseFeatureFile(p, (&messages.Incrementing{}).NewId) + if err != nil { + return err + } + features = append(features, feat) + return nil + }) +} + +func filterFeatures(tags string, collected map[string]*Feature) (features []*Feature) { + for _, ft := range collected { + applyTagFilter(tags, ft) + features = append(features, ft) + } + + return features +} + +func applyTagFilter(tags string, ft *Feature) { + if len(tags) == 0 { + return + } + var pickles []*messages.Pickle + for _, pickle := range ft.Pickles { + if matchesTags(tags, pickle.Tags) { + pickles = append(pickles, pickle) + } + } + + ft.Pickles = pickles +} + +// based on http://behat.readthedocs.org/en/v2.5/guides/6.cli.html#gherkin-filters +func matchesTags(filter string, tags []*messages.PickleTag) (ok bool) { + ok = true + for _, andTags := range strings.Split(filter, "&&") { + var okComma bool + for _, tag := range strings.Split(andTags, ",") { + tag = strings.Replace(strings.TrimSpace(tag), "@", "", -1) + if tag[0] == '~' { + tag = tag[1:] + okComma = !hasTag(tags, tag) || okComma + } else { + okComma = hasTag(tags, tag) || okComma + } + } + ok = ok && okComma + } + return +} + +func hasTag(tags []*messages.PickleTag, tag string) bool { + for _, t := range tags { + tName := strings.Replace(t.Name, "@", "", -1) + + if tName == tag { + return true + } + } + return false +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/gherkin/matcher.go b/packages/kogito-serverless-operator/bddframework/pkg/gherkin/matcher.go new file mode 100644 index 00000000000..5916723d833 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/gherkin/matcher.go @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package gherkin + +import ( + "github.com/cucumber/messages-go/v16" +) + +// MatchingFeatureWithTags checks whether any scenario in the feature has the given tags +func MatchingFeatureWithTags(filterTags string, features []*Feature) bool { + for _, ft := range features { + if MatchesScenariosWithTags(filterTags, ft.Pickles) { + return true + } + } + return false +} + +// MatchesScenariosWithTags checks whether the given scenarioin has the given tags +func MatchesScenariosWithTags(filterTags string, scenarios []*messages.Pickle) bool { + for _, scenario := range scenarios { + if matchesTags(filterTags, scenario.Tags) { + return true + } + } + return false +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/installers/amqstreams_installer.go b/packages/kogito-serverless-operator/bddframework/pkg/installers/amqstreams_installer.go new file mode 100644 index 00000000000..e844f58839f --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/installers/amqstreams_installer.go @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package installers + +import ( + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2" +) + +var ( + // amqStreamsOlmClusterWideInstaller installs AmqStreams cluster wide using OLM + amqStreamsOlmClusterWideInstaller = OlmClusterWideServiceInstaller{ + SubscriptionName: amqStreamsOperatorSubscriptionName, + Channel: amqStreamsOperatorSubscriptionChannel, + StartingCSV: amqStreamsOperatorSubscriptionStartingCsv, + Catalog: framework.GetProductCatalog, + InstallationTimeoutInMinutes: amqStreamsOperatorTimeoutInMin, + GetAllClusterWideOlmCrsInNamespace: getAmqStreamsCrsInNamespace, + } + + amqStreamsOperatorSubscriptionName = "amq-streams" + amqStreamsOperatorSubscriptionChannel = "amq-streams-2.1.x" + amqStreamsOperatorSubscriptionStartingCsv = "amqstreams.v2.1.0-4" + amqStreamsOperatorTimeoutInMin = 10 +) + +// GetAmqStreamsInstaller returns AmqStreams installer +func GetAmqStreamsInstaller() ServiceInstaller { + return &amqStreamsOlmClusterWideInstaller +} + +func getAmqStreamsCrsInNamespace(namespace string) ([]client.Object, error) { + crs := []client.Object{} + + amqStreams := &v1beta2.KafkaList{} + if err := framework.GetObjectsInNamespace(namespace, amqStreams); err != nil { + return nil, err + } + for i := range amqStreams.Items { + crs = append(crs, &amqStreams.Items[i]) + } + + amqStreamsTopics := &v1beta2.KafkaTopicList{} + if err := framework.GetObjectsInNamespace(namespace, amqStreamsTopics); err != nil { + return nil, err + } + for i := range amqStreamsTopics.Items { + crs = append(crs, &amqStreamsTopics.Items[i]) + } + + return crs, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/installers/grafana_installer.go b/packages/kogito-serverless-operator/bddframework/pkg/installers/grafana_installer.go new file mode 100644 index 00000000000..f323bf4da66 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/installers/grafana_installer.go @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package installers + +import ( + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + grafanav1 "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1" +) + +var ( + // grafanaOlmNamespacedInstaller installs Grafana in the namespace using OLM + grafanaOlmNamespacedInstaller = OlmNamespacedServiceInstaller{ + SubscriptionName: grafanaOperatorSubscriptionName, + Channel: grafanaOperatorSubscriptionChannel, + Catalog: framework.GetCommunityCatalog, + InstallationTimeoutInMinutes: 3, + GetAllNamespacedOlmCrsInNamespace: getGrafanaCrsInNamespace, + } + + grafanaOperatorSubscriptionName = "grafana-operator" + grafanaOperatorSubscriptionChannel = "v4" +) + +// GetGrafanaInstaller returns Grafana installer +func GetGrafanaInstaller() ServiceInstaller { + return &grafanaOlmNamespacedInstaller +} + +func getGrafanaCrsInNamespace(namespace string) ([]client.Object, error) { + var crs []client.Object + + grafanas := &grafanav1.GrafanaList{} + if err := framework.GetObjectsInNamespace(namespace, grafanas); err != nil { + return nil, err + } + for i := range grafanas.Items { + crs = append(crs, &grafanas.Items[i]) + } + + return crs, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/installers/hyperfoil_installer.go b/packages/kogito-serverless-operator/bddframework/pkg/installers/hyperfoil_installer.go new file mode 100644 index 00000000000..d4330887810 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/installers/hyperfoil_installer.go @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package installers + +import ( + "sigs.k8s.io/controller-runtime/pkg/client" + + hyperfoil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +var ( + // hyperfoilOlmNamespacedInstaller installs Hyperfoil into the namespace using OLM + hyperfoilOlmNamespacedInstaller = OlmNamespacedServiceInstaller{ + SubscriptionName: hyperfoilOperatorSubscriptionName, + Channel: hyperfoilOperatorSubscriptionChannel, + Catalog: framework.GetCommunityCatalog, + InstallationTimeoutInMinutes: hyperfoilOperatorTimeoutInMin, + GetAllNamespacedOlmCrsInNamespace: getHyperfoilCrsInNamespace, + } + + hyperfoilOperatorSubscriptionName = "hyperfoil-bundle" + hyperfoilOperatorSubscriptionChannel = "alpha" + hyperfoilOperatorTimeoutInMin = 10 +) + +// GetHyperfoilInstaller returns Hyperfoil installer +func GetHyperfoilInstaller() ServiceInstaller { + return &hyperfoilOlmNamespacedInstaller +} + +func getHyperfoilCrsInNamespace(namespace string) ([]client.Object, error) { + var crs []client.Object + + hyperfoils := &hyperfoil.HyperfoilList{} + if err := framework.GetObjectsInNamespace(namespace, hyperfoils); err != nil { + return nil, err + } + for i := range hyperfoils.Items { + crs = append(crs, &hyperfoils.Items[i]) + } + + return crs, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/installers/hyperfoil_node_scraper_installer.go b/packages/kogito-serverless-operator/bddframework/pkg/installers/hyperfoil_node_scraper_installer.go new file mode 100644 index 00000000000..503a72ab4ef --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/installers/hyperfoil_node_scraper_installer.go @@ -0,0 +1,253 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package installers + +import ( + "fmt" + + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + rbac "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +const ( + nodeScraperStart = `#!/bin/bash + CWD=$(dirname $0) + curl -s node-scraper:8080/start -H 'content-type: application/json' --data-binary @$CWD/.node-scraper-config.json > $RUN_DIR/node-scraper.job` + nodeScraperStop = `#!/bin/bash + curl -s node-scraper:8080/stop/$(cat $RUN_DIR/node-scraper.job) > $RUN_DIR/cpu.json + # jq cannot write into file used as a source, need to move original all.json to a temporary location + mv $RUN_DIR/all.json $RUN_DIR/all-temp.json + jq -c -s '{ hyperfoil: .[0], cpu: { "$schema": "urn:node-scraper", data: .[1] }}' $RUN_DIR/all-temp.json $RUN_DIR/cpu.json > $RUN_DIR/all.json` + + // NodeScraperStartConfigMapName ConfigMap name for start script of Node scraper + NodeScraperStartConfigMapName = "node-scraper-start" + // NodeScraperStopConfigMapName ConfigMap name for stop script of Node scraper + NodeScraperStopConfigMapName = "node-scraper-stop" +) + +var ( + // hyperfoilNodeScraperYamlNamespacedInstaller installs Hyperfoil node scraper namespaced using YAMLs + hyperfoilNodeScraperYamlNamespacedInstaller = YamlNamespacedServiceInstaller{ + InstallNamespacedYaml: installHyperfoilNodeScraper, + WaitForNamespacedServiceRunning: waitForHyperfoilNodeScraperRunning, + GetAllNamespaceYamlCrs: getHyperfoilNodeScraperCrsInNamespace, + UninstallNamespaceYaml: uninstallHyperfoilNodeScraper, + NamespacedYamlServiceName: hyperfoilNodeScraperServiceName, + } + hyperfoilNodeScraperServiceName = "Hyperfoil Node scraper" + hyperfoilNodeScraperDeploymentName = "node-scraper" + hyperfoilNodeScraperImage = "quay.io/rvansa/node-scraper" +) + +// GetHyperfoilNodeScraperInstaller returns Hyperfoil Node scraper installer +func GetHyperfoilNodeScraperInstaller() ServiceInstaller { + return &hyperfoilNodeScraperYamlNamespacedInstaller +} + +func installHyperfoilNodeScraper(namespace string) error { + framework.GetLogger(namespace).Info("Deploy Hyperfoil Node scraper") + + if err := framework.CreateServiceAccount(namespace, getHyperfoilNodeScraperUniqueName(namespace)); err != nil { + return err + } + if err := createHyperfoilNodeScraperClusterRole(getHyperfoilNodeScraperUniqueName(namespace)); err != nil { + return err + } + if err := createHyperfoilNodeScraperClusterRoleBinding(getHyperfoilNodeScraperUniqueName(namespace), namespace); err != nil { + return err + } + + scraperConfig, err := getNodeScraperConfigContent(namespace) + if err != nil { + return err + } + + err = framework.CreateConfigMap(namespace, NodeScraperStartConfigMapName, map[string]string{".node-scraper-config.json": scraperConfig, "99-node-scraper-start.sh": nodeScraperStart}, nil) + if err != nil { + return err + } + err = framework.CreateConfigMap(namespace, NodeScraperStopConfigMapName, map[string]string{"00-node-scraper-stop.sh": nodeScraperStop}, nil) + if err != nil { + return err + } + + return deployNodeScraper(namespace) +} + +func waitForHyperfoilNodeScraperRunning(namespace string) error { + return framework.WaitForPodsWithLabel(namespace, "app", hyperfoilNodeScraperDeploymentName, 1, 3) +} + +func uninstallHyperfoilNodeScraper(namespace string) error { + var originalError error + + // Delete cluster wide resources, the rest is deleted together with namespace + crb, err := framework.GetClusterRoleBinding(getHyperfoilNodeScraperUniqueName(namespace)) + if err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Cannot retrieve ClusterRoleBinding %s", getHyperfoilNodeScraperUniqueName(namespace))) + if originalError == nil { + originalError = err + } + } else { + if err = framework.DeleteObject(crb); err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Cannot delete ClusterRoleBinding %s", getHyperfoilNodeScraperUniqueName(namespace))) + if originalError == nil { + originalError = err + } + } + } + + cr, err := framework.GetClusterRole(getHyperfoilNodeScraperUniqueName(namespace)) + if err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Cannot retrieve ClusterRole %s", getHyperfoilNodeScraperUniqueName(namespace))) + if originalError == nil { + originalError = err + } + } else { + if err = framework.DeleteObject(cr); err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Cannot delete ClusterRole %s", getHyperfoilNodeScraperUniqueName(namespace))) + if originalError == nil { + originalError = err + } + } + } + + return originalError +} + +func getHyperfoilNodeScraperCrsInNamespace(namespace string) ([]client.Object, error) { + return []client.Object{}, nil +} + +// Helper functions + +func getHyperfoilNodeScraperUniqueName(namespace string) string { + return "node-scraper-" + namespace +} + +func createHyperfoilNodeScraperClusterRole(name string) error { + clusterRole := &rbac.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Rules: []rbac.PolicyRule{ + { + Verbs: []string{"get"}, + NonResourceURLs: []string{"/metrics"}, + }, + }, + } + + return framework.CreateObject(clusterRole) +} + +func createHyperfoilNodeScraperClusterRoleBinding(name, namespace string) error { + clusterRoleBinding := &rbac.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + RoleRef: rbac.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "ClusterRole", + Name: getHyperfoilNodeScraperUniqueName(namespace), + }, + Subjects: []rbac.Subject{ + { + Kind: "ServiceAccount", + Name: getHyperfoilNodeScraperUniqueName(namespace), + Namespace: namespace, + }, + }, + } + + return framework.CreateObject(clusterRoleBinding) +} + +func getNodeScraperConfigContent(namespace string) (scraperConfig string, err error) { + nodes, err := framework.CreateCommand("oc", "get", "node", "-l", "node-role.kubernetes.io/worker", "-o", "json").WithLoggerContext(namespace).Execute() + if err != nil { + return + } + tempFilePath, err := framework.CreateTemporaryFile("cluster-worker-nodes*.yaml", nodes) + if err != nil { + framework.GetMainLogger().Error(err, "Error while storing worker nodes to temporary file") + return + } + + return framework.CreateCommand("jq", "-c", "{ nodes: [ .items[] | { node : .metadata.name | split(\".\") | .[0], url: (\"https://\" + .status.addresses[0].address + \":9100/metrics\") }] , scrapeInterval: 5000}", tempFilePath).WithLoggerContext(namespace).Execute() +} + +func deployNodeScraper(namespace string) error { + deployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: hyperfoilNodeScraperDeploymentName, + Namespace: namespace, + }, + Spec: appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": hyperfoilNodeScraperDeploymentName}}, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{"app": hyperfoilNodeScraperDeploymentName}, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: hyperfoilNodeScraperDeploymentName, + Image: hyperfoilNodeScraperImage, + }, + }, + ServiceAccountName: getHyperfoilNodeScraperUniqueName(namespace), + }, + }, + }, + } + + if err := framework.CreateObject(deployment); err != nil { + return err + } + + service := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: hyperfoilNodeScraperDeploymentName, + Namespace: namespace, + }, + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + { + Protocol: "TCP", + Port: 8080, + TargetPort: intstr.FromInt(8080), + }, + }, + Selector: deployment.Spec.Selector.MatchLabels, + }, + } + + if err := framework.CreateObject(service); err != nil { + return err + } + return nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/installers/infinispan_installer.go b/packages/kogito-serverless-operator/bddframework/pkg/installers/infinispan_installer.go new file mode 100644 index 00000000000..7de2ecd40f2 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/installers/infinispan_installer.go @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package installers + +import ( + "errors" + "fmt" + + "sigs.k8s.io/controller-runtime/pkg/client" + + coreapps "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + rbac "k8s.io/api/rbac/v1" + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + ispn "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1" +) + +var ( + // infinispanOlmClusterWideInstaller installs Infinispan cluster wide using OLM + infinispanOlmClusterWideInstaller = OlmClusterWideServiceInstaller{ + SubscriptionName: infinispanOperatorSubscriptionName, + Channel: infinispanOperatorSubscriptionChannel, + Catalog: framework.GetCommunityCatalog, + InstallationTimeoutInMinutes: 10, + GetAllClusterWideOlmCrsInNamespace: getInfinispanCrsInNamespace, + } + // infinispanYamlNamespacedInstaller installs Infinispan namespaced using YAMLs + infinispanYamlNamespacedInstaller = YamlNamespacedServiceInstaller{ + InstallNamespacedYaml: installInfinispanUsingYaml, + WaitForNamespacedServiceRunning: waitForInfinispanUsingYamlRunning, + GetAllNamespaceYamlCrs: getInfinispanCrsInNamespace, + UninstallNamespaceYaml: uninstallInfinispanUsingYaml, + NamespacedYamlServiceName: infinispanOperatorServiceName, + } + + infinispanOperatorSubscriptionName = "infinispan" + infinispanOperatorSubscriptionChannel = "2.3.x" + infinispanOperatorGitHubBranch = "2.0.x" + infinispanOperatorDeployFilesURI = fmt.Sprintf("https://raw.githubusercontent.com/infinispan/infinispan-operator/%s/deploy/", infinispanOperatorGitHubBranch) + infinispanOperatorServiceName = "Infinispan" +) + +// GetInfinispanInstaller returns Infinispan installer +func GetInfinispanInstaller() (ServiceInstaller, error) { + if config.IsInfinispanInstalledByYaml() { + return &infinispanYamlNamespacedInstaller, nil + } + + if config.IsInfinispanInstalledByOlm() { + return &infinispanOlmClusterWideInstaller, nil + } + + return nil, errors.New("No Infinispan operator installer available for provided configuration") +} + +func installInfinispanUsingYaml(namespace string) error { + framework.GetLogger(namespace).Info("Deploy Infinispan from yaml files", "file uri", infinispanOperatorDeployFilesURI) + infinispanClusterResourceName := getInfinispanClusterResourceName(namespace) + + if !framework.IsInfinispanAvailable(namespace) { + if err := framework.LoadResource(namespace, infinispanOperatorDeployFilesURI+"crds/infinispan.org_caches_crd.yaml", &apiextensionsv1beta1.CustomResourceDefinition{}, nil); err != nil { + return err + } + if err := framework.LoadResource(namespace, infinispanOperatorDeployFilesURI+"crds/infinispan.org_infinispans_crd.yaml", &apiextensionsv1beta1.CustomResourceDefinition{}, nil); err != nil { + return err + } + } + + err := framework.LoadResource(namespace, infinispanOperatorDeployFilesURI+"clusterrole.yaml", &rbac.ClusterRole{}, func(object interface{}) { + // Prefix name to be unique to allow concurrent installations + object.(*rbac.ClusterRole).Name = infinispanClusterResourceName + }) + if err != nil { + return err + } + + err = framework.LoadResource(namespace, infinispanOperatorDeployFilesURI+"clusterrole_binding.yaml", &rbac.ClusterRoleBinding{}, func(object interface{}) { + // Prefix name to be unique to allow concurrent installations + object.(*rbac.ClusterRoleBinding).Name = infinispanClusterResourceName + // Set proper namespace for binding to service account + object.(*rbac.ClusterRoleBinding).Subjects[0].Namespace = namespace + }) + if err != nil { + return err + } + + if err := framework.LoadResource(namespace, infinispanOperatorDeployFilesURI+"service_account.yaml", &corev1.ServiceAccount{}, nil); err != nil { + return err + } + if err := framework.LoadResource(namespace, infinispanOperatorDeployFilesURI+"role.yaml", &rbac.Role{}, nil); err != nil { + return err + } + if err := framework.LoadResource(namespace, infinispanOperatorDeployFilesURI+"role_binding.yaml", &rbac.RoleBinding{}, nil); err != nil { + return err + } + if err := framework.LoadResource(namespace, infinispanOperatorDeployFilesURI+"operator.yaml", &coreapps.Deployment{}, nil); err != nil { + return err + } + + return nil +} + +func waitForInfinispanUsingYamlRunning(namespace string) error { + return framework.WaitForPodsWithLabel(namespace, "name", "infinispan-operator", 1, 3) +} + +func uninstallInfinispanUsingYaml(namespace string) error { + framework.GetLogger(namespace).Info("Uninstalling Infinispan") + infinispanClusterResourceName := getInfinispanClusterResourceName(namespace) + + var originalError error + + output, err := framework.CreateCommand("oc", "delete", "-f", infinispanOperatorDeployFilesURI+"operator.yaml", "-n", namespace).WithLoggerContext(namespace).Execute() + if err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Deleting Infinispan operator failed, output: %s", output)) + if originalError == nil { + originalError = err + } + } + + output, err = framework.CreateCommand("oc", "delete", "-f", infinispanOperatorDeployFilesURI+"role_binding.yaml", "-n", namespace).WithLoggerContext(namespace).Execute() + if err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Deleting Infinispan role binding failed, output: %s", output)) + if originalError == nil { + originalError = err + } + } + + output, err = framework.CreateCommand("oc", "delete", "-f", infinispanOperatorDeployFilesURI+"role.yaml", "-n", namespace).WithLoggerContext(namespace).Execute() + if err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Deleting Infinispan role failed, output: %s", output)) + if originalError == nil { + originalError = err + } + } + + output, err = framework.CreateCommand("oc", "delete", "-f", infinispanOperatorDeployFilesURI+"service_account.yaml", "-n", namespace).WithLoggerContext(namespace).Execute() + if err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Deleting Infinispan service account failed, output: %s", output)) + if originalError == nil { + originalError = err + } + } + + crb, err := framework.GetClusterRoleBinding(infinispanClusterResourceName) + if err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Cannot retrieve ClusterRoleBinding %s", infinispanClusterResourceName)) + if originalError == nil { + originalError = err + } + } else { + if err = framework.DeleteObject(crb); err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Cannot delete ClusterRoleBinding %s", infinispanClusterResourceName)) + if originalError == nil { + originalError = err + } + } + } + + cr, err := framework.GetClusterRole(infinispanClusterResourceName) + if err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Cannot retrieve ClusterRole %s", infinispanClusterResourceName)) + if originalError == nil { + originalError = err + } + } else { + if err = framework.DeleteObject(cr); err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Cannot delete ClusterRole %s", infinispanClusterResourceName)) + if originalError == nil { + originalError = err + } + } + } + + return originalError +} + +func getInfinispanClusterResourceName(namespace string) string { + return "infinispan-" + namespace +} + +func getInfinispanCrsInNamespace(namespace string) ([]client.Object, error) { + var crs []client.Object + + infinispans := &ispn.InfinispanList{} + if err := framework.GetObjectsInNamespace(namespace, infinispans); err != nil { + return nil, err + } + for i := range infinispans.Items { + crs = append(crs, &infinispans.Items[i]) + } + + return crs, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/installers/kafka_installer.go b/packages/kogito-serverless-operator/bddframework/pkg/installers/kafka_installer.go new file mode 100644 index 00000000000..88acf8884a4 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/installers/kafka_installer.go @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package installers + +import ( + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2" +) + +var ( + // kafkaOlmClusterWideInstaller installs Kafka cluster wide using OLM + kafkaOlmClusterWideInstaller = OlmClusterWideServiceInstaller{ + SubscriptionName: kafkaOperatorSubscriptionName, + Channel: kafkaOperatorSubscriptionChannel, + Catalog: framework.GetCommunityCatalog, + InstallationTimeoutInMinutes: kafkaOperatorTimeoutInMin, + GetAllClusterWideOlmCrsInNamespace: getKafkaCrsInNamespace, + } + + kafkaOperatorSubscriptionName = "strimzi-kafka-operator" + kafkaOperatorSubscriptionChannel = "stable" + kafkaOperatorTimeoutInMin = 10 +) + +// GetKafkaInstaller returns Kafka installer +func GetKafkaInstaller() ServiceInstaller { + return &kafkaOlmClusterWideInstaller +} + +func getKafkaCrsInNamespace(namespace string) ([]client.Object, error) { + var crs []client.Object + + kafkas := &v1beta2.KafkaList{} + if err := framework.GetObjectsInNamespace(namespace, kafkas); err != nil { + return nil, err + } + for i := range kafkas.Items { + crs = append(crs, &kafkas.Items[i]) + } + + kafkaTopics := &v1beta2.KafkaTopicList{} + if err := framework.GetObjectsInNamespace(namespace, kafkaTopics); err != nil { + return nil, err + } + for i := range kafkaTopics.Items { + crs = append(crs, &kafkaTopics.Items[i]) + } + + return crs, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/installers/keycloak_installer.go b/packages/kogito-serverless-operator/bddframework/pkg/installers/keycloak_installer.go new file mode 100644 index 00000000000..ce9665151cc --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/installers/keycloak_installer.go @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package installers + +import ( + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + keycloak "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1" +) + +var ( + // keycloakOlmNamespacedInstaller installs Keycloak in the namespace using OLM + keycloakOlmNamespacedInstaller = OlmNamespacedServiceInstaller{ + SubscriptionName: "keycloak-operator", + Channel: "fast", + Catalog: framework.GetCommunityCatalog, + InstallationTimeoutInMinutes: 10, + GetAllNamespacedOlmCrsInNamespace: getKeycloakCrsInNamespace, + } +) + +// GetKeycloakInstaller returns Keycloak installer +func GetKeycloakInstaller() ServiceInstaller { + return &keycloakOlmNamespacedInstaller +} + +func getKeycloakCrsInNamespace(namespace string) ([]client.Object, error) { + var crs []client.Object + + keycloaks := &keycloak.KeycloakList{} + if err := framework.GetObjectsInNamespace(namespace, keycloaks); err != nil { + return nil, err + } + for i := range keycloaks.Items { + crs = append(crs, &keycloaks.Items[i]) + } + + keycloakClients := &keycloak.KeycloakClientList{} + if err := framework.GetObjectsInNamespace(namespace, keycloakClients); err != nil { + return nil, err + } + for i := range keycloakClients.Items { + crs = append(crs, &keycloakClients.Items[i]) + } + + keycloakUsers := &keycloak.KeycloakUserList{} + if err := framework.GetObjectsInNamespace(namespace, keycloakUsers); err != nil { + return nil, err + } + for i := range keycloakUsers.Items { + crs = append(crs, &keycloakUsers.Items[i]) + } + + keycloakRealms := &keycloak.KeycloakRealmList{} + if err := framework.GetObjectsInNamespace(namespace, keycloakRealms); err != nil { + return nil, err + } + for i := range keycloakRealms.Items { + crs = append(crs, &keycloakRealms.Items[i]) + } + + return crs, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/installers/knative-eventing-kogito-installer.go b/packages/kogito-serverless-operator/bddframework/pkg/installers/knative-eventing-kogito-installer.go new file mode 100644 index 00000000000..76409e2aa76 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/installers/knative-eventing-kogito-installer.go @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package installers + +import ( + "fmt" + + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +var ( + // knativeEventingKogitoYamlClusterInstaller installs Knative eventing KogitoSource cluster wide using YAMLs + knativeEventingKogitoYamlClusterInstaller = YamlClusterWideServiceInstaller{ + InstallClusterYaml: installKnativeEventingKogitoUsingYaml, + InstallationNamespace: knativeEventingKogitoNamespace, + WaitForClusterYamlServiceRunning: waitForKnativeEventingKogitoUsingYamlRunning, + GetAllClusterYamlCrsInNamespace: getKnativeEventingKogitoCrsInNamespace, + UninstallClusterYaml: uninstallKnativeEventingKogitoUsingYaml, + ClusterYamlServiceName: knativeEventingKogitoServiceName, + } + + knativeEventingKogitoNamespace = "knative-kogito" + knativeEventingKogitoNumberOfPods = 2 + knativeEventingKogitoServiceName = "Knative Eventing Kogito Source" +) + +// GetKnativeEventingKogitoInstaller returns KnativeEventing KogitoSource installer +func GetKnativeEventingKogitoInstaller() ServiceInstaller { + return &knativeEventingKogitoYamlClusterInstaller +} + +func installKnativeEventingKogitoUsingYaml() error { + framework.GetMainLogger().Info("Installing Knative eventing KogitoSource") + + output, err := framework.CreateCommand("oc", "apply", "-f", fmt.Sprintf("https://github.com/knative-sandbox/eventing-kogito/releases/download/%s/kogito.yaml", knativeEventingVersion)).Execute() + if err != nil { + framework.GetMainLogger().Error(err, fmt.Sprintf("Applying Knative eventing KogitoSource, output: %s", output)) + } + + return err +} + +func waitForKnativeEventingKogitoUsingYamlRunning() error { + return framework.WaitForPodsInNamespace(knativeEventingKogitoNamespace, knativeEventingKogitoNumberOfPods, 3) +} + +func uninstallKnativeEventingKogitoUsingYaml() error { + framework.GetMainLogger().Info("Uninstalling Knative eventing KogitoSource") + + output, err := framework.CreateCommand("oc", "delete", "-f", fmt.Sprintf("https://github.com/knative-sandbox/eventing-kogito/releases/download/%s/kogito.yaml", knativeEventingVersion)).Execute() + if err != nil { + framework.GetMainLogger().Error(err, fmt.Sprintf("Deleting Knative eventing KogitoSource failed, output: %s", output)) + } + + return err +} + +func getKnativeEventingKogitoCrsInNamespace(namespace string) ([]client.Object, error) { + crs := []client.Object{} + + // Quick workaround, needs to be refactored once BDD tests are moved to separate module + return crs, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/installers/knative_installer.go b/packages/kogito-serverless-operator/bddframework/pkg/installers/knative_installer.go new file mode 100644 index 00000000000..69fbbc5198b --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/installers/knative_installer.go @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package installers + +import ( + "fmt" + + "sigs.k8s.io/controller-runtime/pkg/client" + + eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +var ( + // knativeEventingYamlClusterInstaller installs Knative eventing cluster wide using YAMLs + knativeEventingYamlClusterInstaller = YamlClusterWideServiceInstaller{ + InstallClusterYaml: installKnativeEventingUsingYaml, + InstallationNamespace: knativeEventingNamespace, + WaitForClusterYamlServiceRunning: waitForKnativeEventingUsingYamlRunning, + GetAllClusterYamlCrsInNamespace: getKnativeEventingCrsInNamespace, + UninstallClusterYaml: uninstallKnativeEventingUsingYaml, + ClusterYamlServiceName: knativeEventingServiceName, + } + + knativeEventingNamespace = "knative-eventing" + knativeEventingVersion = "v0.26.0" + knativeEventingNumberOfPods = 7 + knativeEventingServiceName = "Knative eventing" +) + +// GetKnativeEventingInstaller returns KnativeEventing installer +func GetKnativeEventingInstaller() ServiceInstaller { + return &knativeEventingYamlClusterInstaller +} + +func installKnativeEventingUsingYaml() error { + framework.GetMainLogger().Info("Installing Knative eventing") + + output, err := framework.CreateCommand("oc", "apply", "-f", fmt.Sprintf("https://github.com/knative/eventing/releases/download/%s/eventing-crds.yaml", knativeEventingVersion)).Execute() + if err != nil { + framework.GetMainLogger().Error(err, fmt.Sprintf("Applying eventing CRDs failed, output: %s", output)) + return fmt.Errorf("Error applying eventing CRDs") + } + + output, err = framework.CreateCommand("oc", "apply", "-f", fmt.Sprintf("https://github.com/knative/eventing/releases/download/%s/eventing-core.yaml", knativeEventingVersion)).Execute() + if err != nil { + framework.GetMainLogger().Error(err, fmt.Sprintf("Applying eventing core components failed, output: %s", output)) + return fmt.Errorf("Error applying eventing core components") + } + + output, err = framework.CreateCommand("oc", "apply", "-f", fmt.Sprintf("https://github.com/knative/eventing/releases/download/%s/in-memory-channel.yaml", knativeEventingVersion)).Execute() + if err != nil { + framework.GetMainLogger().Error(err, fmt.Sprintf("Applying eventing in-memory channel failed, output: %s", output)) + return fmt.Errorf("Error applying eventing in-memory channel") + } + + output, err = framework.CreateCommand("oc", "apply", "-f", fmt.Sprintf("https://github.com/knative/eventing/releases/download/%s/mt-channel-broker.yaml", knativeEventingVersion)).Execute() + if err != nil { + framework.GetMainLogger().Error(err, fmt.Sprintf("Applying eventing mt-channel broker failed, output: %s", output)) + return fmt.Errorf("Error applying eventing mt-channel broker") + } + + return nil +} + +func waitForKnativeEventingUsingYamlRunning() error { + return framework.WaitForPodsInNamespace(knativeEventingNamespace, knativeEventingNumberOfPods, 3) +} + +func uninstallKnativeEventingUsingYaml() error { + framework.GetMainLogger().Info("Uninstalling Knative eventing") + + var originalError error + + output, err := framework.CreateCommand("oc", "delete", "-f", fmt.Sprintf("https://github.com/knative/eventing/releases/download/%s/mt-channel-broker.yaml", knativeEventingVersion)).Execute() + if err != nil { + framework.GetMainLogger().Error(err, fmt.Sprintf("Deleting eventing mt-channel broker failed, output: %s", output)) + originalError = err + } + + output, err = framework.CreateCommand("oc", "delete", "-f", fmt.Sprintf("https://github.com/knative/eventing/releases/download/%s/in-memory-channel.yaml", knativeEventingVersion)).Execute() + if err != nil { + framework.GetMainLogger().Error(err, fmt.Sprintf("Deleting eventing in-memory channel failed, output: %s", output)) + if originalError == nil { + originalError = err + } + } + + output, err = framework.CreateCommand("oc", "delete", "-f", fmt.Sprintf("https://github.com/knative/eventing/releases/download/%s/eventing-core.yaml", knativeEventingVersion)).Execute() + if err != nil { + framework.GetMainLogger().Error(err, fmt.Sprintf("Deleting eventing core components failed, output: %s", output)) + if originalError == nil { + originalError = err + } + } + + return originalError +} + +func getKnativeEventingCrsInNamespace(namespace string) ([]client.Object, error) { + var crs []client.Object + + triggers := &eventingv1.TriggerList{} + if err := framework.GetObjectsInNamespace(namespace, triggers); err != nil { + return nil, err + } + for i := range triggers.Items { + crs = append(crs, &triggers.Items[i]) + } + + brokers := &eventingv1.BrokerList{} + if err := framework.GetObjectsInNamespace(namespace, brokers); err != nil { + return nil, err + } + for i := range brokers.Items { + crs = append(crs, &brokers.Items[i]) + } + + return crs, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/installers/mongodb_installer.go b/packages/kogito-serverless-operator/bddframework/pkg/installers/mongodb_installer.go new file mode 100644 index 00000000000..625469a2560 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/installers/mongodb_installer.go @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package installers + +import ( + "fmt" + + coreapps "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + rbac "k8s.io/api/rbac/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + mongodbv1 "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1" +) + +var ( + // mongoDbYamlNamespacedInstaller installs MongoDB namespaced using YAMLs + mongoDbYamlNamespacedInstaller = YamlNamespacedServiceInstaller{ + InstallNamespacedYaml: installMongoDbUsingYaml, + WaitForNamespacedServiceRunning: waitForMongoDbUsingYamlRunning, + GetAllNamespaceYamlCrs: getMongoDbCrsInNamespace, + UninstallNamespaceYaml: uninstallMongoDbUsingYaml, + NamespacedYamlServiceName: mongoDBOperatorServiceName, + } + + mongoDBOperatorServiceName = "Mongo DB" + mongoDBOperatorVersion = "v0.7.0" + mongoDBOperatorDeployFilesURI = "https://raw.githubusercontent.com/mongodb/mongodb-kubernetes-operator/" + mongoDBOperatorVersion + "/config/" +) + +// GetMongoDbInstaller returns MongoDB installer +func GetMongoDbInstaller() ServiceInstaller { + return &mongoDbYamlNamespacedInstaller +} + +func installMongoDbUsingYaml(namespace string) error { + framework.GetLogger(namespace).Info("Deploy MongoDB from yaml files", "file uri", mongoDBOperatorDeployFilesURI) + + if !framework.IsMongoDBAvailable(namespace) { + if err := framework.LoadResource(namespace, mongoDBOperatorDeployFilesURI+"crd/bases/mongodbcommunity.mongodb.com_mongodbcommunity.yaml", &apiextensionsv1.CustomResourceDefinition{}, nil); err != nil { + return err + } + } + + if err := framework.LoadResource(namespace, mongoDBOperatorDeployFilesURI+"rbac/service_account.yaml", &corev1.ServiceAccount{}, nil); err != nil { + return err + } + if err := framework.LoadResource(namespace, mongoDBOperatorDeployFilesURI+"rbac/role.yaml", &rbac.Role{}, nil); err != nil { + return err + } + if err := framework.LoadResource(namespace, mongoDBOperatorDeployFilesURI+"rbac/role_binding.yaml", &rbac.RoleBinding{}, nil); err != nil { + return err + } + + // Then deploy operator + err := framework.LoadResource(namespace, mongoDBOperatorDeployFilesURI+"manager/manager.yaml", &coreapps.Deployment{}, func(object interface{}) { + if framework.IsOpenshift() { + // See https://github.com/mongodb/mongodb-kubernetes-operator/blob/v0.7.0/deploy/openshift/operator_openshift.yaml + framework.GetLogger(namespace).Debug("Setup MANAGED_SECURITY_CONTEXT env in MongoDB operator for Openshift") + object.(*coreapps.Deployment).Spec.Template.Spec.Containers[0].Env = append(object.(*coreapps.Deployment).Spec.Template.Spec.Containers[0].Env, + corev1.EnvVar{ + Name: "MANAGED_SECURITY_CONTEXT", + Value: "true", + }) + labels := map[string]string{} + object.(*coreapps.Deployment).Namespace = namespace + object.(*coreapps.Deployment).Name = "mongodb-kubernetes-operator" + labels["owner"] = namespace + object.(*coreapps.Deployment).Labels = labels + //object.(*coreapps.Deployment).Spec.Template.Spec.Containers[0].Name = "mongodb-kubernetes-operator" + object.(*coreapps.Deployment).Spec.Template.Spec.Containers[0].SecurityContext = nil + object.(*coreapps.Deployment).Spec.Template.Spec.Containers[0].Image = "quay.io/mongodb/mongodb-kubernetes-operator:0.7.0" + } + }) + if err != nil { + return err + } + return nil +} + +func waitForMongoDbUsingYamlRunning(namespace string) error { + return framework.WaitForMongoDBOperatorRunning(namespace) +} + +func uninstallMongoDbUsingYaml(namespace string) error { + framework.GetMainLogger().Info("Uninstalling Mongo DB") + + var originalError error + + output, err := framework.CreateCommand("oc", "delete", "-f", mongoDBOperatorDeployFilesURI+"manager/manager.yaml").WithLoggerContext(namespace).Execute() + if err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Deleting Mongo DB operator failed, output: %s", output)) + if originalError == nil { + originalError = err + } + } + + output, err = framework.CreateCommand("oc", "delete", "-f", mongoDBOperatorDeployFilesURI+"rbac/role_binding.yaml").WithLoggerContext(namespace).Execute() + if err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Deleting Mongo DB role binding failed, output: %s", output)) + if originalError == nil { + originalError = err + } + } + + output, err = framework.CreateCommand("oc", "delete", "-f", mongoDBOperatorDeployFilesURI+"rbac/role.yaml").WithLoggerContext(namespace).Execute() + if err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Deleting Mongo DB role failed, output: %s", output)) + if originalError == nil { + originalError = err + } + } + + output, err = framework.CreateCommand("oc", "delete", "-f", mongoDBOperatorDeployFilesURI+"rbac/service_account.yaml").WithLoggerContext(namespace).Execute() + if err != nil { + framework.GetLogger(namespace).Error(err, fmt.Sprintf("Deleting Mongo DB service account failed, output: %s", output)) + if originalError == nil { + originalError = err + } + } + + return nil +} + +func getMongoDbCrsInNamespace(namespace string) ([]client.Object, error) { + var crs []client.Object + + mongoDbs := &mongodbv1.MongoDBCommunityList{} + if err := framework.GetObjectsInNamespace(namespace, mongoDbs); err != nil { + return nil, err + } + for i := range mongoDbs.Items { + crs = append(crs, &mongoDbs.Items[i]) + } + + return crs, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/installers/prometheus_installer.go b/packages/kogito-serverless-operator/bddframework/pkg/installers/prometheus_installer.go new file mode 100644 index 00000000000..8d2b8b100c0 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/installers/prometheus_installer.go @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package installers + +import ( + monv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +var ( + // prometheusOlmNamespacedInstaller installs Prometheus in the namespace using OLM + prometheusOlmNamespacedInstaller = OlmNamespacedServiceInstaller{ + SubscriptionName: prometheusOperatorSubscriptionName, + Channel: prometheusOperatorSubscriptionChannel, + Catalog: framework.GetCommunityCatalog, + InstallationTimeoutInMinutes: 3, + GetAllNamespacedOlmCrsInNamespace: getPrometheusCrsInNamespace, + } + + prometheusOperatorSubscriptionName = "prometheus" + prometheusOperatorSubscriptionChannel = "beta" +) + +// GetPrometheusInstaller returns Prometheus installer +func GetPrometheusInstaller() ServiceInstaller { + return &prometheusOlmNamespacedInstaller +} + +func getPrometheusCrsInNamespace(namespace string) ([]client.Object, error) { + var crs []client.Object + + prometheuses := &monv1.PrometheusList{} + if err := framework.GetObjectsInNamespace(namespace, prometheuses); err != nil { + return nil, err + } + for i := range prometheuses.Items { + crs = append(crs, prometheuses.Items[i]) + } + + return crs, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/installers/service_installer.go b/packages/kogito-serverless-operator/bddframework/pkg/installers/service_installer.go new file mode 100644 index 00000000000..478b2029547 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/installers/service_installer.go @@ -0,0 +1,470 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package installers + +import ( + "fmt" + "sync" + "time" + + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +var ( + waitForAllCrsRemovalTimeout = 1 * time.Minute + + // Map of installed services for namespaces, contains slices of service installers installing services in those namespaces + installedNamespacedServices sync.Map + // Map of cluster wide installed services + installedClusterWideServices sync.Map +) + +// ServiceInstaller is the API to install services +type ServiceInstaller interface { + // Install the service into cloud to serve the namespace + Install(namespace string) error + // Return all CRs of this service which exists in this namespace + getAllCrsInNamespace(namespace string) ([]client.Object, error) + // Returns service name for logging purposes + getServiceName() string + // Cleanup the namespace from service CRs. This functionality is needed because of Kogito service KogitoInfra object. + // KogitoInfra can exists with or without owner and when owner is deleted then KogitoInfra will remain. + // Other services just remove CRs without owner and that will remove all other CRs. + // Returns true in case of success, false in case of some error, logging is handled within the function. + cleanupCrsInNamespace(namespace string) bool +} + +// ClusterWideServiceInstaller is the API of cluster wide services +type ClusterWideServiceInstaller interface { + ServiceInstaller + // Uninstall service from whole cluster + uninstallFromCluster() error +} + +// NamespacedServiceInstaller is the API of namespaced services +type NamespacedServiceInstaller interface { + ServiceInstaller + // Uninstall service from specific namespace + uninstallFromNamespace(namespace string) error +} + +// Generic API for all services + +// UninstallServicesFromNamespace uninstalls all services from specific namespace. Returns false in case of any error while uninstalling. +func UninstallServicesFromNamespace(namespace string) (success bool) { + success = true + + // Delete all CRs without owner + if ok := executeOnClusterWideServices(func(si ClusterWideServiceInstaller) bool { + return si.cleanupCrsInNamespace(namespace) + }); !ok { + success = false + } + if ok := executeOnNamespacedServices(namespace, func(si NamespacedServiceInstaller) bool { + return si.cleanupCrsInNamespace(namespace) + }); !ok { + success = false + } + + // Wait until all CRs are removed + if ok := executeOnClusterWideServices(func(si ClusterWideServiceInstaller) bool { + return waitForAllCrsRemoval(si, namespace, waitForAllCrsRemovalTimeout) + }); !ok { + success = false + } + if ok := executeOnNamespacedServices(namespace, func(si NamespacedServiceInstaller) bool { + return waitForAllCrsRemoval(si, namespace, waitForAllCrsRemovalTimeout) + }); !ok { + success = false + } + + // Remove namespaced services + servicesNotDeleted := []NamespacedServiceInstaller{} + if ok := executeOnNamespacedServices(namespace, func(si NamespacedServiceInstaller) bool { + if err := si.uninstallFromNamespace(namespace); err != nil { + framework.GetLogger(namespace).Error(err, "Error uninstalling service from namespace", "service name", si.getServiceName()) + servicesNotDeleted = append(servicesNotDeleted, si) + return false + } + return true + }); !ok { + success = false + } + + // Add not removed services back to the list + installedNamespacedServices.Store(namespace, servicesNotDeleted) + + return success +} + +// UninstallServicesFromCluster uninstalls the cluster wide service from whole cluster. Returns false in case of any error while uninstalling. +func UninstallServicesFromCluster() (success bool) { + success = true + + servicesDeleted := []ClusterWideServiceInstaller{} + if ok := executeOnClusterWideServices(func(si ClusterWideServiceInstaller) bool { + if err := si.uninstallFromCluster(); err != nil { + framework.GetMainLogger().Error(err, "Error uninstalling service from cluster", "service name", si.getServiceName()) + return false + } + servicesDeleted = append(servicesDeleted, si) + return true + }); !ok { + success = false + } + + // Remove deleted services from list + for si := range servicesDeleted { + installedClusterWideServices.Delete(si) + } + + return success +} + +// YAML namespaced service specification + +// Make sure that YamlNamespacedServiceInstaller can be typed to NamespacedServiceInstaller +var _ NamespacedServiceInstaller = &YamlNamespacedServiceInstaller{} + +// YamlNamespacedServiceInstaller installs service using YAML files applied to specific namespace +type YamlNamespacedServiceInstaller struct { + // Install service for specific namespaces + InstallNamespacedYaml func(namespace string) error + // Wait until the service is up and running + WaitForNamespacedServiceRunning func(namespace string) error + // Return all CRs of this service which exists in this namespace + GetAllNamespaceYamlCrs func(string) ([]client.Object, error) + // Uninstall service from namespace + UninstallNamespaceYaml func(namespace string) error + // Service name + NamespacedYamlServiceName string + // Cleanup functionality, will delete CRs without owner if not defined + CleanupNamespaceYamlCrs func(namespace string) bool +} + +// Install the namespaced service using YAML files into cloud +func (installer *YamlNamespacedServiceInstaller) Install(namespace string) error { + // Store service installer for namespace to use for uninstalling purposes + if sis, loaded := installedNamespacedServices.LoadOrStore(namespace, []NamespacedServiceInstaller{installer}); loaded { + installedNamespacedServices.Store(namespace, append(sis.([]NamespacedServiceInstaller), installer)) + } + + if err := installer.InstallNamespacedYaml(namespace); err != nil { + return err + } + + return installer.WaitForNamespacedServiceRunning(namespace) +} + +func (installer *YamlNamespacedServiceInstaller) getAllCrsInNamespace(namespace string) ([]client.Object, error) { + return installer.GetAllNamespaceYamlCrs(namespace) +} + +func (installer *YamlNamespacedServiceInstaller) uninstallFromNamespace(namespace string) error { + return installer.UninstallNamespaceYaml(namespace) +} + +func (installer *YamlNamespacedServiceInstaller) getServiceName() string { + return installer.NamespacedYamlServiceName +} + +func (installer *YamlNamespacedServiceInstaller) cleanupCrsInNamespace(namespace string) bool { + if installer.CleanupNamespaceYamlCrs == nil { + return deleteCrsWithoutOwner(installer, namespace) + } + return installer.CleanupNamespaceYamlCrs(namespace) +} + +// YAML cluster wide service specification + +// Make sure that YamlClusterWideServiceInstaller can be typed to ClusterWideServiceInstaller +var _ ClusterWideServiceInstaller = &YamlClusterWideServiceInstaller{} + +// YamlClusterWideServiceInstaller installs service using YAML files applied to specific namespace +type YamlClusterWideServiceInstaller struct { + // Install service for all namespaces + InstallClusterYaml func() error + // Namespace used for cluster wide service installation. + InstallationNamespace string + // Wait until the service is up and running + WaitForClusterYamlServiceRunning func() error + // Return all CRs of this service which exists in this namespace + GetAllClusterYamlCrsInNamespace func(string) ([]client.Object, error) + // Uninstall service from whole cluster + UninstallClusterYaml func() error + // Service name + ClusterYamlServiceName string + // Cleanup functionality, will delete CRs without owner if not defined + CleanupClusterYamlCrsInNamespace func(namespace string) bool +} + +// Install the cluster wide service using YAML files into cloud +func (installer *YamlClusterWideServiceInstaller) Install(namespace string) error { + // Store cluster wide service installer to use for uninstalling purposes + if _, loaded := installedClusterWideServices.LoadOrStore(installer, true); loaded { + // Should be running already, wait until it is up + return installer.WaitForClusterYamlServiceRunning() + } + + monitorNamespace(installer.InstallationNamespace) + + if err := installer.InstallClusterYaml(); err != nil { + return err + } + + framework.OnNamespacePostCreated(installer.InstallationNamespace) + + return installer.WaitForClusterYamlServiceRunning() +} + +func (installer *YamlClusterWideServiceInstaller) getAllCrsInNamespace(namespace string) ([]client.Object, error) { + return installer.GetAllClusterYamlCrsInNamespace(namespace) +} + +func (installer *YamlClusterWideServiceInstaller) uninstallFromCluster() error { + stopNamespaceMonitoring(installer.InstallationNamespace) + if err := installer.UninstallClusterYaml(); err != nil { + return err + } + framework.OnNamespacePostDeleted(installer.InstallationNamespace) + return nil +} + +func (installer *YamlClusterWideServiceInstaller) getServiceName() string { + return installer.ClusterYamlServiceName +} + +func (installer *YamlClusterWideServiceInstaller) cleanupCrsInNamespace(namespace string) bool { + if installer.CleanupClusterYamlCrsInNamespace == nil { + return deleteCrsWithoutOwner(installer, namespace) + } + return installer.CleanupClusterYamlCrsInNamespace(namespace) +} + +// OLM namespaced service specification + +// Make sure that OlmNamespacedServiceInstaller can be typed to NamespacedServiceInstaller +var _ NamespacedServiceInstaller = &OlmNamespacedServiceInstaller{} + +// OlmNamespacedServiceInstaller installs service using OLM, installed to specific namespace +type OlmNamespacedServiceInstaller struct { + SubscriptionName string + Channel string + StartingCSV string + Catalog func() framework.OperatorCatalog + InstallationTimeoutInMinutes int + // Return all CRs of this service which exists in this namespace + GetAllNamespacedOlmCrsInNamespace func(string) ([]client.Object, error) + // Cleanup functionality, will delete CRs without owner if not defined + CleanupNamespacedOlmCrsInNamespace func(namespace string) bool +} + +// Install the namespaced service using OLM into cloud +func (installer *OlmNamespacedServiceInstaller) Install(namespace string) error { + // Store service installer for namespace to use for uninstalling purposes + if sis, loaded := installedNamespacedServices.LoadOrStore(namespace, []NamespacedServiceInstaller{installer}); loaded { + installedNamespacedServices.Store(namespace, append(sis.([]NamespacedServiceInstaller), installer)) + } + + if err := framework.InstallOperator(namespace, installer.SubscriptionName, installer.Channel, installer.StartingCSV, installer.Catalog()); err != nil { + return err + } + + return framework.WaitForOperatorRunning(namespace, installer.SubscriptionName, installer.Catalog(), installer.InstallationTimeoutInMinutes) +} + +func (installer *OlmNamespacedServiceInstaller) getAllCrsInNamespace(namespace string) ([]client.Object, error) { + return installer.GetAllNamespacedOlmCrsInNamespace(namespace) +} + +func (installer *OlmNamespacedServiceInstaller) uninstallFromNamespace(namespace string) error { + subscription, err := framework.GetSubscription(namespace, installer.SubscriptionName, installer.Catalog()) + if err != nil { + return err + } + + return framework.DeleteSubscription(subscription) +} + +func (installer *OlmNamespacedServiceInstaller) getServiceName() string { + return installer.SubscriptionName +} + +func (installer *OlmNamespacedServiceInstaller) cleanupCrsInNamespace(namespace string) bool { + if installer.CleanupNamespacedOlmCrsInNamespace == nil { + return deleteCrsWithoutOwner(installer, namespace) + } + return installer.CleanupNamespacedOlmCrsInNamespace(namespace) +} + +// OLM cluster wide service specification + +// Make sure that OlmClusterWideServiceInstaller can be typed to ClusterWideServiceInstaller +var _ ClusterWideServiceInstaller = &OlmClusterWideServiceInstaller{} + +// OlmClusterWideServiceInstaller installs service using OLM, installed cluster wide +type OlmClusterWideServiceInstaller struct { + SubscriptionName string + Channel string + StartingCSV string + Catalog func() framework.OperatorCatalog + InstallationTimeoutInMinutes int + // Return all CRs of this service which exists in this namespace + GetAllClusterWideOlmCrsInNamespace func(string) ([]client.Object, error) + // Cleanup functionality, will delete CRs without owner if not defined + CleanupClusterWideOlmCrsInNamespace func(namespace string) bool +} + +// Install the cluster wide service using OLM into cloud +func (installer *OlmClusterWideServiceInstaller) Install(namespace string) error { + // Store cluster wide service installer to use for uninstalling purposes + if _, loaded := installedClusterWideServices.LoadOrStore(installer, true); loaded { + // Should be running already, wait until it is up + return framework.WaitForClusterWideOperatorRunning(installer.SubscriptionName, installer.Catalog(), installer.InstallationTimeoutInMinutes) + } + + if err := framework.InstallClusterWideOperator(installer.SubscriptionName, installer.Channel, installer.StartingCSV, installer.Catalog()); err != nil { + return err + } + + return framework.WaitForClusterWideOperatorRunning(installer.SubscriptionName, installer.Catalog(), installer.InstallationTimeoutInMinutes) +} + +func (installer *OlmClusterWideServiceInstaller) getAllCrsInNamespace(namespace string) ([]client.Object, error) { + return installer.GetAllClusterWideOlmCrsInNamespace(namespace) +} + +func (installer *OlmClusterWideServiceInstaller) uninstallFromCluster() error { + subscription, err := framework.GetClusterWideSubscription(installer.SubscriptionName, installer.Catalog()) + if err != nil { + return err + } + + return framework.DeleteSubscription(subscription) +} + +func (installer *OlmClusterWideServiceInstaller) getServiceName() string { + return installer.SubscriptionName +} + +func (installer *OlmClusterWideServiceInstaller) cleanupCrsInNamespace(namespace string) bool { + if installer.CleanupClusterWideOlmCrsInNamespace == nil { + return deleteCrsWithoutOwner(installer, namespace) + } + return installer.CleanupClusterWideOlmCrsInNamespace(namespace) +} + +// Helper methods + +// Execute a function on all deployed cluster wide services +func executeOnClusterWideServices(execute func(si ClusterWideServiceInstaller) bool) bool { + success := true + installedClusterWideServices.Range(func(si, _ interface{}) bool { + if ok := execute(si.(ClusterWideServiceInstaller)); !ok { + success = false + } + return true + }) + return success +} + +// Execute a function on all deployed namespaced services +func executeOnNamespacedServices(namespace string, execute func(si NamespacedServiceInstaller) bool) bool { + success := true + if sis, ok := installedNamespacedServices.Load(namespace); ok { + for _, si := range sis.([]NamespacedServiceInstaller) { + if ok := execute(si); !ok { + success = false + } + } + } + return success +} + +// Delete all CRs of the service which don't have owner +func deleteCrsWithoutOwner(installer ServiceInstaller, namespace string) bool { + crs, err := getCrsWithoutOwner(installer, namespace) + if err != nil { + framework.GetLogger(namespace).Error(err, "Error getting CRs without owner.", "service name", installer.getServiceName()) + return false + } + + for _, cr := range crs { + if err := framework.DeleteObject(cr); err != nil { + framework.GetLogger(namespace).Error(err, "Error deleting CR.", "service name", installer.getServiceName(), "CR name", cr.GetName()) + return false + } + } + return true +} + +// Get all CRs of the service which don't have owner +func getCrsWithoutOwner(installer ServiceInstaller, namespace string) (crsWithoutOwner []client.Object, err error) { + crs, err := installer.getAllCrsInNamespace(namespace) + if err != nil { + return nil, err + } + + crsWithoutOwner = []client.Object{} + for _, cr := range crs { + if len(cr.GetOwnerReferences()) == 0 { + crsWithoutOwner = append(crsWithoutOwner, cr) + } + } + return crsWithoutOwner, nil +} + +// Wait until all CRs of the service are removed from namespace +func waitForAllCrsRemoval(installer ServiceInstaller, namespace string, timeout time.Duration) bool { + success := true + err := framework.WaitFor(namespace, fmt.Sprintf("Removal of all related CRs for service %s", installer.getServiceName()), timeout, func() (bool, error) { + crs, err := installer.getAllCrsInNamespace(namespace) + if err != nil { + return false, err + } + + return len(crs) == 0, nil + }) + if err != nil { + framework.GetLogger(namespace).Error(err, "Error waiting on removal of all related CRs", "service name", installer.getServiceName()) + success = false + } + return success +} + +func monitorNamespace(namespace string) { + go func() { + err := framework.StartPodLogCollector(namespace) + if err != nil { + framework.GetLogger(namespace).Error(err, "Error starting log collector", "namespace", namespace) + } + }() +} + +func stopNamespaceMonitoring(namespace string) { + if err := framework.StopPodLogCollector(namespace); err != nil { + framework.GetMainLogger().Error(err, "Error stopping log collector", "namespace", namespace) + } + if err := framework.BumpEvents(namespace); err != nil { + framework.GetMainLogger().Error(err, "Error bumping events", "namespace", namespace) + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/meta/meta.go b/packages/kogito-serverless-operator/bddframework/pkg/meta/meta.go new file mode 100644 index 00000000000..0bd8edda047 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/meta/meta.go @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package meta + +import ( + appsv1 "github.com/openshift/api/apps/v1" + buildv1 "github.com/openshift/api/build/v1" + imgv1 "github.com/openshift/api/image/v1" + routev1 "github.com/openshift/api/route/v1" + coreappsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + rbac "k8s.io/api/rbac/v1" + eventing "knative.dev/eventing/pkg/apis/eventing/v1" + sources "knative.dev/eventing/pkg/apis/sources/v1" + + hyperfoil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2" + grafana "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1" + infinispan "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1" + kafka "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2" + keycloak "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1" + mongodb "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1" + + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + + olmapiv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1" + olmapiv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1" + olmv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/apis/operators/v1" + prometheus "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" +) + +// GetRegisteredSchema gets all schema and types registered for use with CLI, unit tests, custom clients and so on +func GetRegisteredSchema() *runtime.Scheme { + s := runtime.NewScheme() + schemes := getRegisteredSchemeBuilder() + err := schemes.AddToScheme(s) + if err != nil { + panic(err) + } + + // https://issues.jboss.org/browse/KOGITO-617 + metav1.AddToGroupVersion(s, apiextensionsv1.SchemeGroupVersion) + metav1.AddToGroupVersion(s, appsv1.GroupVersion) + metav1.AddToGroupVersion(s, prometheus.SchemeGroupVersion) + metav1.AddToGroupVersion(s, routev1.GroupVersion) + metav1.AddToGroupVersion(s, infinispan.SchemeGroupVersion) + metav1.AddToGroupVersion(s, mongodb.SchemeBuilder.GroupVersion) + metav1.AddToGroupVersion(s, kafka.SchemeGroupVersion) + metav1.AddToGroupVersion(s, grafana.GroupVersion) + metav1.AddToGroupVersion(s, eventing.SchemeGroupVersion) + metav1.AddToGroupVersion(s, sources.SchemeGroupVersion) + metav1.AddToGroupVersion(s, hyperfoil.GroupVersion) + metav1.AddToGroupVersion(s, olmapiv1.SchemeGroupVersion) + metav1.AddToGroupVersion(s, olmapiv1alpha1.SchemeGroupVersion) + metav1.AddToGroupVersion(s, olmv1.SchemeGroupVersion) + return s +} + +// getRegisteredSchemeBuilder gets the SchemeBuilder with all the desired APIs registered +func getRegisteredSchemeBuilder() runtime.SchemeBuilder { + return runtime.NewSchemeBuilder( + clientgoscheme.AddToScheme, + corev1.AddToScheme, + coreappsv1.AddToScheme, + buildv1.Install, + rbac.AddToScheme, + appsv1.Install, + coreappsv1.AddToScheme, + routev1.Install, + imgv1.Install, + apiextensionsv1.AddToScheme, + kafka.SchemeBuilder.AddToScheme, + mongodb.SchemeBuilder.AddToScheme, + infinispan.AddToScheme, + keycloak.SchemeBuilder.AddToScheme, + prometheus.SchemeBuilder.AddToScheme, + eventing.AddToScheme, sources.AddToScheme, + grafana.AddToScheme, + hyperfoil.AddToScheme, + olmapiv1alpha1.AddToScheme, + olmapiv1.AddToScheme, + olmv1.AddToScheme, + // Required for MogoDB, can be removed once we start using newer MongoDB operator version + apiextensionsv1beta1.AddToScheme) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/data.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/data.go new file mode 100644 index 00000000000..342cf3f1ef8 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/data.go @@ -0,0 +1,199 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "fmt" + "strings" + "sync" + "time" + + "github.com/cucumber/messages-go/v16" + + "github.com/cucumber/godog" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +var ( + // Map of created namespaces + namespacesCreated sync.Map +) + +// Data contains all data needed by Gherkin steps to run +type Data struct { + Namespace string + StartTime time.Time + KogitoExamplesLocation string + ScenarioName string + ScenarioContext map[string]string + logsKubernetesObjects []client.ObjectList +} + +// RegisterAllSteps register all steps available to the test suite +func (data *Data) RegisterAllSteps(ctx *godog.ScenarioContext) { + registerGitSteps(ctx, data) + registerGrafanaSteps(ctx, data) + registerGraphQLSteps(ctx, data) + registerHTTPSteps(ctx, data) + registerHyperfoilSteps(ctx, data) + registerImageRegistrySteps(ctx, data) + registerInfinispanSteps(ctx, data) + registerKafkaSteps(ctx, data) + registerKnativeEventingKogitoSteps(ctx, data) + registerKnativeSteps(ctx, data) + registerKogitoDataIndexServiceSteps(ctx, data) + registerKogitoJobsServiceSteps(ctx, data) + registerKogitoManagementConsoleSteps(ctx, data) + registerKogitoTaskConsoleSteps(ctx, data) + registerKubernetesSteps(ctx, data) + registerMavenSteps(ctx, data) + registerMongoDBSteps(ctx, data) + registerOpenShiftSteps(ctx, data) + registerPostgresqlSteps(ctx, data) + registerPrometheusSteps(ctx, data) + registerProcessSteps(ctx, data) + registerTaskSteps(ctx, data) + registerKeycloakSteps(ctx, data) +} + +// RegisterLogsKubernetesObjects allows to change which kubernetes objects logs should be saved +func (data *Data) RegisterLogsKubernetesObjects(objects ...client.ObjectList) { + data.logsKubernetesObjects = append(data.logsKubernetesObjects, objects...) +} + +// BeforeScenario configure the data before a scenario is launched +func (data *Data) BeforeScenario(scenario *messages.Pickle) error { + data.StartTime = time.Now() + data.Namespace = getNamespaceName() + data.KogitoExamplesLocation = createTemporaryFolder() + data.ScenarioName = scenario.Name + data.ScenarioContext = map[string]string{} + + var err error + framework.GetLogger(data.Namespace).Info(fmt.Sprintf("Scenario %s", scenario.Name)) + go func() { + err = framework.StartPodLogCollector(data.Namespace) + }() + if err != nil { + return err + } + + return nil +} + +func getNamespaceName() string { + if namespaceName := config.GetNamespaceName(); len(namespaceName) > 0 { + return namespaceName + } + return generateNamespaceName() +} + +func generateNamespaceName() string { + ns := framework.GenerateNamespaceName("bdd") + for isNamespaceAlreadyCreated(ns) { + ns = framework.GenerateNamespaceName("bdd") + } + namespacesCreated.Store(ns, true) + return ns +} + +func isNamespaceAlreadyCreated(namespace string) bool { + _, exists := namespacesCreated.Load(namespace) + return exists +} + +func createTemporaryFolder() string { + dir, err := framework.CreateTemporaryFolder("kogito-examples") + if err != nil { + panic(fmt.Errorf("Error creating new temporary folder: %v", err)) + } + return dir +} + +// AfterScenario executes some actions on data after a scenario is finished +func (data *Data) AfterScenario(scenario *godog.Scenario, err error) error { + error := framework.OperateOnNamespaceIfExists(data.Namespace, func(namespace string) error { + if err := framework.StopPodLogCollector(namespace); err != nil { + framework.GetMainLogger().Error(err, "Error stopping log collector", "namespace", namespace) + } + if err := framework.FlushLogger(namespace); err != nil { + framework.GetMainLogger().Error(err, "Error flushing running logs", "namespace", namespace) + } + if err := framework.BumpEvents(data.Namespace); err != nil { + framework.GetMainLogger().Error(err, "Error bumping events", "namespace", namespace) + } + if err := framework.LogKubernetesObjects(data.Namespace, data.logsKubernetesObjects...); err != nil { + framework.GetMainLogger().Error(err, "Error logging Kubernetes objects", "namespace", namespace) + } + return nil + }) + + handleScenarioResult(data, scenario, err) + logScenarioDuration(data) + deleteTemporaryExamplesFolder(data) + + if error != nil { + return error + } + + return nil +} + +// ResolveWithScenarioContext replaces all the variables in the string with their values. +func (data *Data) ResolveWithScenarioContext(str string) string { + result := str + for name, value := range data.ScenarioContext { + result = strings.ReplaceAll(result, "{"+name+"}", value) + } + + return result +} + +func logScenarioDuration(data *Data) { + endTime := time.Now() + duration := endTime.Sub(data.StartTime) + framework.GetLogger(data.Namespace).Info("Scenario duration", "duration", duration.String()) +} + +func handleScenarioResult(data *Data, scenario *messages.Pickle, err error) { + newLogFolderName := fmt.Sprintf("%s - %s", strings.ReplaceAll(scenario.Name, "/", "_"), data.Namespace) + var parentLogFolder string + if err != nil { + framework.GetLogger(data.Namespace).Error(err, "Error in scenario", "scenarioName", scenario.Name) + parentLogFolder = "error" + } else { + parentLogFolder = "success" + framework.GetLogger(data.Namespace).Info("Successful scenario", "scenarioName", scenario.Name) + } + err = framework.RenameLogFolder(data.Namespace, parentLogFolder, newLogFolderName) + if err != nil { + framework.GetMainLogger().Error(err, "Error while moving log foler", "logFolder", newLogFolderName, "namespace", data.Namespace) + } +} + +func deleteTemporaryExamplesFolder(data *Data) { + err := framework.DeleteFolder(data.KogitoExamplesLocation) + if err != nil { + framework.GetMainLogger().Error(err, "Error while deleting temporary examples folder", "folderName", data.KogitoExamplesLocation) + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/git.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/git.go new file mode 100644 index 00000000000..948da5ac367 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/git.go @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + git "gopkg.in/src-d/go-git.v4" + "gopkg.in/src-d/go-git.v4/plumbing" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +// registerGitSteps register all existing GIT steps +func registerGitSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Clone Kogito examples into local directory$`, data.cloneKogitoExamplesIntoLocalDirectory) +} + +func (data *Data) cloneKogitoExamplesIntoLocalDirectory() error { + framework.GetLogger(data.Namespace).Info("Cloning kogito examples", "URI", config.GetExamplesRepositoryURI(), "branch", config.GetExamplesRepositoryRef(), "clonedLocation", data.KogitoExamplesLocation) + + cloneOptions := &git.CloneOptions{ + URL: config.GetExamplesRepositoryURI(), + SingleBranch: true, + } + + var err error + reference := config.GetExamplesRepositoryRef() + if len(reference) == 0 { + err = cloneExamples(data.KogitoExamplesLocation, cloneOptions) + } else { + // Try cloning as branch reference + cloneOptions.ReferenceName = plumbing.NewBranchReferenceName(reference) + err = cloneExamples(data.KogitoExamplesLocation, cloneOptions) + // If branch clone was successful then return, otherwise try other cloning options + if err == nil { + return nil + } + + // If branch cloning failed then try cloning as tag + cloneOptions.ReferenceName = plumbing.NewTagReferenceName(reference) + err = cloneExamples(data.KogitoExamplesLocation, cloneOptions) + } + return err +} + +func cloneExamples(examplesLocation string, cloneOptions *git.CloneOptions) error { + _, err := git.PlainClone(examplesLocation, false, cloneOptions) + return err +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/grafana.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/grafana.go new file mode 100644 index 00000000000..db128c9e332 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/grafana.go @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/installers" +) + +func registerGrafanaSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Grafana Operator is deployed$`, data.grafanaOperatorIsDeployed) + ctx.Step(`^Grafana instance is deployed, monitoring services with label name "([^"]*)" and value "([^"]*)"$`, data.grafanaInstanceIsDeployed) +} + +func (data *Data) grafanaOperatorIsDeployed() error { + return installers.GetGrafanaInstaller().Install(data.Namespace) +} + +func (data *Data) grafanaInstanceIsDeployed(labelName, labelValue string) error { + err := framework.DeployGrafanaInstance(data.Namespace, labelName, labelValue) + if err != nil { + return err + } + return framework.WaitForPodsWithLabel(data.Namespace, "app", "grafana", 1, 3) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/graphql.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/graphql.go new file mode 100644 index 00000000000..297c1cef58f --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/graphql.go @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "fmt" + "strconv" + "strings" + "time" + + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +func registerGraphQLSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^GraphQL request on service "([^"]*)" is successful within (\d+) minutes with path "([^"]*)" and query:$`, data.graphqlRequestOnServiceIsSuccessfulWithinMinutesWithPathAndQuery) + ctx.Step(`^GraphQL request on service "([^"]*)" is successful using access token "([^"]*)" within (\d+) minutes with path "([^"]*)" and query:$`, data.graphqlRequestOnServiceIsSuccessfulUsingAccessTokenWithinMinutesWithPathAndQuery) + ctx.Step(`^GraphQL request on Data Index service returns ProcessInstances processName "([^"]*)" within (\d+) minutes$`, data.graphqlRequestOnDataIndexReturnsProcessInstancesProcessNameWithinMinutes) + ctx.Step(`^GraphQL request on Data Index service returns (\d+) (?:instance|instances) of process with name "([^"]*)" within (\d+) minutes$`, data.graphqlRequestOnDataIndexReturnsInstancesOfProcessWithNameWithinMinutes) + ctx.Step(`^GraphQL request on Data Index service returns (\d+) (?:instance|instances) of process with id "([^"]*)" within (\d+) minutes$`, data.graphqlRequestOnDataIndexReturnsInstancesOfProcessWithIDWithinMinutes) + ctx.Step(`^GraphQL request on Data Index service returns Jobs ID "([^"]*)" within (\d+) minutes$`, data.graphqlRequestOnDataIndexReturnsJobsIDWithinMinutes) + + ctx.Step(`^GraphQL request on Data Index service getting instances of process with id "([^"]*)" fails within (\d+) minutes$`, data.graphqlRequestOnDataIndexGettingProcessWithIDFailsWithinMinutes) +} + +func (data *Data) graphqlRequestOnServiceIsSuccessfulWithinMinutesWithPathAndQuery(serviceName string, timeoutInMin int, path string, query *godog.DocString) error { + framework.GetLogger(data.Namespace).Debug("graphqlRequestOnServiceWithPathAndBodyIsSuccessfulWithinMinutes", "service", serviceName, "path", path, "query", query, "timeout", timeoutInMin) + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + var response interface{} + return framework.WaitForSuccessfulGraphQLRequest(data.Namespace, uri, path, query.Content, timeoutInMin, response, nil) +} + +func (data *Data) graphqlRequestOnServiceIsSuccessfulUsingAccessTokenWithinMinutesWithPathAndQuery(serviceName, accessToken string, timeoutInMin int, path string, query *godog.DocString) error { + accessToken = data.ResolveWithScenarioContext(accessToken) + framework.GetLogger(data.Namespace).Debug("graphqlRequestOnServiceIsSuccessfulUsingAccessTokenWithinMinutesWithPathAndQuery", "service", serviceName, "path", path, "query", query, "access token", accessToken, "timeout", timeoutInMin) + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + var response interface{} + return framework.WaitForSuccessfulGraphQLRequestUsingAccessToken(data.Namespace, uri, path, query.Content, accessToken, timeoutInMin, response, nil) +} + +func (data *Data) graphqlRequestOnDataIndexReturnsProcessInstancesProcessNameWithinMinutes(processName string, timeoutInMin int) error { + serviceName := framework.DefaultDataIndexName + query := getProcessInstancesNameQuery + path := "graphql" + + framework.GetLogger(data.Namespace).Debug("graphqlProcessNameRequestOnDataIndexIsSuccessfulWithinMinutes", "service", serviceName, "path", path, "query", query, "timeout", timeoutInMin) + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + response := GraphqlDataIndexProcessInstancesQueryResponse{} + return framework.WaitForSuccessfulGraphQLRequest(data.Namespace, uri, path, query, timeoutInMin, &response, func(response interface{}) (bool, error) { + resp := response.(*GraphqlDataIndexProcessInstancesQueryResponse) + for _, processInstance := range resp.ProcessInstances { + if processInstance.ProcessName == processName { + return true, nil + } + } + return false, nil + }) +} + +func (data *Data) graphqlRequestOnDataIndexReturnsInstancesOfProcessWithNameWithinMinutes(processInstances int, processName string, timeoutInMin int) error { + pageSize := 1000 + preProcessedQuery := strings.ReplaceAll(getProcessInstancesIDByProcessNameQuery, "$name", processName) + preProcessedQuery = strings.ReplaceAll(preProcessedQuery, "$limit", strconv.Itoa(pageSize)) + return graphqlRequestOnDataIndexReturnsInstancesOfProcessWithinMinutes(data.Namespace, preProcessedQuery, processInstances, pageSize, timeoutInMin) +} + +func (data *Data) graphqlRequestOnDataIndexReturnsInstancesOfProcessWithIDWithinMinutes(processInstances int, processID string, timeoutInMin int) error { + pageSize := 1000 + preProcessedQuery := strings.ReplaceAll(getProcessInstancesIDByProcessIDQuery, "$id", processID) + preProcessedQuery = strings.ReplaceAll(preProcessedQuery, "$limit", strconv.Itoa(pageSize)) + return graphqlRequestOnDataIndexReturnsInstancesOfProcessWithinMinutes(data.Namespace, preProcessedQuery, processInstances, pageSize, timeoutInMin) +} + +func graphqlRequestOnDataIndexReturnsInstancesOfProcessWithinMinutes(namespace string, processQuery string, processInstances, pageSize, timeoutInMin int) error { + serviceName := framework.DefaultDataIndexName + path := "graphql" + + framework.GetLogger(namespace).Debug("graphqlRequestOnDataIndexReturnsInstancesOfProcessWithNameWithinMinutes", "service", serviceName, "path", path, "query", processQuery, "timeout", timeoutInMin) + uri, err := framework.WaitAndRetrieveEndpointURI(namespace, serviceName) + if err != nil { + return err + } + response := GraphqlDataIndexProcessInstancesIDQueryResponse{} + var allQueriedProcessInstances GraphqlDataIndexProcessInstancesIDQueryResponse + + startTime := time.Now() + + err = framework.WaitForSuccessfulGraphQLRequestUsingPagination(namespace, uri, path, processQuery, timeoutInMin, pageSize, processInstances, &response, + func(response interface{}) (bool, error) { + resp := response.(*GraphqlDataIndexProcessInstancesIDQueryResponse) + allQueriedProcessInstances.ProcessInstances = append(allQueriedProcessInstances.ProcessInstances, resp.ProcessInstances...) + return true, nil + }, + func() (bool, error) { + queried := len(allQueriedProcessInstances.ProcessInstances) + framework.GetLogger(namespace).Info("Queried records", "got", queried, "expected", processInstances) + conditionMet := queried == processInstances + if !conditionMet { // delete all results so we can start again + allQueriedProcessInstances.ProcessInstances = nil + } + return conditionMet, nil + }) + + duration := time.Since(startTime) + // TODO include reporting + framework.GetLogger(namespace).Info(fmt.Sprintf("%d process instances retrieved from Data Index after %s", processInstances, duration)) + + return err +} + +func (data *Data) graphqlRequestOnDataIndexReturnsJobsIDWithinMinutes(id string, timeoutInMin int) error { + serviceName := framework.DefaultDataIndexName + query := getJobsIDQuery + path := "graphql" + + framework.GetLogger(data.Namespace).Debug("graphqlRequestOnDataIndexReturnsJobsIDWithinMinutes", "service", serviceName, "path", path, "query", query, "timeout", timeoutInMin) + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + response := GraphqlDataIndexJobsQueryResponse{} + return framework.WaitForSuccessfulGraphQLRequest(data.Namespace, uri, path, query, timeoutInMin, &response, func(response interface{}) (bool, error) { + resp := response.(*GraphqlDataIndexJobsQueryResponse) + for _, job := range resp.Jobs { + if job.ID == id { + return true, nil + } + } + return false, nil + }) +} + +func (data *Data) graphqlRequestOnDataIndexGettingProcessWithIDFailsWithinMinutes(processName string, timeoutInMin int) error { + serviceName := framework.DefaultDataIndexName + query := getProcessInstancesNameQuery + path := "graphql" + + framework.GetLogger(data.Namespace).Debug("graphqlProcessNameRequestOnDataIndexIsSuccessfulWithinMinutes", "service", serviceName, "path", path, "query", query, "timeout", timeoutInMin) + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + return framework.WaitForFailingGraphQLRequest(data.Namespace, uri, path, query, timeoutInMin) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/graphql_queries.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/graphql_queries.go new file mode 100644 index 00000000000..9472fc79c53 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/graphql_queries.go @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +var ( + getProcessInstancesNameQuery = ` + { + ProcessInstances{ + processName + } + } + ` + getProcessInstancesIDByProcessNameQuery = ` + { + ProcessInstances(where: {processName: {equal: "$name"}}, pagination: {offset: $offset, limit: $limit}) { + id + } + } + ` + getProcessInstancesIDByProcessIDQuery = ` + { + ProcessInstances(where: {processId: {equal: "$id"}}, pagination: {offset: $offset, limit: $limit}) { + id + } + } + ` + getJobsIDQuery = ` + { + Jobs{ + id + } + } + ` +) + +// GraphqlDataIndexProcessInstancesQueryResponse Query response type of Data Index GraphQL endpoint containing process instances +type GraphqlDataIndexProcessInstancesQueryResponse struct { + ProcessInstances []struct { + ProcessName string `json:"processName,omitempty"` + } +} + +// GraphqlDataIndexProcessInstancesIDQueryResponse Query response type of Data Index GraphQL endpoint containing process instance IDs +type GraphqlDataIndexProcessInstancesIDQueryResponse struct { + ProcessInstances []struct { + ID string `json:"id,omitempty"` + } +} + +// GraphqlDataIndexJobsQueryResponse Query response type of Data Index GraphQL endpoint containing jobs +type GraphqlDataIndexJobsQueryResponse struct { + Jobs []struct { + ID string `json:"id,omitempty"` + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/http.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/http.go new file mode 100644 index 00000000000..21b74f80dcd --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/http.go @@ -0,0 +1,250 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "fmt" + "strings" + "time" + + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +func registerHTTPSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^HTTP GET request on service "([^"]*)" with path "([^"]*)" is successful within (\d+) minutes$`, data.httpGetRequestOnServiceWithPathIsSuccessfulWithinMinutes) + ctx.Step(`^HTTP GET request on service "([^"]*)" with path "([^"]*)" is forbidden within (\d+) minutes$`, data.httpGetRequestOnServiceWithPathIsForbiddenWithinMinutes) + ctx.Step(`^HTTP GET request on service "([^"]*)" with path "([^"]*)" fails within (\d+) minutes$`, data.httpGetRequestOnServiceWithPathFailsWithinMinutes) + ctx.Step(`^HTTP GET request on service "([^"]*)" using access token "([^"]*)" with path "([^"]*)" is successful within (\d+) minutes$`, data.httpGetRequestOnServiceUsingAccessTokenWithPathIsSuccessfulWithinMinutes) + ctx.Step(`^HTTP GET request on service "([^"]*)" with path "([^"]*)" should return an array of size (\d+) within (\d+) minutes$`, data.httpGetRequestOnServiceWithPathShouldReturnAnArrayofSizeWithinMinutes) + ctx.Step(`^HTTP GET request on service "([^"]*)" with path "([^"]*)" should contain a string "([^"]*)" within (\d+) minutes$`, data.httpGetRequestOnServiceWithPathShouldContainAstringWithinMinutes) + ctx.Step(`^HTTP GET request on service "([^"]*)" with path "([^"]*)" should not contain a string "([^"]*)" within (\d+) minutes$`, data.httpGetRequestOnServiceWithPathShouldNotContainAstringWithinMinutes) + ctx.Step(`^HTTP POST request on service "([^"]*)" with path "([^"]*)" and body:$`, data.httpPostRequestOnServiceWithPathAndBody) + ctx.Step(`^HTTP POST request on service "([^"]*)" is successful within (\d+) minutes with path "([^"]*)" and body:$`, data.httpPostRequestOnServiceIsSuccessfulWithinMinutesWithPathAndBody) + ctx.Step(`^HTTP POST request on service "([^"]*)" is successful within (\d+) minutes with path "([^"]*)", headers "([^"]*)" and body:$`, data.httpPostRequestOnServiceIsSuccessfulWithinMinutesWithPathHeadersAndBody) + ctx.Step(`^HTTP POST request on service "([^"]*)" using access token "([^"]*)" is successful within (\d+) minutes with path "([^"]*)" and body:$`, data.httpPostRequestOnServiceUsingAccessTokenIsSuccessfulWithinMinutesWithPathAndBody) + ctx.Step(`^(\d+) HTTP POST requests using (\d+) threads on service "([^"]*)" with path "([^"]*)" and body:$`, data.httpPostRequestsUsingThreadsOnServiceWithPathAndBody) + ctx.Step(`^(\d+) HTTP POST requests with report using (\d+) threads on service "([^"]*)" with path "([^"]*)" and body:$`, data.httpPostRequestsWithReportUsingThreadsOnServiceWithPathAndBody) +} + +func (data *Data) httpGetRequestOnServiceWithPathIsSuccessfulWithinMinutes(serviceName, path string, timeoutInMin int) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + requestInfo := framework.NewGETHTTPRequestInfo(uri, data.ResolveWithScenarioContext(path)) + return framework.WaitForSuccessfulHTTPRequest(data.Namespace, requestInfo, timeoutInMin) +} + +func (data *Data) httpGetRequestOnServiceWithPathIsForbiddenWithinMinutes(serviceName, path string, timeoutInMin int) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + requestInfo := framework.NewGETHTTPRequestInfo(uri, data.ResolveWithScenarioContext(path)) + return framework.WaitForForbiddenHTTPRequest(data.Namespace, requestInfo, timeoutInMin) +} + +func (data *Data) httpGetRequestOnServiceWithPathFailsWithinMinutes(serviceName, path string, timeoutInMin int) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + requestInfo := framework.NewGETHTTPRequestInfo(uri, data.ResolveWithScenarioContext(path)) + return framework.WaitForFailedHTTPRequest(data.Namespace, requestInfo, timeoutInMin) +} + +func (data *Data) httpGetRequestOnServiceUsingAccessTokenWithPathIsSuccessfulWithinMinutes(serviceName, token, path string, timeoutInMin int) error { + token = data.ResolveWithScenarioContext(token) + + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + requestInfo := framework.NewGETHTTPRequestInfo(uri, data.ResolveWithScenarioContext(path)) + requestInfo.Token = token + return framework.WaitForSuccessfulHTTPRequest(data.Namespace, requestInfo, timeoutInMin) +} + +func (data *Data) httpPostRequestOnServiceWithPathAndBody(serviceName, path string, body *godog.DocString) error { + path = data.ResolveWithScenarioContext(path) + bodyContent := data.ResolveWithScenarioContext(body.Content) + framework.GetLogger(data.Namespace).Debug("httpPostRequestOnServiceWithPathAndBody", "service", serviceName, "path", path, "bodyMediaType", body.MediaType, "bodyContent", bodyContent) + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + requestInfo := framework.NewPOSTHTTPRequestInfo(uri, path, body.MediaType, bodyContent) + if success, err := framework.IsHTTPRequestSuccessful(data.Namespace, requestInfo); err != nil { + return err + } else if !success { + return fmt.Errorf("HTTP POST request to path %s was not successful", path) + } + return nil +} + +func (data *Data) httpPostRequestOnServiceUsingAccessTokenIsSuccessfulWithinMinutesWithPathAndBody(serviceName, token string, timeoutInMin int, path string, body *godog.DocString) error { + path = data.ResolveWithScenarioContext(path) + bodyContent := data.ResolveWithScenarioContext(body.Content) + token = data.ResolveWithScenarioContext(token) + framework.GetLogger(data.Namespace).Debug("httpPostRequestOnServiceUsingAccessTokenIsSuccessfulWithinMinutesWithPathAndBody", "service", serviceName, "token", token, "path", path, "bodyMediaType", body.MediaType, "bodyContent", bodyContent, "timeout", timeoutInMin) + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + requestInfo := framework.NewPOSTHTTPRequestInfo(uri, path, body.MediaType, bodyContent) + requestInfo.Token = token + return framework.WaitForSuccessfulHTTPRequest(data.Namespace, requestInfo, timeoutInMin) +} + +func (data *Data) httpPostRequestOnServiceIsSuccessfulWithinMinutesWithPathAndBody(serviceName string, timeoutInMin int, path string, body *godog.DocString) error { + path = data.ResolveWithScenarioContext(path) + bodyContent := data.ResolveWithScenarioContext(body.Content) + framework.GetLogger(data.Namespace).Debug("httpPostRequestOnServiceIsSuccessfulWithinMinutesWithPathAndBody", "service", serviceName, "path", path, "bodyMediaType", body.MediaType, "bodyContent", bodyContent, "timeout", timeoutInMin) + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + requestInfo := framework.NewPOSTHTTPRequestInfo(uri, path, body.MediaType, bodyContent) + return framework.WaitForSuccessfulHTTPRequest(data.Namespace, requestInfo, timeoutInMin) +} + +func (data *Data) httpPostRequestOnServiceIsSuccessfulWithinMinutesWithPathHeadersAndBody(serviceName string, timeoutInMin int, path, headersContent string, body *godog.DocString) error { + path = data.ResolveWithScenarioContext(path) + bodyContent := data.ResolveWithScenarioContext(body.Content) + framework.GetLogger(data.Namespace).Debug("httpPostRequestOnServiceIsSuccessfulWithinMinutesWithPathAndBody", "service", serviceName, "path", path, "bodyMediaType", body.MediaType, "bodyContent", bodyContent, "timeout", timeoutInMin) + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + headers, err := parseHeaders(headersContent) + if err != nil { + return err + } + + requestInfo := framework.NewPOSTHTTPRequestInfoWithHeaders(uri, path, headers, body.MediaType, bodyContent) + return framework.WaitForSuccessfulHTTPRequest(data.Namespace, requestInfo, timeoutInMin) +} + +func (data *Data) httpGetRequestOnServiceWithPathShouldReturnAnArrayofSizeWithinMinutes(serviceName, path string, size, timeoutInMin int) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + path = data.ResolveWithScenarioContext(path) + return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("GET request on path %s to return array of size %d", path, size), timeoutInMin, + func() (bool, error) { + requestInfo := framework.NewGETHTTPRequestInfo(uri, path) + return framework.IsHTTPResponseArraySize(data.Namespace, requestInfo, size) + }) +} + +func (data *Data) httpGetRequestOnServiceWithPathShouldContainAstringWithinMinutes(serviceName, path, responseContent string, timeoutInMin int) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + path = data.ResolveWithScenarioContext(path) + requestInfo := framework.NewGETHTTPRequestInfo(uri, path) + responseContent = data.ResolveWithScenarioContext(responseContent) + return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("GET request on path %s to return response content '%s'", path, responseContent), timeoutInMin, + func() (bool, error) { + return framework.DoesHTTPResponseContain(data.Namespace, requestInfo, responseContent) + }) +} + +func (data *Data) httpGetRequestOnServiceWithPathShouldNotContainAstringWithinMinutes(serviceName, path, responseContent string, timeoutInMin int) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + path = data.ResolveWithScenarioContext(path) + requestInfo := framework.NewGETHTTPRequestInfo(uri, path) + responseContent = data.ResolveWithScenarioContext(responseContent) + return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("GET request on path %s to not contain response content '%s'", path, responseContent), timeoutInMin, + func() (bool, error) { + return framework.DoesNotHTTPResponseContain(data.Namespace, requestInfo, responseContent) + }) +} + +func (data *Data) httpPostRequestsUsingThreadsOnServiceWithPathAndBody(requestCount, threadCount int, serviceName, path string, body *godog.DocString) error { + return executePostRequestsWithOptionalReportingUsingThreadsOnServiceWithPathAndBody(data, requestCount, threadCount, false, serviceName, path, body) +} + +func (data *Data) httpPostRequestsWithReportUsingThreadsOnServiceWithPathAndBody(requestCount, threadCount int, serviceName, path string, body *godog.DocString) error { + return executePostRequestsWithOptionalReportingUsingThreadsOnServiceWithPathAndBody(data, requestCount, threadCount, true, serviceName, path, body) +} + +func executePostRequestsWithOptionalReportingUsingThreadsOnServiceWithPathAndBody(data *Data, requestCount int, threadCount int, report bool, serviceName string, path string, body *godog.DocString) error { + path = data.ResolveWithScenarioContext(path) + bodyContent := data.ResolveWithScenarioContext(body.Content) + framework.GetLogger(data.Namespace).Info("httpPostRequestsUsingThreadsOnServiceWithPathAndBody", "requests", requestCount, "threads", threadCount, "report", report, "service", serviceName, "path", path, "bodyMediaType", body.MediaType, "bodyContent", bodyContent) + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + requestInfo := framework.NewPOSTHTTPRequestInfo(uri, path, body.MediaType, bodyContent) + + startTime := time.Now() + results, err := framework.ExecuteHTTPRequestsInThreads(data.Namespace, requestCount, threadCount, requestInfo) + duration := time.Since(startTime) + + if err != nil { + return err + } + + if report { + metricName := fmt.Sprintf("%s - %s - %d requests", data.Namespace, data.ScenarioName, requestCount) + framework.ReportPerformanceMetric(metricName, fmt.Sprintf("%.5f", duration.Seconds()), "s") + } + + for i := 0; i < threadCount; i++ { + if result := results[i]; result != framework.HTTPRequestResultSuccess { + return fmt.Errorf("One or more go routines have failed, see logs for more information") + } + } + return nil +} + +func parseHeaders(headersContent string) (map[string]string, error) { + headers := make(map[string]string) + + for _, headerEntry := range strings.Split(headersContent, ",") { + keyValuePair := strings.Split(headerEntry, "=") + + if len(keyValuePair) == 1 { + return nil, fmt.Errorf("Header key and value need to be separated by `=`, parsed header: %s", headerEntry) + } + if len(keyValuePair) > 2 { + return nil, fmt.Errorf("Found multiple `=` in parsed header: %s", headerEntry) + } + + headers[keyValuePair[0]] = keyValuePair[1] + } + + return headers, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/hyperfoil.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/hyperfoil.go new file mode 100644 index 00000000000..42a434e9bde --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/hyperfoil.go @@ -0,0 +1,178 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "errors" + "fmt" + + "github.com/cucumber/godog" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + hyperfoilv1alpha2 "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/installers" +) + +const ( + hyperfoilRunContextKey = "hyperfoil-run" +) + +func registerHyperfoilSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Hyperfoil Operator is deployed$`, data.hyperfoilOperatorIsDeployed) + ctx.Step(`^Hyperfoil instance "([^"]*)" is deployed within (\d+) (?:minute|minutes)$`, data.hyperfoilInstanceIsDeployedWithinMinutes) + + ctx.Step(`^Hyperfoil Node scraper is deployed$`, data.hyperfoilNodeScraperIsDeployed) + + ctx.Step(`^Create benchmark on Hyperfoil instance "([^"]*)" within (\d+) (?:minute|minutes) with content:$`, data.createBenchmarkOnHyperfoilInstanceWithinMinutesWithBody) + ctx.Step(`^Start benchmark "([^"]*)" on Hyperfoil instance "([^"]*)" within (\d+) (?:minute|minutes)$`, data.startBenchmarkOnHyperfoilInstanceWithinMinutes) + ctx.Step(`^Benchmark run on Hyperfoil instance "([^"]*)" finished within (\d+) (?:minute|minutes)$`, data.benchmarkRunOnHyperfoilInstanceFinishedWithinMinutes) + ctx.Step(`^Store benchmark statistics of Hyperfoil instance "([^"]*)" as "([^"]*)"$`, data.storeBenchmarkStatisticsOfHyperfoilInstance) +} + +func (data *Data) hyperfoilOperatorIsDeployed() error { + return installers.GetHyperfoilInstaller().Install(data.Namespace) +} + +func (data *Data) hyperfoilNodeScraperIsDeployed() error { + return installers.GetHyperfoilNodeScraperInstaller().Install(data.Namespace) +} + +func (data *Data) hyperfoilInstanceIsDeployedWithinMinutes(name string, timeOutInMin int) error { + hyperfoil := getHyperfoilDefaultResource(name, data.Namespace) + + framework.GetLogger(data.Namespace).Info("Creating Hyperfoil instance", "name", hyperfoil.Name) + if err := framework.CreateObject(hyperfoil); err != nil { + return err + } + + return framework.WaitForPodsWithLabel(data.Namespace, "role", "controller", 1, 5) +} + +func (data *Data) createBenchmarkOnHyperfoilInstanceWithinMinutesWithBody(hyperfoilName string, timeOutInMin int, body *godog.DocString) error { + return data.httpPostRequestOnServiceIsSuccessfulWithinMinutesWithPathAndBody(hyperfoilName, timeOutInMin, "benchmark", body) +} + +func (data *Data) startBenchmarkOnHyperfoilInstanceWithinMinutes(benchmarkName, hyperfoilName string, timeOutInMin int) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, hyperfoilName) + if err != nil { + return err + } + + run := &HyperfoilRun{} + // Yes, GET request actually triggers benchmark run + requestInfo := framework.NewGETHTTPRequestInfo(uri, fmt.Sprintf("benchmark/%s/start", benchmarkName)) + return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("HTTP %s request on path '%s' to be successful", requestInfo.HTTPMethod, requestInfo.Path), timeOutInMin, + func() (bool, error) { + err := framework.ExecuteHTTPRequestWithUnmarshalledResponse(data.Namespace, requestInfo, run) + if err != nil { + return false, err + } + if run != nil { + // Persist run ID into context, it is expected that one scenario run will operate on one Hyperfoil run + data.ScenarioContext[hyperfoilRunContextKey] = run.ID + return true, nil + } + return false, err + }) +} + +func (data *Data) benchmarkRunOnHyperfoilInstanceFinishedWithinMinutes(hyperfoilName string, timeOutInMin int) error { + runID := data.ScenarioContext[hyperfoilRunContextKey] + if len(runID) == 0 { + return errors.New("Hyperfoil run ID not found. Did you start the benchmark?") + } + + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, hyperfoilName) + if err != nil { + return err + } + + run := &HyperfoilRun{} + requestInfo := framework.NewGETHTTPRequestInfo(uri, fmt.Sprintf("run/%s", runID)) + return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("HTTP %s request on path '%s' to be successful", requestInfo.HTTPMethod, requestInfo.Path), timeOutInMin, + func() (bool, error) { + err := framework.ExecuteHTTPRequestWithUnmarshalledResponse(data.Namespace, requestInfo, run) + if err != nil { + return false, err + } + if run != nil && run.Completed { + return true, nil + } + return false, err + }) +} + +func (data *Data) storeBenchmarkStatisticsOfHyperfoilInstance(hyperfoilName, benchmarkFileName string) error { + runID := data.ScenarioContext[hyperfoilRunContextKey] + if len(runID) == 0 { + return errors.New("Hyperfoil run ID not found. Did you start the benchmark?") + } + + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, hyperfoilName) + if err != nil { + return err + } + requestInfo := framework.NewGETHTTPRequestInfo(uri, fmt.Sprintf("run/%s/stats/all/json", runID)) + stats, err := framework.ExecuteHTTPRequestWithStringResponse(data.Namespace, requestInfo) + if err != nil { + return err + } + + err = framework.CreateFile(config.GetHyperfoilOutputDirectory(), benchmarkFileName, stats) + return err +} + +func getHyperfoilDefaultResource(name, namespace string) *hyperfoilv1alpha2.Hyperfoil { + hyperfoil := &hyperfoilv1alpha2.Hyperfoil{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: hyperfoilv1alpha2.HyperfoilSpec{ + PreHooks: []string{}, + PostHooks: []string{}, + }, + } + if exists, err := framework.IsConfigMapExist(types.NamespacedName{Namespace: namespace, Name: installers.NodeScraperStartConfigMapName}); err != nil { + framework.GetLogger(namespace).Error(err, "Cannot fetch ConfigMap", "name", name, "namespace", namespace) + } else if exists { + hyperfoil.Spec.PreHooks = append(hyperfoil.Spec.PreHooks, installers.NodeScraperStartConfigMapName) + } + if exists, err := framework.IsConfigMapExist(types.NamespacedName{Namespace: namespace, Name: installers.NodeScraperStopConfigMapName}); err != nil { + framework.GetLogger(namespace).Error(err, "Cannot fetch ConfigMap", "name", name, "namespace", namespace) + } else if exists { + hyperfoil.Spec.PostHooks = append(hyperfoil.Spec.PostHooks, installers.NodeScraperStopConfigMapName) + } + + if imageVersion := config.GetHyperfoilControllerImageVersion(); len(imageVersion) > 0 { + hyperfoil.Spec.Version = imageVersion + } + + return hyperfoil +} + +// HyperfoilRun represents informations about the Hyperfoil run +type HyperfoilRun struct { + ID string `json:"id"` + Completed bool `json:"completed"` +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/image_registry.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/image_registry.go new file mode 100644 index 00000000000..44f22870e50 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/image_registry.go @@ -0,0 +1,219 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "errors" + "fmt" + "path/filepath" + "sort" + "strings" + + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers" +) + +/* + DataTable for Maven: + | profile | profile | + | profile | profile2 | + | option | -Doption=true | + | option | -Doption2=true | + | native | enabled | +*/ + +const ( + builtTagsLogFile = "logs/built_images.log" + builtProjectImageNamesLogFile = "logs/built_project_image_names.log" +) + +// registerImageRegistrySteps register all existing image registry steps +func registerImageRegistrySteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step("^"+DefaultMavenBuiltExampleRegex+" and deployed to runtime registry$", data.localServiceBuiltByMavenAndDeployedToRuntimeRegistry) + ctx.Step("^"+DefaultMavenBuiltExampleRegex+" and deployed to runtime registry with Maven configuration:$", data.localServiceBuiltByMavenWithProfileAndDeployedToRuntimeRegistryWithMavenConfiguration) +} + +// Build local service and deploy it to registry if the registry doesn't contain such image already +func (data *Data) localServiceBuiltByMavenAndDeployedToRuntimeRegistry(contextDir string) error { + return data.localServiceBuiltByMavenWithProfileAndDeployedToRuntimeRegistryWithMavenConfiguration(contextDir, nil) +} + +// Build local service and deploy it to registry if the registry doesn't contain such image already +func (data *Data) localServiceBuiltByMavenWithProfileAndDeployedToRuntimeRegistryWithMavenConfiguration(contextDir string, table *godog.Table) error { + mavenConfig := &mappers.MavenCommandConfig{} + if table != nil && len(table.Rows) > 0 { + err := mappers.MapMavenCommandConfigTable(table, mavenConfig) + if err != nil { + return err + } + } + + projectLocation := data.KogitoExamplesLocation + "/" + contextDir + + projectImageName := getProjectImageName(projectLocation, mavenConfig) + runtimeApplicationImageTag, err := getRuntimeApplicationImageTag(projectImageName) + if err != nil { + return err + } + + if needToBuildImage(data.Namespace, runtimeApplicationImageTag) { + // Not found in registry, so we need to build and push the application + // Build the application + err = data.localServiceBuiltByMavenWithProfileAndOptions(contextDir, mavenConfig) + if err != nil { + return err + } + + // Create Dockerfile + dockerfileContent, err := framework.GetKogitoApplicationDockerfileProvider(projectLocation).GetDockerfileContent() + if err != nil { + return err + } + + if err := framework.CreateFile(projectLocation, "Dockerfile", dockerfileContent); err != nil { + return err + } + + // Build and push image + err = framework.GetContainerEngine(data.Namespace).BuildImage(projectLocation, runtimeApplicationImageTag).PushImage(runtimeApplicationImageTag).GetError() + if err != nil { + return err + } + + //Delete Dockerfile + err = framework.DeleteFile(projectLocation, "Dockerfile") + if err != nil { + return err + } + + onImageBuiltPostCreated(data.Namespace, projectImageName, runtimeApplicationImageTag) + } else { + framework.GetLogger(data.Namespace).Info("Using cached Kogito image", "imageTag", runtimeApplicationImageTag) + } + + // Store image tag into scenario context + kogitoApplicationName := filepath.Base(projectLocation) + data.ScenarioContext[GetBuiltRuntimeImageTagContextKey(kogitoApplicationName)] = runtimeApplicationImageTag + + return nil +} + +// Returns true if the image has to be built +func needToBuildImage(namespace, imageTag string) bool { + switch config.GetImageCacheMode() { + case config.UseImageCacheAlways: + return false + case config.UseImageCacheNever: + return true + case config.UseImageCacheIfAvailable: + { + // Check if image is available in registry, error means it is not available + err := framework.GetContainerEngine(namespace).PullImage(imageTag).GetError() + return err != nil + } + } + return true +} + +// Returns complete Kogito image tag, registry and namespace is retrieved from test configuration +func getRuntimeApplicationImageTag(projectImageName string) (string, error) { + runtimeApplicationImageRegistry := config.GetRuntimeApplicationImageRegistry() + if len(runtimeApplicationImageRegistry) == 0 { + return "", errors.New("Runtime application image registry must be set to build the image") + } + + runtimeApplicationImageName := getRuntimeApplicationImageName(projectImageName) + + runtimeApplicationImageVersion := config.GetRuntimeApplicationImageVersion() + if len(runtimeApplicationImageVersion) == 0 { + runtimeApplicationImageVersion = "latest" + } + + buildImageTag := fmt.Sprintf("%s/%s:%s", runtimeApplicationImageRegistry, runtimeApplicationImageName, runtimeApplicationImageVersion) + return buildImageTag, nil +} + +// Retrieve the image name from project, based from test configuration +func getRuntimeApplicationImageName(projectImageName string) string { + var runtimeApplicationImageNameParts []string + + if runtimeApplicationImageNamePrefix := config.GetRuntimeApplicationImageNamePrefix(); len(runtimeApplicationImageNamePrefix) > 0 { + runtimeApplicationImageNameParts = append(runtimeApplicationImageNameParts, runtimeApplicationImageNamePrefix) + } + + runtimeApplicationImageNameParts = append(runtimeApplicationImageNameParts, projectImageName) + + if runtimeApplicationImageNameSuffix := config.GetRuntimeApplicationImageNameSuffix(); len(runtimeApplicationImageNameSuffix) > 0 { + runtimeApplicationImageNameParts = append(runtimeApplicationImageNameParts, runtimeApplicationImageNameSuffix) + } + + return strings.Join(runtimeApplicationImageNameParts, "-") +} + +// Returns project image name in the form of "(-)*(-)*" +func getProjectImageName(projectLocation string, mavenConfig *mappers.MavenCommandConfig) string { + var projectImageNameParts []string + + projectImageBaseName := filepath.Base(projectLocation) + projectImageNameParts = append(projectImageNameParts, projectImageBaseName) + + if len(mavenConfig.Profiles) > 0 { + // Sort profiles to generate consistent image name + sort.Strings(mavenConfig.Profiles) + projectImageNameParts = append(projectImageNameParts, mavenConfig.Profiles...) + } + + if mavenConfig.Native { + projectImageNameParts = append(projectImageNameParts, nativeProfile) + } + + if len(mavenConfig.Options) > 0 { + // Sanitize mavenOptions so they can be used in the image name + var sanitizedMavenOptions []string + for _, option := range mavenConfig.Options { + option = strings.ReplaceAll(option, "=", "-") + option = strings.ToLower(option) + sanitizedMavenOptions = append(sanitizedMavenOptions, option) + } + // Sort mavenOptions to generate consistent image name + sort.Strings(sanitizedMavenOptions) + + projectImageNameParts = append(projectImageNameParts, sanitizedMavenOptions...) + } + + return strings.Join(projectImageNameParts, "-") +} + +// GetBuiltRuntimeImageTagContextKey Returns context tag used to store built runtime image tag +func GetBuiltRuntimeImageTagContextKey(kogitoApplicationName string) string { + return fmt.Sprintf("built-image-%s", kogitoApplicationName) +} + +func onImageBuiltPostCreated(namespace, projectImageName, runtimeApplicationImageTag string) { + if err := framework.AddLineToFile(projectImageName, builtProjectImageNamesLogFile); err != nil { + framework.GetLogger(namespace).Warn("Error updating built project image names", "error", err) + } + if err := framework.AddLineToFile(runtimeApplicationImageTag, builtTagsLogFile); err != nil { + framework.GetLogger(namespace).Warn("Error updating built image tags", "error", err) + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/infinispan.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/infinispan.go new file mode 100644 index 00000000000..6de26639169 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/infinispan.go @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + infinispan "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1" + + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/installers" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers" +) + +/* + DataTable for Infinispan: + | username | developer | + | password | mypass | +*/ + +const ( + externalInfinispanSecret = "external-infinispan-secret" +) + +var performanceInfinispanContainerSpec = infinispan.InfinispanContainerSpec{ + ExtraJvmOpts: "-Xmx2G", + Memory: "3Gi", + CPU: "1", +} + +func registerInfinispanSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Infinispan Operator is deployed$`, data.infinispanOperatorIsDeployed) + ctx.Step(`^Infinispan instance "([^"]*)" has (\d+) (?:pod|pods) running within (\d+) (?:minute|minutes)$`, data.infinispanInstanceHasPodsRunningWithinMinutes) + ctx.Step(`^Infinispan instance "([^"]*)" is deployed with configuration:$`, data.infinispanInstanceIsDeployedWithConfiguration) + ctx.Step(`^Infinispan instance "([^"]*)" is deployed for performance within (\d+) minute\(s\) with configuration:$`, data.infinispanInstanceIsDeployedForPerformanceWithinMinutesWithConfiguration) + ctx.Step(`^Scale Infinispan instance "([^"]*)" to (\d+) pods within (\d+) minutes$`, data.scaleInfinispanInstanceToPodsWithinMinutes) +} + +func (data *Data) infinispanOperatorIsDeployed() error { + installer, err := installers.GetInfinispanInstaller() + if err != nil { + return err + } + return installer.Install(data.Namespace) +} + +func (data *Data) infinispanInstanceHasPodsRunningWithinMinutes(name string, numberOfPods, timeOutInMin int) error { + return framework.WaitForPodsWithLabels(data.Namespace, framework.GetRunningInfinispanPodLabels(name), numberOfPods, timeOutInMin) +} + +func (data *Data) infinispanInstanceIsDeployedWithConfiguration(name string, table *godog.Table) error { + if err := createInfinispanSecret(data.Namespace, externalInfinispanSecret, table); err != nil { + return err + } + + infinispan := framework.GetInfinispanStub(data.Namespace, name, externalInfinispanSecret) + + if err := framework.DeployInfinispanInstance(data.Namespace, infinispan); err != nil { + return err + } + + return framework.WaitForPodsWithLabels(data.Namespace, framework.GetRunningInfinispanPodLabels(name), 1, 3) +} + +func (data *Data) infinispanInstanceIsDeployedForPerformanceWithinMinutesWithConfiguration(name string, timeOutInMin int, table *godog.Table) error { + if err := createInfinispanSecret(data.Namespace, externalInfinispanSecret, table); err != nil { + return err + } + + infinispan := framework.GetInfinispanStub(data.Namespace, name, externalInfinispanSecret) + // Add performance-specific container spec + infinispan.Spec.Container = performanceInfinispanContainerSpec + + if err := framework.DeployInfinispanInstance(data.Namespace, infinispan); err != nil { + return err + } + + return framework.WaitForInfinispanPodsToBeRunningWithConfig(data.Namespace, performanceInfinispanContainerSpec, 1, timeOutInMin) +} + +func (data *Data) scaleInfinispanInstanceToPodsWithinMinutes(name string, nbPods, timeoutInMin int) error { + err := framework.SetInfinispanReplicas(data.Namespace, name, nbPods) + if err != nil { + return err + } + return framework.WaitForPodsWithLabels(data.Namespace, framework.GetRunningInfinispanPodLabels(name), nbPods, timeoutInMin) +} + +// Misc methods + +func createInfinispanSecret(namespace, secretName string, table *godog.Table) error { + credentials := make(map[string]string) + credentials["operator"] = "supersecretoperatorpassword" // Credentials required by Infinispan operator + + if username, password, err := mappers.MapInfinispanCredentialsFromTable(table); err != nil { + return err + } else if len(username) > 0 { + // User defined credentials + credentials[username] = password + } + + return framework.CreateInfinispanSecret(namespace, secretName, credentials) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/kafka.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/kafka.go new file mode 100644 index 00000000000..85492483a4c --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/kafka.go @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/installers" +) + +func registerKafkaSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Kafka Operator is deployed$`, data.kafkaOperatorIsDeployed) + ctx.Step(`^Kafka instance "([^"]*)" has (\d+) (?:pod|pods) running within (\d+) (?:minute|minutes)$`, data.kafkaInstanceHasPodsRunningWithinMinutes) + ctx.Step(`^Kafka instance "([^"]*)" has (\d+) kafka (?:pod|pods) running within (\d+) (?:minute|minutes)$`, data.kafkaInstanceHasKafkaPodsRunningWithinMinutes) + ctx.Step(`^Kafka instance "([^"]*)" is deployed$`, data.kafkaInstanceIsDeployed) + ctx.Step(`^Scale Kafka instance "([^"]*)" down`, data.scaleKafkaInstanceDown) + ctx.Step(`^Kafka topic "([^"]*)" is deployed$`, data.kafkaTopicIsDeployed) + ctx.Step(`^Kafka instance "([^"]*)" should contain at least (\d+) (?:message|messages) on topic "([^"]*)" within (\d+) (?:minute|minutes)$`, data.kafkaInstanceShouldContainAtLeastMessagesOnTopicWithinMinutes) +} + +func (data *Data) kafkaOperatorIsDeployed() error { + if config.UseProductOperator() { + return installers.GetAmqStreamsInstaller().Install(data.Namespace) + } + return installers.GetKafkaInstaller().Install(data.Namespace) +} + +func (data *Data) kafkaInstanceHasPodsRunningWithinMinutes(name string, numberOfPods, timeOutInMin int) error { + return framework.WaitForPodsWithLabel(data.Namespace, "strimzi.io/name", name+"-entity-operator", numberOfPods, timeOutInMin) +} + +func (data *Data) kafkaInstanceHasKafkaPodsRunningWithinMinutes(name string, numberOfPods, timeOutInMin int) error { + return framework.WaitForPodsWithLabel(data.Namespace, "strimzi.io/name", name+"-kafka", numberOfPods, timeOutInMin) +} + +func (data *Data) kafkaInstanceIsDeployed(name string) error { + kafka := getKafkaDefaultResource(name, data.Namespace) + + if err := framework.DeployKafkaInstance(data.Namespace, kafka); err != nil { + return err + } + + return framework.WaitForPodsWithLabel(data.Namespace, "strimzi.io/name", name+"-entity-operator", 1, 5) +} + +func (data *Data) scaleKafkaInstanceDown(name string) error { + return framework.ScaleKafkaInstanceDown(data.Namespace, name) +} + +func (data *Data) kafkaTopicIsDeployed(name string) error { + return framework.DeployKafkaTopic(data.Namespace, name, infrastructure.KafkaInstanceName) +} + +func (data *Data) kafkaInstanceShouldContainAtLeastMessagesOnTopicWithinMinutes(instanceName string, numberOfMsg int, topic string, timeoutInMinutes int) error { + return framework.WaitForMessagesOnTopic(data.Namespace, instanceName, topic, numberOfMsg, timeoutInMinutes) +} + +func getKafkaDefaultResource(name, namespace string) *v1beta2.Kafka { + return &v1beta2.Kafka{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: v1beta2.KafkaSpec{ + EntityOperator: v1beta2.EntityOperatorSpec{ + TopicOperator: v1beta2.EntityTopicOperatorSpec{}, + UserOperator: v1beta2.EntityUserOperatorSpec{}, + }, + Kafka: v1beta2.KafkaClusterSpec{ + Replicas: 1, + Storage: v1beta2.KafkaStorage{StorageType: v1beta2.KafkaEphemeralStorage}, + Listeners: []v1beta2.GenericKafkaListener{ + { + Name: "plain", + Port: 9092, + TLS: false, + ListenerType: "internal", + }, + { + Name: "tls", + Port: 9093, + TLS: true, + ListenerType: "internal", + }, + }, + JvmOptions: map[string]interface{}{"gcLoggingEnabled": false}, + Config: map[string]interface{}{ + "log.message.format.version": "2.3", + "offsets.topic.replication.factor": 1, + "transaction.state.log.min.isr": 1, + "transaction.state.log.replication.factor": 1, + "auto.create.topics.enable": true, + }, + }, + Zookeeper: v1beta2.ZookeeperClusterSpec{ + Replicas: 1, + Storage: v1beta2.KafkaStorage{StorageType: v1beta2.KafkaEphemeralStorage}, + }, + }, + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/keycloak.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/keycloak.go new file mode 100644 index 00000000000..68ad5f2e3a1 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/keycloak.go @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/installers" +) + +func registerKeycloakSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Keycloak Operator is deployed$`, data.keycloakOperatorIsDeployed) + ctx.Step(`^Keycloak instance is deployed$`, data.keycloakInstanceIsDeployed) + ctx.Step(`^Keycloak instance with realm "([^"]*)" and client "([^"]*)" is deployed$`, data.keycloakInstanceWithRealmAndClientIsDeployed) + ctx.Step(`^Keycloak realm "([^"]*)" is deployed$`, data.keycloakRealmIsDeployed) + ctx.Step(`^Keycloak client "([^"]*)" is deployed$`, data.keycloakClientIsDeployed) + ctx.Step(`^Keycloak user "([^"]*)" with password "([^"]*)" is deployed$`, data.keycloakUserWithPasswordIsDeployed) + + ctx.Step(`^Stores access token for user "([^"]*)" and password "([^"]*)" on realm "([^"]*)" and client "([^"]*)" into variable "([^"]*)"$`, data.storesAccessTokenForUserAndPasswordOnRealmAndClientIntoVariable) +} + +func (data *Data) keycloakOperatorIsDeployed() error { + return installers.GetKeycloakInstaller().Install(data.Namespace) +} + +func (data *Data) keycloakInstanceIsDeployed() error { + return framework.DeployKeycloakInstance(data.Namespace) +} + +func (data *Data) keycloakInstanceWithRealmAndClientIsDeployed(realm, clientName string) error { + if err := data.keycloakInstanceIsDeployed(); err != nil { + return err + } + + if err := data.keycloakRealmIsDeployed(realm); err != nil { + return err + } + + return data.keycloakClientIsDeployed(clientName) +} + +func (data *Data) keycloakRealmIsDeployed(realm string) error { + return framework.DeployKeycloakRealm(data.Namespace, realm) +} + +func (data *Data) keycloakClientIsDeployed(clientName string) error { + return framework.DeployKeycloakClient(data.Namespace, clientName) +} + +func (data *Data) keycloakUserWithPasswordIsDeployed(userName, password string) error { + return framework.DeployKeycloakUser(data.Namespace, userName, password) +} + +func (data *Data) storesAccessTokenForUserAndPasswordOnRealmAndClientIntoVariable(userName, password, realm, clientName, contextKey string) error { + uri, err := framework.RetrieveKeycloakEndpointURI(data.Namespace) + if err != nil { + return err + } + + accessToken, err := framework.GetAccessTokenFromKeycloak(data.Namespace, uri, userName, password, realm, clientName) + if err != nil { + return err + } + + data.ScenarioContext[contextKey] = accessToken + + return nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/knative-eventing-kogito.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/knative-eventing-kogito.go new file mode 100644 index 00000000000..9a4cc782c6a --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/knative-eventing-kogito.go @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "fmt" + + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/installers" +) + +func registerKnativeEventingKogitoSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Install Knative eventing KogitoSource$`, data.installKnativeEventingKogitoSource) + ctx.Step(`^Create (quarkus|springboot) KogitoSource "([^"]*)" sinking events to Broker "([^"]*)" from runtime registry$`, data.createKogitoSource) +} + +func (data *Data) installKnativeEventingKogitoSource() error { + return installers.GetKnativeEventingKogitoInstaller().Install(data.Namespace) +} + +func (data *Data) createKogitoSource(runtimeType, kogitoSourceName, brokerName string) error { + imageTag := data.ScenarioContext[GetBuiltRuntimeImageTagContextKey(kogitoSourceName)] + + // TODO: Quick workaround, needs to be refactored once KogitoSource API is moved to separate module + kogitoSourceContent := `apiVersion: kogito.knative.dev/v1alpha1 +kind: KogitoSource +metadata: + name: process-knative-quickstart-quarkus +spec: + image: %s + sink: + ref: + apiVersion: eventing.knative.dev/v1 + kind: Broker + name: default` + + filteredKogitoSourceContent := fmt.Sprintf(kogitoSourceContent, imageTag) + tempFilePath, err := framework.CreateTemporaryFile("kogito-source*.yaml", filteredKogitoSourceContent) + if err != nil { + return err + } + output, err := framework.CreateCommand("oc", "apply", "-n", data.Namespace, "-f", tempFilePath).Execute() + if err != nil { + framework.GetMainLogger().Error(err, fmt.Sprintf("Applying KogitoSource failed, output: %s", output)) + } + + return err +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/knative.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/knative.go new file mode 100644 index 00000000000..8688f76b7e5 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/knative.go @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/installers" +) + +func registerKnativeSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Install Knative eventing$`, data.installKnativeEventing) + ctx.Step(`^Deploy Knative Broker "([^"]*)"$`, data.deployKnativeBroker) + ctx.Step(`^Create Knative Trigger "([^"]*)" receiving events from Broker "([^"]*)" delivering to Service "([^"]*)"$`, data.createKnativeTrigger) + ctx.Step(`^Deploy Event display "([^"]*)"$`, data.deployEventDisplay) +} + +func (data *Data) installKnativeEventing() error { + return installers.GetKnativeEventingInstaller().Install(data.Namespace) +} + +func (data *Data) deployKnativeBroker(name string) error { + if err := framework.DeployBroker(data.Namespace, name); err != nil { + return err + } + + return framework.WaitForBrokerResource(data.Namespace, name, 3) +} + +func (data *Data) createKnativeTrigger(name, brokerName, serviceName string) error { + if err := framework.CreateTrigger(data.Namespace, name, brokerName, serviceName); err != nil { + return err + } + + return framework.WaitForTrigger(data.Namespace, name, 3) +} + +func (data *Data) deployEventDisplay(name string) error { + deployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: data.Namespace, + }, + Spec: appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": name}}, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{"app": name}, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: name, + Image: "gcr.io/knative-releases/knative.dev/eventing-contrib/cmd/event_display", + }, + }, + }, + }, + }, + } + + if err := framework.CreateObject(deployment); err != nil { + return err + } + + service := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: data.Namespace, + }, + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + { + Protocol: "TCP", + Port: 80, + TargetPort: intstr.FromInt(8080), + }, + }, + Selector: deployment.Spec.Selector.MatchLabels, + }, + } + + if err := framework.CreateObject(service); err != nil { + return err + } + return framework.WaitForPodsWithLabel(data.Namespace, "app", name, 1, 3) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/kogitodataindex.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/kogitodataindex.go new file mode 100644 index 00000000000..840f8736c67 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/kogitodataindex.go @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers" + bddtypes "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/types" +) + +/* + DataTable for Data Index: + | config | database | | + | config | infra | | + | runtime-request | cpu/memory | value | + | runtime-limit | cpu/memory | value | + | runtime-env | varName | varValue | +*/ + +func registerKogitoDataIndexServiceSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Install Kogito Data Index with (\d+) replicas$`, data.installKogitoDataIndexServiceWithReplicas) + ctx.Step(`^Install Kogito Data Index with (\d+) replicas with configuration:$`, data.installKogitoDataIndexServiceWithReplicasWithConfiguration) + ctx.Step(`^Kogito Data Index has (\d+) pods running within (\d+) minutes$`, data.kogitoDataIndexHasPodsRunningWithinMinutes) +} + +func (data *Data) installKogitoDataIndexServiceWithReplicas(replicas int) error { + dataIndex := framework.GetKogitoDataIndexResourceStub(data.Namespace, replicas) + return framework.InstallKogitoDataIndexService(data.Namespace, framework.GetDefaultInstallerType(), &bddtypes.KogitoServiceHolder{KogitoService: dataIndex}) +} + +func (data *Data) installKogitoDataIndexServiceWithReplicasWithConfiguration(replicas int, table *godog.Table) error { + dataIndex := &bddtypes.KogitoServiceHolder{ + KogitoService: framework.GetKogitoDataIndexResourceStub(data.Namespace, replicas), + } + + if err := mappers.MapKogitoServiceTable(table, dataIndex); err != nil { + return err + } + if dataIndex.DatabaseType == infrastructure.MongoDBKind { + framework.GetMainLogger().Debug("Setting Data Index MongoDB image") + dataIndex.KogitoService.GetSpec().SetImage(framework.NewImageOrDefault(config.GetServiceImageTag(config.DataIndexImageType, config.MongoDBPersistenceType), framework.DataIndexMongoDBImageName)) + } else if dataIndex.DatabaseType == "PostgreSQL" { + framework.GetMainLogger().Debug("Setting Data Index PostgreSQL image") + dataIndex.KogitoService.GetSpec().SetImage(framework.NewImageOrDefault(config.GetServiceImageTag(config.DataIndexImageType, config.PosgresqlPersistenceType), framework.DataIndexPostgresqlImageName)) + } + + return framework.InstallKogitoDataIndexService(data.Namespace, framework.GetDefaultInstallerType(), dataIndex) +} + +func (data *Data) kogitoDataIndexHasPodsRunningWithinMinutes(podNb, timeoutInMin int) error { + return framework.WaitForKogitoDataIndexService(data.Namespace, podNb, timeoutInMin) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/kogitojobsservice.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/kogitojobsservice.go new file mode 100644 index 00000000000..0c13c947668 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/kogitojobsservice.go @@ -0,0 +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. + */ + +package steps + +import ( + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers" + bddtypes "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/types" +) + +/* + DataTable for Jobs Service: + | config | infra | | + | runtime-request | cpu/memory | value | + | runtime-limit | cpu/memory | value | + | runtime-env | varName | varValue | +*/ + +func registerKogitoJobsServiceSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Install Kogito Jobs Service with (\d+) replicas$`, data.installKogitoJobsServiceWithReplicas) + ctx.Step(`^Install Kogito Jobs Service with (\d+) replicas with configuration:$`, data.installKogitoJobsServiceWithReplicasWithConfiguration) + ctx.Step(`^Kogito Jobs Service has (\d+) pods running within (\d+) minutes$`, data.kogitoJobsServiceHasPodsRunningWithinMinutes) + ctx.Step(`^Scale Kogito Jobs Service to (\d+) pods within (\d+) minutes$`, data.scaleKogitoJobsServiceToPodsWithinMinutes) + ctx.Step(`^Kogito Jobs Service log contains text "([^"]*)" within (\d+) minutes$`, data.kogitoJobsServiceLogContainsTextWithinMinutes) +} + +func (data *Data) installKogitoJobsServiceWithReplicas(replicas int) error { + jobsService := framework.GetKogitoJobsServiceResourceStub(data.Namespace, replicas) + return framework.InstallKogitoJobsService(framework.GetDefaultInstallerType(), &bddtypes.KogitoServiceHolder{KogitoService: jobsService}) +} + +func (data *Data) installKogitoJobsServiceWithReplicasWithConfiguration(replicas int, table *godog.Table) error { + jobsService := &bddtypes.KogitoServiceHolder{ + KogitoService: framework.GetKogitoJobsServiceResourceStub(data.Namespace, replicas), + } + + if err := mappers.MapKogitoServiceTable(table, jobsService); err != nil { + return err + } + if jobsService.DatabaseType == infrastructure.InfinispanKind { + framework.GetMainLogger().Debug("Setting Jobs service Infinispan image") + jobsService.KogitoService.GetSpec().SetImage(framework.NewImageOrDefault(config.GetServiceImageTag(config.JobServiceImageType, config.InfinispanPersistenceType), framework.JobsServiceInfinispanImageName)) + } else if jobsService.DatabaseType == infrastructure.MongoDBKind { + framework.GetMainLogger().Debug("Setting Jobs service MongoDB image") + jobsService.KogitoService.GetSpec().SetImage(framework.NewImageOrDefault(config.GetServiceImageTag(config.JobServiceImageType, config.MongoDBPersistenceType), framework.JobsServiceMongoDBImageName)) + } else if jobsService.DatabaseType == "PostgreSQL" { + framework.GetMainLogger().Debug("Setting Jobs service PostgreSQL image") + jobsService.KogitoService.GetSpec().SetImage(framework.NewImageOrDefault(config.GetServiceImageTag(config.JobServiceImageType, config.PosgresqlPersistenceType), framework.JobsServicePostgresqlImageName)) + } + + return framework.InstallKogitoJobsService(framework.GetDefaultInstallerType(), jobsService) +} + +func (data *Data) kogitoJobsServiceHasPodsRunningWithinMinutes(pods, timeoutInMin int) error { + return framework.WaitForKogitoJobsService(data.Namespace, pods, timeoutInMin) +} + +func (data *Data) scaleKogitoJobsServiceToPodsWithinMinutes(nbPods, timeoutInMin int) error { + err := framework.SetKogitoJobsServiceReplicas(data.Namespace, int32(nbPods)) + if err != nil { + return err + } + return framework.WaitForKogitoJobsService(data.Namespace, nbPods, timeoutInMin) +} + +func (data *Data) kogitoJobsServiceLogContainsTextWithinMinutes(logText string, timeoutInMin int) error { + return framework.WaitForKogitoJobsServiceLogContainsTextWithinMinutes(data.Namespace, logText, timeoutInMin) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/kogitomgmtconsole.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/kogitomgmtconsole.go new file mode 100644 index 00000000000..e169016fb91 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/kogitomgmtconsole.go @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers" + bddtypes "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/types" +) + +/* + DataTable for Management console: + | config | infra | | + | runtime-request | cpu/memory | value | + | runtime-limit | cpu/memory | value | + | runtime-env | varName | varValue | +*/ + +// RegisterCliSteps register all CLI steps existing +func registerKogitoManagementConsoleSteps(s *godog.ScenarioContext, data *Data) { + s.Step(`^Install Kogito Management Console with (\d+) replicas$`, data.installKogitoManagementConsoleWithReplicas) + s.Step(`^Install Kogito Management Console with (\d+) replicas with configuration:$`, data.installKogitoManagementConsoleWithReplicasWithConfiguration) + s.Step(`^Kogito Management Console has (\d+) pods running within (\d+) minutes$`, data.kogitoManagementConsoleHasPodsRunningWithinMinutes) +} + +func (data *Data) installKogitoManagementConsoleWithReplicas(replicas int) error { + managementConsole := &bddtypes.KogitoServiceHolder{ + KogitoService: framework.GetKogitoManagementConsoleResourceStub(data.Namespace, replicas), + } + + // Can be removed once https://issues.redhat.com/browse/KOGITO-1141 is implemented + if !framework.IsOpenshift() { + if err := addIngressURIEnvVariableToManagementConsole(data.Namespace, managementConsole); err != nil { + return err + } + } + + return framework.InstallKogitoManagementConsole(framework.GetDefaultInstallerType(), managementConsole) +} + +func (data *Data) installKogitoManagementConsoleWithReplicasWithConfiguration(replicas int, table *godog.Table) error { + managementConsole := &bddtypes.KogitoServiceHolder{ + KogitoService: framework.GetKogitoManagementConsoleResourceStub(data.Namespace, replicas), + } + + if err := mappers.MapKogitoServiceTable(table, managementConsole); err != nil { + return err + } + + // Can be removed once https://issues.redhat.com/browse/KOGITO-1141 is implemented + if !framework.IsOpenshift() { + if err := addIngressURIEnvVariableToManagementConsole(data.Namespace, managementConsole); err != nil { + return err + } + } + + return framework.InstallKogitoManagementConsole(framework.GetDefaultInstallerType(), managementConsole) +} + +func (data *Data) kogitoManagementConsoleHasPodsRunningWithinMinutes(pods, timeoutInMin int) error { + return framework.WaitForKogitoManagementConsoleService(data.Namespace, pods, timeoutInMin) +} + +func addIngressURIEnvVariableToManagementConsole(namespace string, managementConsole *bddtypes.KogitoServiceHolder) error { + dataIndexURI, err := framework.GetIngressURI(namespace, "data-index") + if err != nil { + return err + } + managementConsole.KogitoService.GetSpec().AddEnvironmentVariable("KOGITO_DATAINDEX_HTTP_URL", dataIndexURI) + return nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/kogitotaskconsole.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/kogitotaskconsole.go new file mode 100644 index 00000000000..8b59a7c13d8 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/kogitotaskconsole.go @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers" + bddtypes "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/types" +) + +/* + DataTable for Task console: + | config | infra | | + | runtime-request | cpu/memory | value | + | runtime-limit | cpu/memory | value | + | runtime-env | varName | varValue | +*/ + +// RegisterCliSteps register all CLI steps existing +func registerKogitoTaskConsoleSteps(s *godog.ScenarioContext, data *Data) { + s.Step(`^Install Kogito Task Console with (\d+) replicas$`, data.installKogitoTaskConsoleWithReplicas) + s.Step(`^Install Kogito Task Console with (\d+) replicas with configuration:$`, data.installKogitoTaskConsoleWithReplicasWithConfiguration) + s.Step(`^Kogito Task Console has (\d+) pods running within (\d+) minutes$`, data.kogitoTaskConsoleHasPodsRunningWithinMinutes) +} + +func (data *Data) installKogitoTaskConsoleWithReplicas(replicas int) error { + taskConsole := &bddtypes.KogitoServiceHolder{ + KogitoService: framework.GetKogitoTaskConsoleResourceStub(data.Namespace, replicas), + } + + // Can be removed once https://issues.redhat.com/browse/KOGITO-1141 is implemented + if !framework.IsOpenshift() { + if err := addIngressURIEnvVariableToTaskConsole(data.Namespace, taskConsole); err != nil { + return err + } + } + + return framework.InstallKogitoTaskConsole(framework.GetDefaultInstallerType(), taskConsole) +} + +func (data *Data) installKogitoTaskConsoleWithReplicasWithConfiguration(replicas int, table *godog.Table) error { + taskConsole := &bddtypes.KogitoServiceHolder{ + KogitoService: framework.GetKogitoTaskConsoleResourceStub(data.Namespace, replicas), + } + + if err := mappers.MapKogitoServiceTable(table, taskConsole); err != nil { + return err + } + + // Can be removed once https://issues.redhat.com/browse/KOGITO-1141 is implemented + if !framework.IsOpenshift() { + if err := addIngressURIEnvVariableToTaskConsole(data.Namespace, taskConsole); err != nil { + return err + } + } + + return framework.InstallKogitoTaskConsole(framework.GetDefaultInstallerType(), taskConsole) +} + +func (data *Data) kogitoTaskConsoleHasPodsRunningWithinMinutes(pods, timeoutInMin int) error { + return framework.WaitForKogitoTaskConsoleService(data.Namespace, pods, timeoutInMin) +} + +func addIngressURIEnvVariableToTaskConsole(namespace string, taskConsole *bddtypes.KogitoServiceHolder) error { + dataIndexURI, err := framework.GetIngressURI(namespace, "data-index") + if err != nil { + return err + } + taskConsole.KogitoService.GetSpec().AddEnvironmentVariable("KOGITO_DATAINDEX_HTTP_URL", dataIndexURI) + return nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/kubernetes.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/kubernetes.go new file mode 100644 index 00000000000..d39647d4c13 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/kubernetes.go @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + v1 "k8s.io/api/core/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers" +) + +/* + DataTable for Deployment runtime resources: + | runtime-request | cpu/memory | value | + | runtime-limit | cpu/memory | value | +*/ + +func registerKubernetesSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Namespace is created$`, data.namespaceIsCreated) + ctx.Step(`^Namespace is deleted$`, data.namespaceIsDeleted) + + ctx.Step(`^CLI create namespace$`, data.cliCreateNamespace) + ctx.Step(`^CLI use namespace$`, data.cliUseNamespace) + + ctx.Step(`^Deployment "([^"]*)" has (\d+) pods with runtime resources within (\d+) minutes:$`, data.deploymentHasResourcesWithinMinutes) + + // Logging steps + ctx.Step(`^Deployment "([^"]*)" pods log contains text "([^"]*)" within (\d+) minutes$`, data.deploymentPodsLogContainsTextWithinMinutes) +} + +func (data *Data) namespaceIsCreated() error { + return framework.CreateNamespace(data.Namespace) +} + +func (data *Data) namespaceIsDeleted() error { + if exists, err := framework.IsNamespace(data.Namespace); err != nil { + return err + } else if exists { + err := framework.DeleteNamespace(data.Namespace) + if err != nil { + return err + } + // wait for deletion complete + err = framework.WaitForOnOpenshift(data.Namespace, "namespace is deleted", 2, + func() (bool, error) { + exists, err := framework.IsNamespace(data.Namespace) + return !exists, err + }) + if err != nil { + return err + } + } + return nil +} + +func (data *Data) cliCreateNamespace() error { + _, err := framework.ExecuteCliCommand(data.Namespace, "new-project", data.Namespace) + return err +} + +func (data *Data) cliUseNamespace() error { + _, err := framework.ExecuteCliCommand(data.Namespace, "use-project", data.Namespace) + return err +} + +func (data *Data) deploymentHasResourcesWithinMinutes(dName string, podNb, timeoutInMin int, table *godog.Table) error { + if err := framework.WaitForDeploymentRunning(data.Namespace, dName, podNb, timeoutInMin); err != nil { + return err + } + + runtime := &v1.ResourceRequirements{Limits: v1.ResourceList{}, Requests: v1.ResourceList{}} + err := mappers.MapRuntimeResourceRequirementsTable(table, runtime) + + if err != nil { + return err + } + + return framework.WaitForPodsByDeploymentToHaveResources(data.Namespace, dName, *runtime, timeoutInMin) +} + +func (data *Data) deploymentPodsLogContainsTextWithinMinutes(dName, logText string, timeoutInMin int) error { + return framework.WaitForAllPodsByDeploymentToContainTextInLog(data.Namespace, dName, logText, timeoutInMin) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/check_resource_requirements.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/check_resource_requirements.go new file mode 100644 index 00000000000..40ffd290f1d --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/check_resource_requirements.go @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package mappers + +import ( + "fmt" + + "github.com/cucumber/messages-go/v16" + + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" +) + +// *** Whenever you add new parsing functionality here please add corresponding DataTable example to every file in steps which can use the functionality *** + +const ( + // DataTable first column + buildRequestKey = "build-request" + buildLimitKey = "build-limit" + runtimeRequestKey = "runtime-request" + runtimeLimitKey = "runtime-limit" +) + +// MapBuildResourceRequirementsTable maps Cucumber table of build resource requirements +func MapBuildResourceRequirementsTable(table *messages.PickleTable, build *v1.ResourceRequirements) error { + for _, row := range table.Rows { + mappingFound, err := mapBuildResourceRequirementsTableRow(row, build) + if !mappingFound { + return fmt.Errorf("Row mapping not found, Build resource mapping error: %v", err) + } + + } + return nil +} + +// mapBuildResourceRequirementsTableRow maps Cucumber table row of build resource requirements +func mapBuildResourceRequirementsTableRow(row *TableRow, build *v1.ResourceRequirements) (mappingFound bool, err error) { + if len(row.Cells) != 3 { + return false, fmt.Errorf("expected table to have exactly three columns") + } + + firstColumn := GetFirstColumn(row) + switch firstColumn { + case buildRequestKey: + build.Requests[v1.ResourceName(GetSecondColumn(row))] = resource.MustParse(GetThirdColumn(row)) + + case buildLimitKey: + build.Limits[v1.ResourceName(GetSecondColumn(row))] = resource.MustParse(GetThirdColumn(row)) + + default: + return false, fmt.Errorf("Unrecognized build configuration option: %s", firstColumn) + } + + return true, nil +} + +// MapRuntimeResourceRequirementsTable maps Cucumber table of runtime resource requirements +func MapRuntimeResourceRequirementsTable(table *messages.PickleTable, runtime *v1.ResourceRequirements) error { + for _, row := range table.Rows { + mappingFound, err := mapRuntimeResourceRequirementsTableRow(row, runtime) + if !mappingFound { + return fmt.Errorf("Row mapping not found, Runtime resource mapping error: %v", err) + } + + } + return nil +} + +// mapRuntimeResourceRequirementsTableRow maps Cucumber table row of runtime resource requirements +func mapRuntimeResourceRequirementsTableRow(row *TableRow, runtime *v1.ResourceRequirements) (mappingFound bool, err error) { + if len(row.Cells) != 3 { + return false, fmt.Errorf("expected table to have exactly three columns") + } + + firstColumn := GetFirstColumn(row) + switch firstColumn { + case runtimeRequestKey: + runtime.Requests[v1.ResourceName(GetSecondColumn(row))] = resource.MustParse(GetThirdColumn(row)) + + case runtimeLimitKey: + runtime.Limits[v1.ResourceName(GetSecondColumn(row))] = resource.MustParse(GetThirdColumn(row)) + + default: + return false, fmt.Errorf("Unrecognized runtime configuration option: %s", firstColumn) + } + + return true, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_infinispan_instance.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_infinispan_instance.go new file mode 100644 index 00000000000..f470ee3d479 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_infinispan_instance.go @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package mappers + +import ( + "fmt" + + "github.com/cucumber/messages-go/v16" +) + +// *** Whenever you add new parsing functionality here please add corresponding DataTable example to every file in steps which can use the functionality *** + +const ( + // DataTable first column + infinispanUsernameKey = "username" + infinispanPasswordKey = "password" +) + +// MapInfinispanCredentialsFromTable maps Cucumber table to Infinispan credentials +func MapInfinispanCredentialsFromTable(table *messages.PickleTable) (username, password string, err error) { + if len(table.Rows) == 0 { // Using default configuration + return + } + + if len(table.Rows[0].Cells) != 2 { + return "", "", fmt.Errorf("expected table to have exactly two columns") + } + + for _, row := range table.Rows { + firstColumn := GetFirstColumn(row) + switch firstColumn { + case infinispanUsernameKey: + username = GetSecondColumn(row) + case infinispanPasswordKey: + password = GetSecondColumn(row) + + default: + return "", "", fmt.Errorf("Unrecognized configuration option: %s", firstColumn) + } + } + return +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_kogito_service.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_kogito_service.go new file mode 100644 index 00000000000..75c267cfab4 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_kogito_service.go @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package mappers + +import ( + "fmt" + + "github.com/cucumber/messages-go/v16" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/types" + bddtypes "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/types" +) + +// *** Whenever you add new parsing functionality here please add corresponding DataTable example to every file in steps which can use the functionality *** + +const ( + // DataTable first column + kogitoServiceConfigKey = "config" + kogitoServiceRuntimeRequestKey = "runtime-request" + kogitoServiceRuntimeLimitKey = "runtime-limit" + kogitoServiceRuntimeEnvKey = "runtime-env" + kogitoServiceServiceLabelKey = "service-label" + kogitoServiceDeploymentLabelKey = "deployment-label" + + // DataTable second column + kogitoServiceInfraKey = "infra" + kogitoServiceDabaseTypeKey = "database-type" + kogitoServiceNameTypeKey = "name" +) + +// MapKogitoServiceTable maps Cucumber table to KogitoServiceHolder +func MapKogitoServiceTable(table *messages.PickleTable, serviceHolder *types.KogitoServiceHolder) error { + for _, row := range table.Rows { + // Try to map configuration row to KogitoServiceHolder + _, err := MapKogitoServiceTableRow(row, serviceHolder) + if err != nil { + return err + } + + } + return nil +} + +// MapKogitoServiceTableRow maps Cucumber table row to KogitoServiceHolder +func MapKogitoServiceTableRow(row *TableRow, kogitoService *bddtypes.KogitoServiceHolder) (mappingFound bool, err error) { + if len(row.Cells) != 3 { + return false, fmt.Errorf("expected table to have exactly three columns") + } + + firstColumn := GetFirstColumn(row) + + switch firstColumn { + case kogitoServiceServiceLabelKey: + kogitoService.KogitoService.GetSpec().AddServiceLabel(GetSecondColumn(row), GetThirdColumn(row)) + + case kogitoServiceDeploymentLabelKey: + kogitoService.KogitoService.GetSpec().AddDeploymentLabel(GetSecondColumn(row), GetThirdColumn(row)) + + case kogitoServiceRuntimeEnvKey: + kogitoService.KogitoService.GetSpec().AddEnvironmentVariable(GetSecondColumn(row), GetThirdColumn(row)) + + case kogitoServiceRuntimeRequestKey: + kogitoService.KogitoService.GetSpec().AddResourceRequest(GetSecondColumn(row), GetThirdColumn(row)) + + case kogitoServiceRuntimeLimitKey: + kogitoService.KogitoService.GetSpec().AddResourceLimit(GetSecondColumn(row), GetThirdColumn(row)) + + case kogitoServiceConfigKey: + return mapKogitoServiceConfigTableRow(row, kogitoService) + + default: + return false, fmt.Errorf("Unrecognized configuration option: %s", firstColumn) + } + + return true, nil +} + +func mapKogitoServiceConfigTableRow(row *TableRow, kogitoService *bddtypes.KogitoServiceHolder) (mappingFound bool, err error) { + secondColumn := GetSecondColumn(row) + + switch secondColumn { + case kogitoServiceInfraKey: + kogitoService.KogitoService.GetSpec().AddInfra(GetThirdColumn(row)) + + case kogitoServiceDabaseTypeKey: + kogitoService.DatabaseType = GetThirdColumn(row) + + case kogitoServiceNameTypeKey: + kogitoService.KogitoService.SetName(GetThirdColumn(row)) + + default: + return false, fmt.Errorf("Unrecognized config configuration option: %s", secondColumn) + } + + return true, nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_maven_options.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_maven_options.go new file mode 100644 index 00000000000..969545b59ec --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_maven_options.go @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package mappers + +import ( + "fmt" + "strings" + + "github.com/cucumber/messages-go/v16" +) + +const ( + // Maven config first column + mavenProfileKey = "profile" + mavenOptionKey = "option" + mavenNativeKey = "native" +) + +// MavenCommandConfig contains configuration for Maven Command execution +type MavenCommandConfig struct { + Profiles []string + Options []string + Native bool +} + +// MapMavenCommandConfigTable maps Cucumber table with Maven options to a slice +func MapMavenCommandConfigTable(table *messages.PickleTable, config *MavenCommandConfig) error { + if len(table.Rows) == 0 { // Using default configuration + return nil + } + + if len(table.Rows[0].Cells) != 2 { + return fmt.Errorf("expected table to have exactly two columns") + } + + for _, row := range table.Rows { + firstColumn := GetFirstColumn(row) + switch firstColumn { + case mavenProfileKey: + config.Profiles = append(config.Profiles, strings.Split(GetSecondColumn(row), ",")...) + case mavenOptionKey: + config.Options = append(config.Options, GetSecondColumn(row)) + case mavenNativeKey: + config.Native = MustParseEnabledDisabled(GetSecondColumn(row)) + default: + return fmt.Errorf("Unrecognized configuration option: %s", firstColumn) + } + } + return nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_mongodb_instance.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_mongodb_instance.go new file mode 100644 index 00000000000..5699a0c2fb7 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_mongodb_instance.go @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package mappers + +import ( + "fmt" + + "github.com/cucumber/messages-go/v16" +) + +// *** Whenever you add new parsing functionality here please add corresponding DataTable example to every file in steps which can use the functionality *** + +const ( + // DataTable first column + mongodbUsernameKey = "username" + mongodbPasswordKey = "password" + mongodbDatabaseKey = "database" + mongodbAuthDatabaseKey = "auth-database" +) + +// MongoDBCredentialsConfig contains credentials information for MongoDB, taken from configuration table +type MongoDBCredentialsConfig struct { + Username string + Password string + Database string + AuthDatabase string +} + +// MapMongoDBCredentialsFromTable maps Cucumber table to MongoDB credentials +func MapMongoDBCredentialsFromTable(table *messages.PickleTable, creds *MongoDBCredentialsConfig) error { + if len(table.Rows) == 0 { // Using default configuration + return nil + } + + if len(table.Rows[0].Cells) != 2 { + return fmt.Errorf("expected table to have exactly two columns") + } + + for _, row := range table.Rows { + firstColumn := GetFirstColumn(row) + switch firstColumn { + case mongodbUsernameKey: + creds.Username = GetSecondColumn(row) + case mongodbPasswordKey: + creds.Password = GetSecondColumn(row) + case mongodbDatabaseKey: + creds.Database = GetSecondColumn(row) + case mongodbAuthDatabaseKey: + creds.AuthDatabase = GetSecondColumn(row) + + default: + return fmt.Errorf("Unrecognized configuration option: %s", firstColumn) + } + } + return nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_postgresql_instance.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_postgresql_instance.go new file mode 100644 index 00000000000..93157e54efb --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/create_postgresql_instance.go @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package mappers + +import ( + "fmt" + + "github.com/cucumber/messages-go/v16" +) + +// *** Whenever you add new parsing functionality here please add corresponding DataTable example to every file in steps which can use the functionality *** + +const ( + // DataTable first column + posgresqlUsernameKey = "username" + posgresqlPasswordKey = "password" + posgresqlDatabaseKey = "database" +) + +// PostgresqlCredentialsConfig contains credentials information for PostgreSQL, taken from configuration table +type PostgresqlCredentialsConfig struct { + Username string + Password string + Database string +} + +// MapPostgresqlCredentialsFromTable maps Cucumber table to PostgreSQL credentials +func MapPostgresqlCredentialsFromTable(table *messages.PickleTable, creds *PostgresqlCredentialsConfig) error { + if len(table.Rows) == 0 { // Using default configuration + return nil + } + + if len(table.Rows[0].Cells) != 2 { + return fmt.Errorf("expected table to have exactly two columns") + } + + for _, row := range table.Rows { + firstColumn := GetFirstColumn(row) + switch firstColumn { + case posgresqlUsernameKey: + creds.Username = GetSecondColumn(row) + case posgresqlPasswordKey: + creds.Password = GetSecondColumn(row) + case posgresqlDatabaseKey: + creds.Database = GetSecondColumn(row) + + default: + return fmt.Errorf("Unrecognized configuration option: %s", firstColumn) + } + } + return nil +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/shared_functions.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/shared_functions.go new file mode 100644 index 00000000000..45890786050 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers/shared_functions.go @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package mappers + +import ( + "fmt" + + "github.com/cucumber/messages-go/v16" +) + +// TableRow represents a row of godog.Table made to a step definition +type TableRow = messages.PickleTableRow + +const ( + enabledKey = "enabled" + disabledKey = "disabled" +) + +// GetFirstColumn returns first table row column +func GetFirstColumn(row *TableRow) string { + return row.Cells[0].Value +} + +// GetSecondColumn returns second table row column +func GetSecondColumn(row *TableRow) string { + return row.Cells[1].Value +} + +// GetThirdColumn returns third table row column +func GetThirdColumn(row *TableRow) string { + return row.Cells[2].Value +} + +// MustParseEnabledDisabled parse a boolean string value +func MustParseEnabledDisabled(value string) bool { + switch value { + case enabledKey: + return true + case disabledKey: + return false + default: + panic(fmt.Errorf("Unknown value for enabled/disabled: %s", value)) + } +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/maven.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/maven.go new file mode 100644 index 00000000000..45924a0604e --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/maven.go @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers" +) + +/* + DataTable for Maven: + | profile | profile | + | profile | profile2 | + | option | -Doption=true | + | option | -Doption2=true | + | native | enabled | +*/ + +const ( + // DefaultMavenBuiltExampleRegex is the regex for building maven example + DefaultMavenBuiltExampleRegex = "Local example service \"([^\"]*)\" is built by Maven" + nativeProfile = "native" +) + +// registerMavenSteps register all existing Maven steps +func registerMavenSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step("^"+DefaultMavenBuiltExampleRegex+"$", data.localServiceBuiltByMaven) + ctx.Step("^"+DefaultMavenBuiltExampleRegex+" with configuration:$", data.localServiceBuiltByMavenWithConfiguration) +} + +// Build local service +func (data *Data) localServiceBuiltByMaven(contextDir string) error { + return data.localServiceBuiltByMavenWithConfiguration(contextDir, nil) +} + +// Build local service with configuration +func (data *Data) localServiceBuiltByMavenWithConfiguration(contextDir string, table *godog.Table) error { + mavenConfig := &mappers.MavenCommandConfig{} + if table != nil && len(table.Rows) > 0 { + err := mappers.MapMavenCommandConfigTable(table, mavenConfig) + if err != nil { + return err + } + } + return data.localServiceBuiltByMavenWithProfileAndOptions(contextDir, mavenConfig) +} + +// Build local service with profile and additional options +func (data *Data) localServiceBuiltByMavenWithProfileAndOptions(contextDir string, mavenConfig *mappers.MavenCommandConfig) error { + serviceRepositoryPath := data.KogitoExamplesLocation + "/" + contextDir + mvnCmd := framework.CreateMavenCommand(serviceRepositoryPath). + SkipTests(). + UpdateArtifacts(). + Options(mavenConfig.Options...). + Profiles(mavenConfig.Profiles...). + WithLoggerContext(data.Namespace) + + if mavenConfig.Native { + mvnCmd = mvnCmd.Profiles(nativeProfile) + } + output, err := mvnCmd.Execute("clean", "package") + framework.GetLogger(data.Namespace).Debug(output) + return err +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/mongodb.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/mongodb.go new file mode 100644 index 00000000000..047d6553a61 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/mongodb.go @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/installers" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers" +) + +/* + DataTable for MongoDB: + | username | developer | + | password | mypass | + | database | kogito | +*/ + +func registerMongoDBSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^MongoDB Operator is deployed$`, data.mongoDbOperatorIsDeployed) + ctx.Step(`^MongoDB instance "([^"]*)" has (\d+) (?:pod|pods) running within (\d+) (?:minute|minutes)$`, data.mongodbInstanceHasPodsRunningWithinMinutes) + ctx.Step(`^MongoDB instance "([^"]*)" is deployed with configuration:$`, data.mongodbInstanceIsDeployedWithConfiguration) + + ctx.Step(`^Scale MongoDB instance "([^"]*)" to (\d+) pods within (\d+) minutes$`, data.scaleMongoDBInstanceToPodsWithinMinutes) +} + +func (data *Data) mongoDbOperatorIsDeployed() error { + return installers.GetMongoDbInstaller().Install(data.Namespace) +} + +func (data *Data) mongodbInstanceHasPodsRunningWithinMinutes(name string, numberOfPods, timeOutInMin int) error { + return framework.WaitForPodsWithLabel(data.Namespace, "app", name+"-svc", numberOfPods, timeOutInMin) +} + +func (data *Data) mongodbInstanceIsDeployedWithConfiguration(name string, table *godog.Table) error { + mongoDBSecretName := name + "-secret" + creds := &mappers.MongoDBCredentialsConfig{} + if err := mappers.MapMongoDBCredentialsFromTable(table, creds); err != nil { + return err + } + + if err := framework.CreateMongoDBSecret(data.Namespace, mongoDBSecretName, creds.Password); err != nil { + return err + } + + mongodb := framework.GetMongoDBStub(framework.IsOpenshift(), data.Namespace, name, []framework.MongoDBUserCred{ + { + Name: creds.Username, + AuthDatabase: creds.AuthDatabase, + SecretName: mongoDBSecretName, + Databases: []string{creds.Database}, + }, + }) + if err := framework.DeployMongoDBInstance(data.Namespace, mongodb); err != nil { + return err + } + + return framework.WaitForPodsWithLabel(data.Namespace, "app", name+"-svc", 1, 3) +} + +func (data *Data) scaleMongoDBInstanceToPodsWithinMinutes(name string, nbPods, timeoutInMin int) error { + err := framework.SetMongoDBReplicas(data.Namespace, name, nbPods) + if err != nil { + return err + } + return framework.WaitForPodsWithLabel(data.Namespace, "app", name+"-svc", nbPods, timeoutInMin) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/openshift.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/openshift.go new file mode 100644 index 00000000000..e210e6c37d3 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/openshift.go @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "fmt" + + "github.com/cucumber/godog" + v1 "k8s.io/api/core/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers" +) + +const defaultTimeoutToStartBuildInMin = 5 + +/* + DataTable for BuildConfig build resources: + | build-request | cpu/memory | value | + | build-limit | cpu/memory | value | +*/ + +func registerOpenShiftSteps(ctx *godog.ScenarioContext, data *Data) { + // Build steps + ctx.Step(`^Start build with name "([^"]*)" from local example service path "([^"]*)"$`, data.startBuildFromExampleServicePath) + ctx.Step(`^Start build with name "([^"]*)" from local example service file "([^"]*)"$`, data.startBuildFromExampleServiceFile) + + // BuildConfig steps + ctx.Step(`^BuildConfig "([^"]*)" is created after (\d+) minutes$`, data.buildConfigIsCreatedAfterMinutes) + ctx.Step(`^BuildConfig "([^"]*)" is created with build resources within (\d+) minutes:$`, data.buildConfigHasResourcesWithinMinutes) +} + +// Build steps +func (data *Data) startBuildFromExampleServicePath(buildName, localExamplePath string) error { + examplesRepositoryPath := data.KogitoExamplesLocation + return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("Build '%s' to start", buildName), defaultTimeoutToStartBuildInMin, + func() (bool, error) { + _, err := framework.CreateCommand("oc", "start-build", buildName, "--from-dir="+examplesRepositoryPath+"/"+localExamplePath, "-n", data.Namespace).WithLoggerContext(data.Namespace).Execute() + return err == nil, err + }) +} + +func (data *Data) startBuildFromExampleServiceFile(buildName, localExampleFilePath string) error { + examplesRepositoryPath := data.KogitoExamplesLocation + return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("Build '%s' to start", buildName), defaultTimeoutToStartBuildInMin, + func() (bool, error) { + _, err := framework.CreateCommand("oc", "start-build", buildName, "--from-file="+examplesRepositoryPath+"/"+localExampleFilePath, "-n", data.Namespace).WithLoggerContext(data.Namespace).Execute() + return err == nil, err + }) +} + +func (data *Data) buildConfigIsCreatedAfterMinutes(buildConfigName string, timeoutInMin int) error { + return framework.WaitForBuildConfigCreated(data.Namespace, buildConfigName, timeoutInMin) +} + +func (data *Data) buildConfigHasResourcesWithinMinutes(buildConfigName string, timeoutInMin int, dt *godog.Table) error { + build := &v1.ResourceRequirements{Limits: v1.ResourceList{}, Requests: v1.ResourceList{}} + err := mappers.MapBuildResourceRequirementsTable(dt, build) + + if err != nil { + return err + } + + return framework.WaitForBuildConfigToHaveResources(data.Namespace, buildConfigName, *build, timeoutInMin) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/postgresql.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/postgresql.go new file mode 100644 index 00000000000..4989d09b67c --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/postgresql.go @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/steps/mappers" +) + +/* + DataTable for PostgreSQL: + | username | developer | + | password | mypass | + | database | kogito | +*/ + +func registerPostgresqlSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^PostgreSQL instance "([^"]*)" is deployed within (\d+) (?:minute|minutes) with configuration:$`, data.postgresqlInstanceIsDeployedWithConfiguration) + + ctx.Step(`^Scale PostgreSQL instance "([^"]*)" to (\d+) pods within (\d+) minutes$`, data.scalePostgresqlInstanceToPodsWithinMinutes) +} + +func (data *Data) postgresqlInstanceIsDeployedWithConfiguration(name string, timeOutInMin int, table *godog.Table) error { + creds := &mappers.PostgresqlCredentialsConfig{} + if err := mappers.MapPostgresqlCredentialsFromTable(table, creds); err != nil { + return err + } + + err := framework.CreatePostgresqlInstance(data.Namespace, name, 1, creds.Username, creds.Password, creds.Database) + if err != nil { + return err + } + + return framework.WaitForPostgresqlInstance(data.Namespace, 1, 3) +} + +func (data *Data) scalePostgresqlInstanceToPodsWithinMinutes(name string, nbPods, timeoutInMin int) error { + err := framework.SetPostgresqlReplicas(data.Namespace, name, nbPods) + if err != nil { + return err + } + return framework.WaitForPostgresqlInstance(data.Namespace, nbPods, 3) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/process.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/process.go new file mode 100644 index 00000000000..8844007daa3 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/process.go @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "fmt" + + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +func registerProcessSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Start "([^"]*)" process on service "([^"]*)" with body:$`, data.startProcessOnService) + ctx.Step(`^Start "([^"]*)" process on service "([^"]*)" within (\d+) minutes with body:$`, data.startProcessOnServiceWithinMinutes) + ctx.Step(`^Service "([^"]*)" with process name "([^"]*)" is available$`, data.serviceWithProcessNameIsAvailable) + ctx.Step(`^Service "([^"]*)" with process name "([^"]*)" is available within (\d+) minutes$`, data.serviceWithProcessNameIsAvailableWithinMinutes) + ctx.Step(`^Service "([^"]*)" contains (\d+) (?:instance|instances) of process with name "([^"]*)"$`, data.serviceContainsInstancesOfProcess) + ctx.Step(`^Service "([^"]*)" contains (\d+) (?:instance|instances) of process with name "([^"]*)" within (\d+) minutes$`, data.serviceContainsInstancesOfProcessWithinMinutes) +} + +func (data *Data) startProcessOnService(processName, serviceName string, body *godog.DocString) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + bodyContent := data.ResolveWithScenarioContext(body.Content) + err = framework.StartProcess(data.Namespace, uri, processName, body.MediaType, bodyContent) + if err != nil { + return err + } + return nil +} + +func (data *Data) startProcessOnServiceWithinMinutes(processName, serviceName string, timeoutInMin int, body *godog.DocString) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("Service %s is not available yet", serviceName), timeoutInMin, + func() (bool, error) { + err = framework.StartProcess(data.Namespace, uri, processName, body.MediaType, body.Content) + if err != nil { + return false, err + } + + return true, nil + }) +} + +func (data *Data) serviceWithProcessNameIsAvailable(serviceName, processName string) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + _, err = framework.GetProcessInstances(data.Namespace, uri, processName) + if err != nil { + return err + } + + return nil +} + +func (data *Data) serviceWithProcessNameIsAvailableWithinMinutes(serviceName, processName string, timeoutInMin int) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("Process %s is not available yet", processName), timeoutInMin, + func() (bool, error) { + _, err = framework.GetProcessInstances(data.Namespace, uri, processName) + if err != nil { + return false, err + } + + return true, nil + }) +} + +func (data *Data) serviceContainsInstancesOfProcess(serviceName string, processInstances int, processName string) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + foundProcessInstances, err := framework.GetProcessInstances(data.Namespace, uri, processName) + if err != nil { + return err + } + if len(foundProcessInstances) != processInstances { + return fmt.Errorf("expected %d of process instances, but got %d", processInstances, len(foundProcessInstances)) + } + return nil +} + +func (data *Data) serviceContainsInstancesOfProcessWithinMinutes(serviceName string, processInstances int, processName string, timeoutInMin int) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("Process %s has %d instances", processName, processInstances), timeoutInMin, + func() (bool, error) { + foundProcessInstances, err := framework.GetProcessInstances(data.Namespace, uri, processName) + if err != nil { + return false, err + } + if len(foundProcessInstances) != processInstances { + return false, nil + } + return true, nil + }) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/prometheus.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/prometheus.go new file mode 100644 index 00000000000..06606fd3079 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/prometheus.go @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/installers" +) + +func registerPrometheusSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Prometheus Operator is deployed$`, data.prometheusOperatorIsDeployed) + ctx.Step(`^Prometheus instance is deployed, monitoring services with label name "([^"]*)" and value "([^"]*)"$`, data.prometheusInstanceIsDeployed) +} + +func (data *Data) prometheusOperatorIsDeployed() error { + return installers.GetPrometheusInstaller().Install(data.Namespace) +} + +func (data *Data) prometheusInstanceIsDeployed(labelName, labelValue string) error { + err := framework.DeployPrometheusInstance(data.Namespace, labelName, labelValue) + if err != nil { + return err + } + return framework.WaitForPodsWithLabel(data.Namespace, "app.kubernetes.io/name", "prometheus", 1, 3) +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/steps/task.go b/packages/kogito-serverless-operator/bddframework/pkg/steps/task.go new file mode 100644 index 00000000000..fe0e995e7e2 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/steps/task.go @@ -0,0 +1,168 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "fmt" + + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +func registerTaskSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^Service "([^"]*)" contains (\d+) (?:task|tasks) of process with name "([^"]*)" and task name "([^"]*)"$`, data.serviceContainsTasksOfProcessWithNameAndTaskName) + ctx.Step(`^Service "([^"]*)" contains (\d+) (?:task|tasks) of process with name "([^"]*)" and task name "([^"]*)" for user "([^"]*)"$`, data.serviceContainsTasksOfProcessWithNameAndTaskNameForUser) + ctx.Step(`^Service "([^"]*)" contains (\d+) (?:task|tasks) of process with name "([^"]*)" and task name "([^"]*)" for user "([^"]*)" within (\d+) minutes$`, data.serviceContainsTasksOfProcessWithNameAndTaskNameForUserWithinMinutes) + ctx.Step(`^Complete "([^"]*)" task on service "([^"]*)" and process with name "([^"]*)" with body:$`, data.completeTaskOnServiceAndProcessWithName) + ctx.Step(`^Complete "([^"]*)" task on service "([^"]*)" and process with name "([^"]*)" by user "([^"]*)" with body:$`, data.completeTaskOnServiceAndProcessWithNameAndUser) +} + +func (data *Data) serviceContainsTasksOfProcessWithNameAndTaskName(serviceName string, numberOfTasks int, processName, taskName string) error { + return data.serviceContainsTasksOfProcessWithNameAndTaskNameForUser(serviceName, numberOfTasks, processName, taskName, "") +} + +func (data *Data) serviceContainsTasksOfProcessWithNameAndTaskNameForUserWithinMinutes(serviceName string, numberOfTasks int, processName, taskName, user string, timeoutInMin int) error { + return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("Process %s has %d %s task(s)", processName, numberOfTasks, taskName), timeoutInMin, + func() (bool, error) { + err := data.serviceContainsTasksOfProcessWithNameAndTaskNameForUser(serviceName, numberOfTasks, processName, taskName, user) + if err != nil { + return false, err + } + + return true, nil + }) +} + +func (data *Data) serviceContainsTasksOfProcessWithNameAndTaskNameForUser(serviceName string, numberOfTasks int, processName, taskName, user string) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + processInstanceID, err := getProcessInstanceID(data.Namespace, uri, processName) + if err != nil { + return err + } + + var foundTasks []framework.Task + if user != "" { + foundTasks, err = framework.GetTasksByUser(data.Namespace, uri, processName, processInstanceID, user) + } else { + foundTasks, err = framework.GetTasks(data.Namespace, uri, processName, processInstanceID) + } + if err != nil { + return err + } + for _, foundTask := range foundTasks { + if taskName != foundTask.Name { + return fmt.Errorf("found unexpected task name %s", foundTask.Name) + } + } + if len(foundTasks) < numberOfTasks { + return fmt.Errorf("not enough tasks found, expected at least %d tasks, but found just %d tasks", numberOfTasks, len(foundTasks)) + } + + return nil +} + +func (data *Data) completeTaskOnServiceAndProcessWithName(taskName, serviceName, processName string, body *godog.DocString) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + processInstanceID, err := getProcessInstanceID(data.Namespace, uri, processName) + if err != nil { + return err + } + + foundTasks, err := framework.GetTasks(data.Namespace, uri, processName, processInstanceID) + if err != nil { + return err + } + + taskID, exists := getTaskID(foundTasks, taskName) + if !exists { + return fmt.Errorf("task with name %s not found", taskName) + } + + bodyContent := data.ResolveWithScenarioContext(body.Content) + err = framework.CompleteTask(data.Namespace, uri, processName, processInstanceID, taskName, taskID, body.MediaType, bodyContent) + if err != nil { + return err + } + return nil +} + +func (data *Data) completeTaskOnServiceAndProcessWithNameAndUser(taskName, serviceName, processName, user string, body *godog.DocString) error { + uri, err := framework.WaitAndRetrieveEndpointURI(data.Namespace, serviceName) + if err != nil { + return err + } + + processInstanceID, err := getProcessInstanceID(data.Namespace, uri, processName) + if err != nil { + return err + } + + foundTasks, err := framework.GetTasksByUser(data.Namespace, uri, processName, processInstanceID, user) + if err != nil { + return err + } + + taskID, exists := getTaskID(foundTasks, taskName) + if !exists { + return fmt.Errorf("task with name %s not found", taskName) + } + + bodyContent := data.ResolveWithScenarioContext(body.Content) + err = framework.CompleteTaskByUser(data.Namespace, uri, processName, processInstanceID, taskName, taskID, user, body.MediaType, bodyContent) + if err != nil { + return err + } + return nil +} + +// getProcessInstanceID returns the process instance ID by process name +func getProcessInstanceID(namespace, routeURI, processName string) (string, error) { + foundProcessInstances, err := framework.GetProcessInstances(namespace, routeURI, processName) + if err != nil { + return "", err + } + if len(foundProcessInstances) == 0 { + return "", fmt.Errorf("no process instance found, expected one instance") + } + if len(foundProcessInstances) > 1 { + return "", fmt.Errorf("too many process instances found, expected one instance, but found %d instances", len(foundProcessInstances)) + } + + return foundProcessInstances[0]["id"].(string), nil +} + +// getTaskID Returns task id of the task with name searchedTaskName and flag is the task with such name exists in tasks map +func getTaskID(tasks []framework.Task, searchedTaskName string) (string, bool) { + for _, task := range tasks { + if task.Name == searchedTaskName { + return task.ID, true + } + } + return "", false +} diff --git a/packages/kogito-serverless-operator/bddframework/pkg/types/holder.go b/packages/kogito-serverless-operator/bddframework/pkg/types/holder.go new file mode 100644 index 00000000000..ccf93f44bb0 --- /dev/null +++ b/packages/kogito-serverless-operator/bddframework/pkg/types/holder.go @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package types + +import ( + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api" +) + +// KogitoServiceHolder Helper structure holding informations which are not available in KogitoService +type KogitoServiceHolder struct { + api.KogitoService + + DatabaseType string +} + +// KogitoBuildHolder Helper structure holding informations for Kogito build +type KogitoBuildHolder struct { + *KogitoServiceHolder + + // Specifies folder with prebuilt Kogito binaries to be uploaded to KogitoBuild + BuiltBinaryFolder string +} diff --git a/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-builder-config_v1_configmap.yaml b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-builder-config_v1_configmap.yaml new file mode 100644 index 00000000000..d04b6b62165 --- /dev/null +++ b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-builder-config_v1_configmap.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +data: + DEFAULT_WORKFLOW_EXTENSION: .sw.json + Dockerfile: "FROM quay.io/kiegroup/kogito-swf-builder-nightly:latest 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: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: + name: sonataflow-operator-builder-config diff --git a/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-controller-manager-metrics-service_v1_service.yaml b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-controller-manager-metrics-service_v1_service.yaml new file mode 100644 index 00000000000..48f0198e414 --- /dev/null +++ b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-controller-manager-metrics-service_v1_service.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Service +metadata: + creationTimestamp: null + labels: + control-plane: sonataflow-operator + name: sonataflow-operator-controller-manager-metrics-service +spec: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: https + selector: + control-plane: sonataflow-operator +status: + loadBalancer: {} diff --git a/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-controllers-config_v1_configmap.yaml b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-controllers-config_v1_configmap.yaml new file mode 100644 index 00000000000..a16e6be86fb --- /dev/null +++ b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-controllers-config_v1_configmap.yaml @@ -0,0 +1,34 @@ +apiVersion: v1 +data: + controllers_cfg.yaml: | + # 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: "" + dataIndexEphemeralTag: "" + # 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 se 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" +kind: ConfigMap +metadata: + name: sonataflow-operator-controllers-config diff --git a/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-manager-config_v1_configmap.yaml b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-manager-config_v1_configmap.yaml new file mode 100644 index 00000000000..3f7526a3928 --- /dev/null +++ b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-manager-config_v1_configmap.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +data: + controller_manager_config.yaml: | + 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 +kind: ConfigMap +metadata: + name: sonataflow-operator-manager-config diff --git a/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml new file mode 100644 index 00000000000..dc5dac882e3 --- /dev/null +++ b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml @@ -0,0 +1,10 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: sonataflow-operator-metrics-reader +rules: + - nonResourceURLs: + - /metrics + verbs: + - get diff --git a/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-sonataflowclusterplatform-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-sonataflowclusterplatform-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml new file mode 100644 index 00000000000..776356b7e77 --- /dev/null +++ b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator-sonataflowclusterplatform-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml @@ -0,0 +1,27 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + labels: + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: sonataflow-operator + app.kubernetes.io/instance: sonataflowclusterplatform-viewer-role + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: clusterrole + app.kubernetes.io/part-of: sonataflow-operator + name: sonataflow-operator-sonataflowclusterplatform-viewer-role +rules: + - apiGroups: + - sonataflow.org + resources: + - sonataflowclusterplatforms + verbs: + - get + - list + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflowclusterplatforms/status + verbs: + - get diff --git a/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator.clusterserviceversion.yaml b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator.clusterserviceversion.yaml new file mode 100644 index 00000000000..0b294cfee58 --- /dev/null +++ b/packages/kogito-serverless-operator/bundle/manifests/sonataflow-operator.clusterserviceversion.yaml @@ -0,0 +1,864 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: |- + [ + { + "apiVersion": "sonataflow.org/v1alpha08", + "kind": "SonataFlow", + "metadata": { + "annotations": { + "sonataflow.org/description": "Greeting example on k8s!", + "sonataflow.org/version": "0.0.1" + }, + "name": "greeting" + }, + "spec": { + "flow": { + "functions": [ + { + "name": "greetFunction", + "operation": "sysout", + "type": "custom" + } + ], + "start": "ChooseOnLanguage", + "states": [ + { + "dataConditions": [ + { + "condition": "${ .language == \"English\" }", + "transition": "GreetInEnglish" + }, + { + "condition": "${ .language == \"Spanish\" }", + "transition": "GreetInSpanish" + } + ], + "defaultCondition": "GreetInEnglish", + "name": "ChooseOnLanguage", + "type": "switch" + }, + { + "data": { + "greeting": "Hello from JSON Workflow, " + }, + "name": "GreetInEnglish", + "transition": "GreetPerson", + "type": "inject" + }, + { + "data": { + "greeting": "Saludos desde JSON Workflow, " + }, + "name": "GreetInSpanish", + "transition": "GreetPerson", + "type": "inject" + }, + { + "actions": [ + { + "functionRef": { + "arguments": { + "message": ".greeting+.name" + }, + "refName": "greetFunction" + }, + "name": "greetAction" + } + ], + "end": true, + "name": "GreetPerson", + "type": "operation" + } + ] + } + } + }, + { + "apiVersion": "sonataflow.org/v1alpha08", + "kind": "SonataFlowBuild", + "metadata": { + "name": "greeting" + }, + "spec": { + "timeout": "360s" + } + }, + { + "apiVersion": "sonataflow.org/v1alpha08", + "kind": "SonataFlowClusterPlatform", + "metadata": { + "name": "sonataflow-clusterplatform" + }, + "spec": { + "platformRef": { + "name": "sonataflow-platform", + "namespace": "sonataflow-operator-system" + } + } + }, + { + "apiVersion": "sonataflow.org/v1alpha08", + "kind": "SonataFlowPlatform", + "metadata": { + "name": "sonataflow-platform" + }, + "spec": { + "build": { + "config": { + "registry": { + "address": "quay.io/kiegroup", + "secret": "regcred" + } + } + } + } + } + ] + capabilities: Basic Install + categories: Application Runtime + containerImage: quay.io/kiegroup/kogito-serverless-operator-nightly:latest + description: SonataFlow Kubernetes Operator for deploying workflow applications + based on the CNCF Serverless Workflow specification + operators.operatorframework.io/builder: operator-sdk-v1.25.0 + operators.operatorframework.io/internal-objects: '["sonataflowbuilds.sonataflow.org"]' + operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 + repository: https://github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator + support: Red Hat + 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: Sonata Flow Build + 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: Sonata Flow Cluster Platform + 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: Sonata Flow Platform + 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: "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 build + displayName: info + path: info + - 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: Sonata Flow + kind: SonataFlow + name: sonataflows.sonataflow.org + resources: + - kind: Deployment + name: A Deployment for the Flow + version: apps/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 + 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: lastTimeRecoverAttempt + path: lastTimeRecoverAttempt + - 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 + 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: + clusterPermissions: + - 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 + - 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: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflowbuilds + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflowbuilds/finalizers + verbs: + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowbuilds/status + verbs: + - get + - patch + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowclusterplatforms + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflowclusterplatforms/finalizers + verbs: + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowclusterplatforms/status + verbs: + - get + - patch + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowplatforms + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflowplatforms/finalizers + verbs: + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowplatforms/status + verbs: + - get + - patch + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflows + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflows/finalizers + verbs: + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflows/status + verbs: + - get + - patch + - update + - 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 + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create + - 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 + serviceAccountName: sonataflow-operator-controller-manager + deployments: + - label: + control-plane: sonataflow-operator + name: sonataflow-operator-controller-manager + spec: + replicas: 1 + selector: + matchLabels: + control-plane: sonataflow-operator + strategy: {} + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: manager + labels: + control-plane: sonataflow-operator + spec: + containers: + - args: + - --health-probe-bind-address=:8081 + - --metrics-bind-address=127.0.0.1:8080 + - --leader-elect + - --v=0 + command: + - /usr/local/bin/manager + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: quay.io/kiegroup/kogito-serverless-operator-nightly:latest + 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: 128Mi + requests: + cpu: 10m + memory: 64Mi + 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 + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0 + 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 + permissions: + - 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 + serviceAccountName: sonataflow-operator-controller-manager + strategy: deployment + 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: bsig-cloud@redhat.com + name: Red Hat + maturity: alpha + minKubeVersion: 1.23.0 + provider: + name: Red Hat + version: 0.0.0 diff --git a/packages/kogito-serverless-operator/bundle/manifests/sonataflow.org_sonataflowbuilds.yaml b/packages/kogito-serverless-operator/bundle/manifests/sonataflow.org_sonataflowbuilds.yaml new file mode 100644 index 00000000000..e83477192f2 --- /dev/null +++ b/packages/kogito-serverless-operator/bundle/manifests/sonataflow.org_sonataflowbuilds.yaml @@ -0,0 +1,366 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/packages/kogito-serverless-operator/bundle/manifests/sonataflow.org_sonataflowclusterplatforms.yaml b/packages/kogito-serverless-operator/bundle/manifests/sonataflow.org_sonataflowclusterplatforms.yaml new file mode 100644 index 00000000000..e76ea83978d --- /dev/null +++ b/packages/kogito-serverless-operator/bundle/manifests/sonataflow.org_sonataflowclusterplatforms.yaml @@ -0,0 +1,133 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + 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: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/packages/kogito-serverless-operator/bundle/manifests/sonataflow.org_sonataflowplatforms.yaml b/packages/kogito-serverless-operator/bundle/manifests/sonataflow.org_sonataflowplatforms.yaml new file mode 100644 index 00000000000..c425d5ca31c --- /dev/null +++ b/packages/kogito-serverless-operator/bundle/manifests/sonataflow.org_sonataflowplatforms.yaml @@ -0,0 +1,16420 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + 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. \n 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + 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. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + 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 + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be set + if type is "Localhost". + type: string + type: + description: "type indicates which kind of + seccomp profile will be applied. Valid options + are: \n 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. + This field is alpha-level and will only + be honored by components that enable the + WindowsHostProcessContainers feature flag. + Setting this field without the feature flag + will result in errors when validating the + Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind + of seccomp profile will be applied. Valid + options are: \n 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. This field is alpha-level and + will only be honored by components that + enable the WindowsHostProcessContainers + feature flag. Setting this field without + the feature flag will result in errors + when validating the Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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 + 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 + 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 + 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 + ip: + description: IP address of the host file entry. + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind + of seccomp profile will be applied. Valid + options are: \n 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. This field is alpha-level and + will only be honored by components that + enable the WindowsHostProcessContainers + feature flag. Setting this field without + the feature flag will result in errors + when validating the Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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. \n If the OS field is set to linux, the + following fields must be unset: -securityContext.windowsOptions + \n 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 + 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. \n This is an + alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable." + items: + description: PodResourceClaim references exactly one + ResourceClaim through a ClaimSource. 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 + source: + description: Source describes where to find the + ResourceClaim. + properties: + resourceClaimName: + description: ResourceClaimName is the name of + a ResourceClaim object in the same namespace + as this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the + name of a ResourceClaimTemplate object in + the same namespace as this pod. \n 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 name of the ResourceClaim + will be -, where + is the PodResourceClaim.Name. + Pod validation will reject the pod if the + concatenated name is not valid for a ResourceClaim + (e.g. too long). \n An existing ResourceClaim + with that name that is not owned by the pod + will not be used for the pod to avoid using + an unrelated resource by mistake. Scheduling + and pod startup are then blocked until the + unrelated ResourceClaim is removed. \n This + field is immutable and no changes will be + made to the corresponding ResourceClaim by + the control plane after creating the ResourceClaim." + type: string + type: object + 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. \n SchedulingGates can only be + set at pod creation time, and be removed only afterwards. + \n 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: + 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: \n 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---- \n + 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: + \n 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, the fsGroup (if specified), + and group memberships defined in the container image + for the uid of the container process. If unspecified, + no additional groups are added to any container. + Note that group memberships defined in the container + image for the uid of the container process are still + effective, even if they are not included in this + list. Note that this field cannot be set when spec.os.name + is windows. + items: + format: int64 + type: integer + type: array + 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 + 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. + This field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the + feature flag will result in errors when validating + the Pod. 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + 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. \n 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. \n 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. \n This is a beta + field and requires the MinDomainsInPodTopologySpread + feature gate to be enabled (enabled by default)." + 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. + \n 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. \n 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + name: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 and namespace 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 + 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. \n 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). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes + that persist for longer than the lifecycle of + an individual pod. \n 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. \n 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). + \n 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. \n This field is read-only + and no changes will be made by Kubernetes + to the PVC after it has been created. \n 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 + 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: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. + \n This is an alpha field and + requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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. TODO: how do we prevent errors + in the filesystem from compromising the machine' + 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 + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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 + --- TODO(jonesdl) We need to restrict who can + use host directory mounts and who can/can not + mount host directories as read/write." + 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 + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + items: + description: Projection that may be projected + along with other supported volume types + properties: + 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 + name: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 and namespace + 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 + 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 + name: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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 + pool: + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + x-kubernetes-map-type: atomic + user: + 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: + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable + SSL communication with Gateway, default false + type: boolean + storageMode: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + 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: 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + 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. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + 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 + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be set + if type is "Localhost". + type: string + type: + description: "type indicates which kind of + seccomp profile will be applied. Valid options + are: \n 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. + This field is alpha-level and will only + be honored by components that enable the + WindowsHostProcessContainers feature flag. + Setting this field without the feature flag + will result in errors when validating the + Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind + of seccomp profile will be applied. Valid + options are: \n 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. This field is alpha-level and + will only be honored by components that + enable the WindowsHostProcessContainers + feature flag. Setting this field without + the feature flag will result in errors + when validating the Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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 + 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 + 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 + 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 + ip: + description: IP address of the host file entry. + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind + of seccomp profile will be applied. Valid + options are: \n 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. This field is alpha-level and + will only be honored by components that + enable the WindowsHostProcessContainers + feature flag. Setting this field without + the feature flag will result in errors + when validating the Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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. \n If the OS field is set to linux, the + following fields must be unset: -securityContext.windowsOptions + \n 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 + 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. \n This is an + alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable." + items: + description: PodResourceClaim references exactly one + ResourceClaim through a ClaimSource. 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 + source: + description: Source describes where to find the + ResourceClaim. + properties: + resourceClaimName: + description: ResourceClaimName is the name of + a ResourceClaim object in the same namespace + as this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the + name of a ResourceClaimTemplate object in + the same namespace as this pod. \n 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 name of the ResourceClaim + will be -, where + is the PodResourceClaim.Name. + Pod validation will reject the pod if the + concatenated name is not valid for a ResourceClaim + (e.g. too long). \n An existing ResourceClaim + with that name that is not owned by the pod + will not be used for the pod to avoid using + an unrelated resource by mistake. Scheduling + and pod startup are then blocked until the + unrelated ResourceClaim is removed. \n This + field is immutable and no changes will be + made to the corresponding ResourceClaim by + the control plane after creating the ResourceClaim." + type: string + type: object + 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. \n SchedulingGates can only be + set at pod creation time, and be removed only afterwards. + \n 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: + 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: \n 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---- \n + 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: + \n 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, the fsGroup (if specified), + and group memberships defined in the container image + for the uid of the container process. If unspecified, + no additional groups are added to any container. + Note that group memberships defined in the container + image for the uid of the container process are still + effective, even if they are not included in this + list. Note that this field cannot be set when spec.os.name + is windows. + items: + format: int64 + type: integer + type: array + 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 + 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. + This field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the + feature flag will result in errors when validating + the Pod. 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + 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. \n 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. \n 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. \n This is a beta + field and requires the MinDomainsInPodTopologySpread + feature gate to be enabled (enabled by default)." + 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. + \n 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. \n 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + name: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 and namespace 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 + 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. \n 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). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes + that persist for longer than the lifecycle of + an individual pod. \n 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. \n 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). + \n 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. \n This field is read-only + and no changes will be made by Kubernetes + to the PVC after it has been created. \n 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 + 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: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. + \n This is an alpha field and + requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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. TODO: how do we prevent errors + in the filesystem from compromising the machine' + 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 + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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 + --- TODO(jonesdl) We need to restrict who can + use host directory mounts and who can/can not + mount host directories as read/write." + 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 + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + items: + description: Projection that may be projected + along with other supported volume types + properties: + 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 + name: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 and namespace + 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 + 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 + name: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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 + pool: + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + x-kubernetes-map-type: atomic + user: + 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: + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable + SSL communication with Gateway, default false + type: boolean + storageMode: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + 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 build + type: object + observedGeneration: + description: The generation observed by the deployment controller. + format: int64 + type: integer + version: + description: Version the operator version controlling this Platform + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/packages/kogito-serverless-operator/bundle/manifests/sonataflow.org_sonataflows.yaml b/packages/kogito-serverless-operator/bundle/manifests/sonataflow.org_sonataflows.yaml new file mode 100644 index 00000000000..d66b8b5c72a --- /dev/null +++ b/packages/kogito-serverless-operator/bundle/manifests/sonataflow.org_sonataflows.yaml @@ -0,0 +1,9508 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + 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: + type: string + 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: + 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: + additionalProperties: + type: object + description: Metadata information + type: object + 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: + additionalProperties: + type: object + description: Metadata information + type: object + 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) + TODO: make iso8601duration compatible this type" + 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: + additionalProperties: + type: object + description: Add additional extension context + attributes to the produced event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to be passed + to the referenced function TODO: validate + it as required if function type is graphql" + type: object + 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. TODO: validate it as required if function + type is graphql" + 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: + additionalProperties: + type: object + description: Add additional extension + context attributes to the produced + event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function + definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to + be passed to the referenced function + TODO: validate it as required if function + type is graphql" + type: object + 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. TODO: validate + it as required if function type is + graphql" + 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: + additionalProperties: + type: object + description: Add additional extension context + attributes to the produced event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to be passed + to the referenced function TODO: validate + it as required if function type is graphql" + type: object + 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. TODO: validate it as required if function + type is graphql" + 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: + additionalProperties: + type: object + description: JSON object which can be set as state's + data input and can be manipulated via filter + minProperties: 1 + type: object + 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: + additionalProperties: + type: object + description: Metadata information. + type: object + 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: + additionalProperties: + type: object + description: Add additional extension context + attributes to the produced event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to be passed + to the referenced function TODO: validate + it as required if function type is graphql" + type: object + 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. TODO: validate it as required if function + type is graphql" + 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: + additionalProperties: + type: object + description: Add additional extension + context attributes to the produced + event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function + definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to + be passed to the referenced function + TODO: validate it as required if function + type is graphql" + type: object + 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. TODO: validate + it as required if function type is + graphql" + 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. + TODO: change this field to unmarshal result as int" + 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: TODO End or Transition needs to be + exclusive tag, one or another should be set. + 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 + type: object + 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. + type: object + 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: + additionalProperties: + type: object + description: Metadata information. + type: object + 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. + type: object + 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: If 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: TODO End or Transition needs to be + exclusive tag, one or another should be set. + 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: 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + 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 + 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 + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + 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 is DefaultProcMount + 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n 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. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + 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 is DefaultProcMount + 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n + 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. This + field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the + Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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 + 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 + 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 + 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 + ip: + description: IP address of the host file entry. + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + type: object + 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 + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + 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 is DefaultProcMount + 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n + 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. This + field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the + Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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. \n If + the OS field is set to linux, the following fields must be unset: + -securityContext.windowsOptions \n 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 + 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. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. \n This + field is immutable." + items: + description: PodResourceClaim references exactly one ResourceClaim + through a ClaimSource. 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 + source: + description: Source describes where to find the ResourceClaim. + properties: + resourceClaimName: + description: ResourceClaimName is the name of a ResourceClaim + object in the same namespace as this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the name + of a ResourceClaimTemplate object in the same namespace + as this pod. \n 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 name of the ResourceClaim will be + -, where + is the PodResourceClaim.Name. Pod validation will + reject the pod if the concatenated name is not valid + for a ResourceClaim (e.g. too long). \n An existing + ResourceClaim with that name that is not owned by + the pod will not be used for the pod to avoid using + an unrelated resource by mistake. Scheduling and pod + startup are then blocked until the unrelated ResourceClaim + is removed. \n This field is immutable and no changes + will be made to the corresponding ResourceClaim by + the control plane after creating the ResourceClaim." + type: string + type: object + 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. \n SchedulingGates + can only be set at pod creation time, and be removed only afterwards. + \n 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: + 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: \n 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---- + \n 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n 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, the fsGroup (if specified), and group memberships defined + in the container image for the uid of the container process. + If unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image + for the uid of the container process are still effective, + even if they are not included in this list. Note that this + field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + 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 + 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. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + 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. \n 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. \n 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. \n This is a beta field and requires + the MinDomainsInPodTopologySpread feature gate to be enabled + (enabled by default)." + 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. \n 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. \n 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 + TODO: how do we prevent errors in the filesystem from + compromising the machine' + 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: + 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: + 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 + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + name: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 and namespace + 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 + 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. \n + 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). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes that persist + for longer than the lifecycle of an individual pod. \n + 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. \n 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). \n 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. + \n This field is read-only and no changes will be + made by Kubernetes to the PVC after it has been created. + \n 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 + 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: + claims: + description: "Claims lists the names of + resources, defined in spec.resourceClaims, + that are used by this container. \n This + is an alpha field and requires enabling + the DynamicResourceAllocation feature + gate. \n 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 + 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 + 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + 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 + 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. TODO: how do we prevent + errors in the filesystem from compromising the machine' + 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 + 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 + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + TODO: how do we prevent errors in the filesystem from + compromising the machine' + 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 + --- TODO(jonesdl) We need to restrict who can use host + directory mounts and who can/can not mount host directories + as read/write." + 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 + 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 + TODO: how do we prevent errors in the filesystem from + compromising the machine' + 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: + 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 + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + items: + description: Projection that may be projected along + with other supported volume types + properties: + 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 + name: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 and namespace 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 + 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 + name: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + TODO: how do we prevent errors in the filesystem from + compromising the machine' + 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: + 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 + pool: + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + x-kubernetes-map-type: atomic + user: + 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: + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + 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 + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + type: object + 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 + 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 + 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 + 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 + lastTimeRecoverAttempt: + format: date-time + type: string + observedGeneration: + description: The generation observed by the deployment controller. + format: int64 + type: integer + recoverFailureAttempts: + description: keeps track of how many failure recovers a given workflow + had so far + type: integer + 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 + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/packages/kogito-serverless-operator/bundle/metadata/annotations.yaml b/packages/kogito-serverless-operator/bundle/metadata/annotations.yaml new file mode 100644 index 00000000000..68eab166f4f --- /dev/null +++ b/packages/kogito-serverless-operator/bundle/metadata/annotations.yaml @@ -0,0 +1,15 @@ +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: alpha + operators.operatorframework.io.metrics.builder: operator-sdk-v1.25.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/packages/kogito-serverless-operator/bundle/tests/scorecard/config.yaml b/packages/kogito-serverless-operator/bundle/tests/scorecard/config.yaml new file mode 100644 index 00000000000..10c93fa4d75 --- /dev/null +++ b/packages/kogito-serverless-operator/bundle/tests/scorecard/config.yaml @@ -0,0 +1,70 @@ +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.25.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.25.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.25.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.25.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.25.0 + labels: + suite: olm + test: olm-status-descriptors-test + storage: + spec: + mountPath: {} +storage: + spec: + mountPath: {} diff --git a/packages/kogito-serverless-operator/config/crd/bases/sonataflow.org_sonataflowbuilds.yaml b/packages/kogito-serverless-operator/config/crd/bases/sonataflow.org_sonataflowbuilds.yaml new file mode 100644 index 00000000000..c1a21bd445e --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/bases/sonataflow.org_sonataflowbuilds.yaml @@ -0,0 +1,361 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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: {} diff --git a/packages/kogito-serverless-operator/config/crd/bases/sonataflow.org_sonataflowclusterplatforms.yaml b/packages/kogito-serverless-operator/config/crd/bases/sonataflow.org_sonataflowclusterplatforms.yaml new file mode 100644 index 00000000000..6ed0c78cddf --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/bases/sonataflow.org_sonataflowclusterplatforms.yaml @@ -0,0 +1,128 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + 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: {} diff --git a/packages/kogito-serverless-operator/config/crd/bases/sonataflow.org_sonataflowplatforms.yaml b/packages/kogito-serverless-operator/config/crd/bases/sonataflow.org_sonataflowplatforms.yaml new file mode 100644 index 00000000000..1c6766cbbf7 --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/bases/sonataflow.org_sonataflowplatforms.yaml @@ -0,0 +1,16415 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + 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. \n 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + 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. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + 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 + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be set + if type is "Localhost". + type: string + type: + description: "type indicates which kind of + seccomp profile will be applied. Valid options + are: \n 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. + This field is alpha-level and will only + be honored by components that enable the + WindowsHostProcessContainers feature flag. + Setting this field without the feature flag + will result in errors when validating the + Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind + of seccomp profile will be applied. Valid + options are: \n 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. This field is alpha-level and + will only be honored by components that + enable the WindowsHostProcessContainers + feature flag. Setting this field without + the feature flag will result in errors + when validating the Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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 + 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 + 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 + 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 + ip: + description: IP address of the host file entry. + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind + of seccomp profile will be applied. Valid + options are: \n 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. This field is alpha-level and + will only be honored by components that + enable the WindowsHostProcessContainers + feature flag. Setting this field without + the feature flag will result in errors + when validating the Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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. \n If the OS field is set to linux, the + following fields must be unset: -securityContext.windowsOptions + \n 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 + 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. \n This is an + alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable." + items: + description: PodResourceClaim references exactly one + ResourceClaim through a ClaimSource. 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 + source: + description: Source describes where to find the + ResourceClaim. + properties: + resourceClaimName: + description: ResourceClaimName is the name of + a ResourceClaim object in the same namespace + as this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the + name of a ResourceClaimTemplate object in + the same namespace as this pod. \n 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 name of the ResourceClaim + will be -, where + is the PodResourceClaim.Name. + Pod validation will reject the pod if the + concatenated name is not valid for a ResourceClaim + (e.g. too long). \n An existing ResourceClaim + with that name that is not owned by the pod + will not be used for the pod to avoid using + an unrelated resource by mistake. Scheduling + and pod startup are then blocked until the + unrelated ResourceClaim is removed. \n This + field is immutable and no changes will be + made to the corresponding ResourceClaim by + the control plane after creating the ResourceClaim." + type: string + type: object + 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. \n SchedulingGates can only be + set at pod creation time, and be removed only afterwards. + \n 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: + 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: \n 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---- \n + 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: + \n 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, the fsGroup (if specified), + and group memberships defined in the container image + for the uid of the container process. If unspecified, + no additional groups are added to any container. + Note that group memberships defined in the container + image for the uid of the container process are still + effective, even if they are not included in this + list. Note that this field cannot be set when spec.os.name + is windows. + items: + format: int64 + type: integer + type: array + 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 + 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. + This field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the + feature flag will result in errors when validating + the Pod. 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + 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. \n 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. \n 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. \n This is a beta + field and requires the MinDomainsInPodTopologySpread + feature gate to be enabled (enabled by default)." + 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. + \n 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. \n 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + name: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 and namespace 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 + 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. \n 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). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes + that persist for longer than the lifecycle of + an individual pod. \n 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. \n 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). + \n 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. \n This field is read-only + and no changes will be made by Kubernetes + to the PVC after it has been created. \n 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 + 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: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. + \n This is an alpha field and + requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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. TODO: how do we prevent errors + in the filesystem from compromising the machine' + 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 + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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 + --- TODO(jonesdl) We need to restrict who can + use host directory mounts and who can/can not + mount host directories as read/write." + 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 + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + items: + description: Projection that may be projected + along with other supported volume types + properties: + 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 + name: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 and namespace + 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 + 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 + name: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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 + pool: + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + x-kubernetes-map-type: atomic + user: + 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: + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable + SSL communication with Gateway, default false + type: boolean + storageMode: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + 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: 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + 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. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + 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 + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be set + if type is "Localhost". + type: string + type: + description: "type indicates which kind of + seccomp profile will be applied. Valid options + are: \n 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. + This field is alpha-level and will only + be honored by components that enable the + WindowsHostProcessContainers feature flag. + Setting this field without the feature flag + will result in errors when validating the + Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind + of seccomp profile will be applied. Valid + options are: \n 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. This field is alpha-level and + will only be honored by components that + enable the WindowsHostProcessContainers + feature flag. Setting this field without + the feature flag will result in errors + when validating the Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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 + 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 + 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 + 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 + ip: + description: IP address of the host file entry. + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind + of seccomp profile will be applied. Valid + options are: \n 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. This field is alpha-level and + will only be honored by components that + enable the WindowsHostProcessContainers + feature flag. Setting this field without + the feature flag will result in errors + when validating the Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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. \n If the OS field is set to linux, the + following fields must be unset: -securityContext.windowsOptions + \n 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 + 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. \n This is an + alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable." + items: + description: PodResourceClaim references exactly one + ResourceClaim through a ClaimSource. 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 + source: + description: Source describes where to find the + ResourceClaim. + properties: + resourceClaimName: + description: ResourceClaimName is the name of + a ResourceClaim object in the same namespace + as this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the + name of a ResourceClaimTemplate object in + the same namespace as this pod. \n 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 name of the ResourceClaim + will be -, where + is the PodResourceClaim.Name. + Pod validation will reject the pod if the + concatenated name is not valid for a ResourceClaim + (e.g. too long). \n An existing ResourceClaim + with that name that is not owned by the pod + will not be used for the pod to avoid using + an unrelated resource by mistake. Scheduling + and pod startup are then blocked until the + unrelated ResourceClaim is removed. \n This + field is immutable and no changes will be + made to the corresponding ResourceClaim by + the control plane after creating the ResourceClaim." + type: string + type: object + 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. \n SchedulingGates can only be + set at pod creation time, and be removed only afterwards. + \n 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: + 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: \n 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---- \n + 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: + \n 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, the fsGroup (if specified), + and group memberships defined in the container image + for the uid of the container process. If unspecified, + no additional groups are added to any container. + Note that group memberships defined in the container + image for the uid of the container process are still + effective, even if they are not included in this + list. Note that this field cannot be set when spec.os.name + is windows. + items: + format: int64 + type: integer + type: array + 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 + 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. + This field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the + feature flag will result in errors when validating + the Pod. 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + 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. \n 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. \n 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. \n This is a beta + field and requires the MinDomainsInPodTopologySpread + feature gate to be enabled (enabled by default)." + 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. + \n 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. \n 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + name: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 and namespace 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 + 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. \n 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). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes + that persist for longer than the lifecycle of + an individual pod. \n 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. \n 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). + \n 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. \n This field is read-only + and no changes will be made by Kubernetes + to the PVC after it has been created. \n 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 + 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: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. + \n This is an alpha field and + requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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. TODO: how do we prevent errors + in the filesystem from compromising the machine' + 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 + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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 + --- TODO(jonesdl) We need to restrict who can + use host directory mounts and who can/can not + mount host directories as read/write." + 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 + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + items: + description: Projection that may be projected + along with other supported volume types + properties: + 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 + name: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 and namespace + 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 + 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 + name: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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 + pool: + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + x-kubernetes-map-type: atomic + user: + 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: + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable + SSL communication with Gateway, default false + type: boolean + storageMode: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + 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 build + type: object + observedGeneration: + description: The generation observed by the deployment controller. + format: int64 + type: integer + version: + description: Version the operator version controlling this Platform + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/kogito-serverless-operator/config/crd/bases/sonataflow.org_sonataflows.yaml b/packages/kogito-serverless-operator/config/crd/bases/sonataflow.org_sonataflows.yaml new file mode 100644 index 00000000000..6d506dbf8b7 --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/bases/sonataflow.org_sonataflows.yaml @@ -0,0 +1,9503 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + 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: + type: string + 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: + 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: + additionalProperties: + type: object + description: Metadata information + type: object + 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: + additionalProperties: + type: object + description: Metadata information + type: object + 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) + TODO: make iso8601duration compatible this type" + 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: + additionalProperties: + type: object + description: Add additional extension context + attributes to the produced event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to be passed + to the referenced function TODO: validate + it as required if function type is graphql" + type: object + 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. TODO: validate it as required if function + type is graphql" + 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: + additionalProperties: + type: object + description: Add additional extension + context attributes to the produced + event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function + definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to + be passed to the referenced function + TODO: validate it as required if function + type is graphql" + type: object + 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. TODO: validate + it as required if function type is + graphql" + 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: + additionalProperties: + type: object + description: Add additional extension context + attributes to the produced event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to be passed + to the referenced function TODO: validate + it as required if function type is graphql" + type: object + 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. TODO: validate it as required if function + type is graphql" + 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: + additionalProperties: + type: object + description: JSON object which can be set as state's + data input and can be manipulated via filter + minProperties: 1 + type: object + 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: + additionalProperties: + type: object + description: Metadata information. + type: object + 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: + additionalProperties: + type: object + description: Add additional extension context + attributes to the produced event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to be passed + to the referenced function TODO: validate + it as required if function type is graphql" + type: object + 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. TODO: validate it as required if function + type is graphql" + 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: + additionalProperties: + type: object + description: Add additional extension + context attributes to the produced + event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function + definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to + be passed to the referenced function + TODO: validate it as required if function + type is graphql" + type: object + 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. TODO: validate + it as required if function type is + graphql" + 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. + TODO: change this field to unmarshal result as int" + 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: TODO End or Transition needs to be + exclusive tag, one or another should be set. + 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 + type: object + 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. + type: object + 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: + additionalProperties: + type: object + description: Metadata information. + type: object + 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. + type: object + 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: If 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: TODO End or Transition needs to be + exclusive tag, one or another should be set. + 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: 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + 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 + 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 + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + 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 is DefaultProcMount + 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n 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. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + 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 is DefaultProcMount + 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n + 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. This + field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the + Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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 + 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 + 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 + 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 + ip: + description: IP address of the host file entry. + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + type: object + 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 + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + 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 is DefaultProcMount + 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n + 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. This + field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the + Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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. \n If + the OS field is set to linux, the following fields must be unset: + -securityContext.windowsOptions \n 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 + 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. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. \n This + field is immutable." + items: + description: PodResourceClaim references exactly one ResourceClaim + through a ClaimSource. 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 + source: + description: Source describes where to find the ResourceClaim. + properties: + resourceClaimName: + description: ResourceClaimName is the name of a ResourceClaim + object in the same namespace as this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the name + of a ResourceClaimTemplate object in the same namespace + as this pod. \n 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 name of the ResourceClaim will be + -, where + is the PodResourceClaim.Name. Pod validation will + reject the pod if the concatenated name is not valid + for a ResourceClaim (e.g. too long). \n An existing + ResourceClaim with that name that is not owned by + the pod will not be used for the pod to avoid using + an unrelated resource by mistake. Scheduling and pod + startup are then blocked until the unrelated ResourceClaim + is removed. \n This field is immutable and no changes + will be made to the corresponding ResourceClaim by + the control plane after creating the ResourceClaim." + type: string + type: object + 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. \n SchedulingGates + can only be set at pod creation time, and be removed only afterwards. + \n 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: + 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: \n 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---- + \n 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n 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, the fsGroup (if specified), and group memberships defined + in the container image for the uid of the container process. + If unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image + for the uid of the container process are still effective, + even if they are not included in this list. Note that this + field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + 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 + 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. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + 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. \n 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. \n 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. \n This is a beta field and requires + the MinDomainsInPodTopologySpread feature gate to be enabled + (enabled by default)." + 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. \n 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. \n 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 + TODO: how do we prevent errors in the filesystem from + compromising the machine' + 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: + 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: + 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 + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + name: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 and namespace + 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 + 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. \n + 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). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes that persist + for longer than the lifecycle of an individual pod. \n + 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. \n 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). \n 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. + \n This field is read-only and no changes will be + made by Kubernetes to the PVC after it has been created. + \n 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 + 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: + claims: + description: "Claims lists the names of + resources, defined in spec.resourceClaims, + that are used by this container. \n This + is an alpha field and requires enabling + the DynamicResourceAllocation feature + gate. \n 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 + 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 + 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + 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 + 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. TODO: how do we prevent + errors in the filesystem from compromising the machine' + 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 + 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 + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + TODO: how do we prevent errors in the filesystem from + compromising the machine' + 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 + --- TODO(jonesdl) We need to restrict who can use host + directory mounts and who can/can not mount host directories + as read/write." + 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 + 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 + TODO: how do we prevent errors in the filesystem from + compromising the machine' + 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: + 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 + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + items: + description: Projection that may be projected along + with other supported volume types + properties: + 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 + name: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 and namespace 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 + 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 + name: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + TODO: how do we prevent errors in the filesystem from + compromising the machine' + 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: + 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 + pool: + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + x-kubernetes-map-type: atomic + user: + 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: + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + 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 + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + type: object + 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 + 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 + 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 + 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 + lastTimeRecoverAttempt: + format: date-time + type: string + observedGeneration: + description: The generation observed by the deployment controller. + format: int64 + type: integer + recoverFailureAttempts: + description: keeps track of how many failure recovers a given workflow + had so far + type: integer + 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 + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/kogito-serverless-operator/config/crd/kustomization.yaml b/packages/kogito-serverless-operator/config/crd/kustomization.yaml new file mode 100644 index 00000000000..61ebf163b35 --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/kustomization.yaml @@ -0,0 +1,30 @@ +# 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 + +patchesStrategicMerge: +# [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 + +# the following config is for teaching kustomize how to do kustomization for CRDs. +configurations: + - kustomizeconfig.yaml diff --git a/packages/kogito-serverless-operator/config/crd/kustomizeconfig.yaml b/packages/kogito-serverless-operator/config/crd/kustomizeconfig.yaml new file mode 100644 index 00000000000..c1418ddee6e --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/kustomizeconfig.yaml @@ -0,0 +1,19 @@ +# 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: CustomResourceDefinition + version: v1 + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/namespace + create: false + +varReference: + - path: metadata/annotations diff --git a/packages/kogito-serverless-operator/config/crd/patches/cainjection_in_sonataflowbuilds.yaml b/packages/kogito-serverless-operator/config/crd/patches/cainjection_in_sonataflowbuilds.yaml new file mode 100644 index 00000000000..451e6d05315 --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/patches/cainjection_in_sonataflowbuilds.yaml @@ -0,0 +1,7 @@ +# 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/packages/kogito-serverless-operator/config/crd/patches/cainjection_in_sonataflowclusterplatforms.yaml b/packages/kogito-serverless-operator/config/crd/patches/cainjection_in_sonataflowclusterplatforms.yaml new file mode 100644 index 00000000000..dc0274cd7a4 --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/patches/cainjection_in_sonataflowclusterplatforms.yaml @@ -0,0 +1,7 @@ +# 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/packages/kogito-serverless-operator/config/crd/patches/cainjection_in_sonataflowplatforms.yaml b/packages/kogito-serverless-operator/config/crd/patches/cainjection_in_sonataflowplatforms.yaml new file mode 100644 index 00000000000..f0cb2da79b1 --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/patches/cainjection_in_sonataflowplatforms.yaml @@ -0,0 +1,7 @@ +# 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/packages/kogito-serverless-operator/config/crd/patches/cainjection_in_sonataflows.yaml b/packages/kogito-serverless-operator/config/crd/patches/cainjection_in_sonataflows.yaml new file mode 100644 index 00000000000..0f2efd86b4b --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/patches/cainjection_in_sonataflows.yaml @@ -0,0 +1,7 @@ +# 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/packages/kogito-serverless-operator/config/crd/patches/webhook_in_sonataflowbuilds.yaml b/packages/kogito-serverless-operator/config/crd/patches/webhook_in_sonataflowbuilds.yaml new file mode 100644 index 00000000000..3406df4d48f --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/patches/webhook_in_sonataflowbuilds.yaml @@ -0,0 +1,16 @@ +# 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/packages/kogito-serverless-operator/config/crd/patches/webhook_in_sonataflowclusterplatforms.yaml b/packages/kogito-serverless-operator/config/crd/patches/webhook_in_sonataflowclusterplatforms.yaml new file mode 100644 index 00000000000..68343cb2513 --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/patches/webhook_in_sonataflowclusterplatforms.yaml @@ -0,0 +1,16 @@ +# 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/packages/kogito-serverless-operator/config/crd/patches/webhook_in_sonataflowplatforms.yaml b/packages/kogito-serverless-operator/config/crd/patches/webhook_in_sonataflowplatforms.yaml new file mode 100644 index 00000000000..a51005ca19d --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/patches/webhook_in_sonataflowplatforms.yaml @@ -0,0 +1,16 @@ +# 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/packages/kogito-serverless-operator/config/crd/patches/webhook_in_sonataflows.yaml b/packages/kogito-serverless-operator/config/crd/patches/webhook_in_sonataflows.yaml new file mode 100644 index 00000000000..b55a65f1a51 --- /dev/null +++ b/packages/kogito-serverless-operator/config/crd/patches/webhook_in_sonataflows.yaml @@ -0,0 +1,16 @@ +# 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/packages/kogito-serverless-operator/config/default/controllers_config_patch.yaml b/packages/kogito-serverless-operator/config/default/controllers_config_patch.yaml new file mode 100644 index 00000000000..59fdab2bc72 --- /dev/null +++ b/packages/kogito-serverless-operator/config/default/controllers_config_patch.yaml @@ -0,0 +1,18 @@ +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/packages/kogito-serverless-operator/config/default/kustomization.yaml b/packages/kogito-serverless-operator/config/default/kustomization.yaml new file mode 100644 index 00000000000..cde9f268fe9 --- /dev/null +++ b/packages/kogito-serverless-operator/config/default/kustomization.yaml @@ -0,0 +1,77 @@ +# Adds namespace to all resources. +namespace: sonataflow-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- + +# Labels to add to all resources and selectors. +#commonLabels: +# someName: someValue + +bases: + - ../crd + - ../rbac + - ../manager +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in +# crd/kustomization.yaml +#- ../webhook +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. +#- ../certmanager +# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. +#- ../prometheus + +patchesStrategicMerge: + # 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. + - manager_auth_proxy_patch.yaml + + # Mount the controller config file for loading manager configurations + # through a ComponentConfig type + #- manager_config_patch.yaml + + # Mount the custom controllers config + - controllers_config_patch.yaml + +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in +# crd/kustomization.yaml +#- manager_webhook_patch.yaml + +# [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 +vars: +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. +#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR +# objref: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # this name should match the one in certificate.yaml +# fieldref: +# fieldpath: metadata.namespace +#- name: CERTIFICATE_NAME +# objref: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # this name should match the one in certificate.yaml +#- name: SERVICE_NAMESPACE # namespace of the service +# objref: +# kind: Service +# version: v1 +# name: webhook-service +# fieldref: +# fieldpath: metadata.namespace +#- name: SERVICE_NAME +# objref: +# kind: Service +# version: v1 +# name: webhook-service diff --git a/packages/kogito-serverless-operator/config/default/manager_auth_proxy_patch.yaml b/packages/kogito-serverless-operator/config/default/manager_auth_proxy_patch.yaml new file mode 100644 index 00000000000..9b04d354a0c --- /dev/null +++ b/packages/kogito-serverless-operator/config/default/manager_auth_proxy_patch.yaml @@ -0,0 +1,42 @@ +# 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: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0 + 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" + - "--v=0" diff --git a/packages/kogito-serverless-operator/config/default/manager_config_patch.yaml b/packages/kogito-serverless-operator/config/default/manager_config_patch.yaml new file mode 100644 index 00000000000..68563ebf121 --- /dev/null +++ b/packages/kogito-serverless-operator/config/default/manager_config_patch.yaml @@ -0,0 +1,20 @@ +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/packages/kogito-serverless-operator/config/manager/SonataFlow-Builder.containerfile b/packages/kogito-serverless-operator/config/manager/SonataFlow-Builder.containerfile new file mode 100644 index 00000000000..d95cbf0fd36 --- /dev/null +++ b/packages/kogito-serverless-operator/config/manager/SonataFlow-Builder.containerfile @@ -0,0 +1,33 @@ +FROM quay.io/kiegroup/kogito-swf-builder-nightly:latest 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: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/packages/kogito-serverless-operator/config/manager/controller_manager_config.yaml b/packages/kogito-serverless-operator/config/manager/controller_manager_config.yaml new file mode 100644 index 00000000000..4cefd89bb3f --- /dev/null +++ b/packages/kogito-serverless-operator/config/manager/controller_manager_config.yaml @@ -0,0 +1,11 @@ +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/packages/kogito-serverless-operator/config/manager/controllers_cfg.yaml b/packages/kogito-serverless-operator/config/manager/controllers_cfg.yaml new file mode 100644 index 00000000000..41f2f860ebb --- /dev/null +++ b/packages/kogito-serverless-operator/config/manager/controllers_cfg.yaml @@ -0,0 +1,28 @@ +# 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: "" +dataIndexEphemeralTag: "" +# 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 se 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" diff --git a/packages/kogito-serverless-operator/config/manager/kustomization.yaml b/packages/kogito-serverless-operator/config/manager/kustomization.yaml new file mode 100644 index 00000000000..771af44078c --- /dev/null +++ b/packages/kogito-serverless-operator/config/manager/kustomization.yaml @@ -0,0 +1,41 @@ +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 +images: + - name: controller + newName: quay.io/kiegroup/kogito-serverless-operator-nightly + newTag: latest +# Patching the manager deployment file to add an env var with the operator namespace in +patchesJson6902: + - patch: |- + - op: add + path: /spec/template/spec/containers/0/env + value: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + target: + group: apps + kind: Deployment + name: controller-manager + namespace: system + version: v1 diff --git a/packages/kogito-serverless-operator/config/manager/manager.yaml b/packages/kogito-serverless-operator/config/manager/manager.yaml new file mode 100644 index 00000000000..7474a88ad3a --- /dev/null +++ b/packages/kogito-serverless-operator/config/manager/manager.yaml @@ -0,0 +1,63 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + control-plane: sonataflow-operator + name: system +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system + labels: + control-plane: sonataflow-operator +spec: + selector: + matchLabels: + control-plane: sonataflow-operator + replicas: 1 + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: manager + labels: + control-plane: sonataflow-operator + spec: + securityContext: + runAsNonRoot: true + 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: 128Mi + requests: + cpu: 10m + memory: 64Mi + serviceAccountName: controller-manager + terminationGracePeriodSeconds: 10 diff --git a/packages/kogito-serverless-operator/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml b/packages/kogito-serverless-operator/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml new file mode 100644 index 00000000000..302f623757c --- /dev/null +++ b/packages/kogito-serverless-operator/config/manifests/bases/sonataflow-operator.clusterserviceversion.yaml @@ -0,0 +1,256 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: "[]" + capabilities: Basic Install + categories: Application Runtime + containerImage: quay.io/kiegroup/kogito-serverless-operator-nightly:latest + 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/kogito-serverless-operator + support: Red Hat + 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: Sonata Flow Build + 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: Sonata Flow Cluster Platform + 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: Sonata Flow Platform + 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: "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 build + displayName: info + path: info + - 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: Sonata Flow + kind: SonataFlow + name: sonataflows.sonataflow.org + resources: + - kind: Deployment + name: A Deployment for the Flow + version: apps/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 + 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: lastTimeRecoverAttempt + path: lastTimeRecoverAttempt + - 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 + 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: bsig-cloud@redhat.com + name: Red Hat + maturity: alpha + minKubeVersion: 1.23.0 + provider: + name: Red Hat + version: 0.0.0 diff --git a/packages/kogito-serverless-operator/config/manifests/kustomization.yaml b/packages/kogito-serverless-operator/config/manifests/kustomization.yaml new file mode 100644 index 00000000000..b1dc3831287 --- /dev/null +++ b/packages/kogito-serverless-operator/config/manifests/kustomization.yaml @@ -0,0 +1,26 @@ +# 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 +# [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. +#patchesJson6902: +#- target: +# group: apps +# version: v1 +# kind: Deployment +# name: controller-manager +# namespace: system +# patch: |- +# # 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 +# # 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 +# path: /spec/template/spec/volumes/0 diff --git a/packages/kogito-serverless-operator/config/prometheus/kustomization.yaml b/packages/kogito-serverless-operator/config/prometheus/kustomization.yaml new file mode 100644 index 00000000000..d556b996a21 --- /dev/null +++ b/packages/kogito-serverless-operator/config/prometheus/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - monitor.yaml diff --git a/packages/kogito-serverless-operator/config/prometheus/monitor.yaml b/packages/kogito-serverless-operator/config/prometheus/monitor.yaml new file mode 100644 index 00000000000..1f235df53b3 --- /dev/null +++ b/packages/kogito-serverless-operator/config/prometheus/monitor.yaml @@ -0,0 +1,19 @@ +# Prometheus Monitor Service (Metrics) +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + labels: + control-plane: sonataflow-operator + name: controller-manager-metrics-monitor + namespace: system +spec: + endpoints: + - path: /metrics + port: https + scheme: https + bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + tlsConfig: + insecureSkipVerify: true + selector: + matchLabels: + control-plane: sonataflow-operator diff --git a/packages/kogito-serverless-operator/config/rbac/auth_proxy_client_clusterrole.yaml b/packages/kogito-serverless-operator/config/rbac/auth_proxy_client_clusterrole.yaml new file mode 100644 index 00000000000..07f4382934e --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/auth_proxy_client_clusterrole.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/packages/kogito-serverless-operator/config/rbac/auth_proxy_role.yaml b/packages/kogito-serverless-operator/config/rbac/auth_proxy_role.yaml new file mode 100644 index 00000000000..2e55d6aeaca --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/auth_proxy_role.yaml @@ -0,0 +1,17 @@ +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/packages/kogito-serverless-operator/config/rbac/auth_proxy_role_binding.yaml b/packages/kogito-serverless-operator/config/rbac/auth_proxy_role_binding.yaml new file mode 100644 index 00000000000..ec70c402000 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/auth_proxy_role_binding.yaml @@ -0,0 +1,12 @@ +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/packages/kogito-serverless-operator/config/rbac/auth_proxy_service.yaml b/packages/kogito-serverless-operator/config/rbac/auth_proxy_service.yaml new file mode 100644 index 00000000000..b843fb75ceb --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/auth_proxy_service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: sonataflow-operator + name: controller-manager-metrics-service + namespace: system +spec: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: https + selector: + control-plane: sonataflow-operator diff --git a/packages/kogito-serverless-operator/config/rbac/builder_role.yaml b/packages/kogito-serverless-operator/config/rbac/builder_role.yaml new file mode 100644 index 00000000000..3547077f70d --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/builder_role.yaml @@ -0,0 +1,98 @@ +--- +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 + - 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 diff --git a/packages/kogito-serverless-operator/config/rbac/builder_role_binding.yaml b/packages/kogito-serverless-operator/config/rbac/builder_role_binding.yaml new file mode 100644 index 00000000000..160a7470f7e --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/builder_role_binding.yaml @@ -0,0 +1,12 @@ +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/packages/kogito-serverless-operator/config/rbac/kustomization.yaml b/packages/kogito-serverless-operator/config/rbac/kustomization.yaml new file mode 100644 index 00000000000..877a27cfae0 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/kustomization.yaml @@ -0,0 +1,26 @@ +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 + # 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 diff --git a/packages/kogito-serverless-operator/config/rbac/leader_election_role.yaml b/packages/kogito-serverless-operator/config/rbac/leader_election_role.yaml new file mode 100644 index 00000000000..9221419fae4 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/leader_election_role.yaml @@ -0,0 +1,37 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + 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 diff --git a/packages/kogito-serverless-operator/config/rbac/leader_election_role_binding.yaml b/packages/kogito-serverless-operator/config/rbac/leader_election_role_binding.yaml new file mode 100644 index 00000000000..887508ddeff --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/leader_election_role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: leader-election-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: leader-election-role +subjects: + - kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/packages/kogito-serverless-operator/config/rbac/openshift_role.yaml b/packages/kogito-serverless-operator/config/rbac/openshift_role.yaml new file mode 100644 index 00000000000..04945c5098b --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/openshift_role.yaml @@ -0,0 +1,96 @@ +--- +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/packages/kogito-serverless-operator/config/rbac/openshift_role_binding.yaml b/packages/kogito-serverless-operator/config/rbac/openshift_role_binding.yaml new file mode 100644 index 00000000000..1aaff931744 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/openshift_role_binding.yaml @@ -0,0 +1,12 @@ +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/packages/kogito-serverless-operator/config/rbac/operator_role_binding_leases.yaml b/packages/kogito-serverless-operator/config/rbac/operator_role_binding_leases.yaml new file mode 100644 index 00000000000..188c7e218c7 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/operator_role_binding_leases.yaml @@ -0,0 +1,12 @@ +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/packages/kogito-serverless-operator/config/rbac/operator_role_leases.yaml b/packages/kogito-serverless-operator/config/rbac/operator_role_leases.yaml new file mode 100644 index 00000000000..1dacd7d7439 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/operator_role_leases.yaml @@ -0,0 +1,18 @@ +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/packages/kogito-serverless-operator/config/rbac/role.yaml b/packages/kogito-serverless-operator/config/rbac/role.yaml new file mode 100644 index 00000000000..ccac71b06f4 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/role.yaml @@ -0,0 +1,111 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: manager-role +rules: + - apiGroups: + - sonataflow.org + resources: + - sonataflowbuilds + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflowbuilds/finalizers + verbs: + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowbuilds/status + verbs: + - get + - patch + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowclusterplatforms + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflowclusterplatforms/finalizers + verbs: + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowclusterplatforms/status + verbs: + - get + - patch + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowplatforms + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflowplatforms/finalizers + verbs: + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowplatforms/status + verbs: + - get + - patch + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflows + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflows/finalizers + verbs: + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflows/status + verbs: + - get + - patch + - update diff --git a/packages/kogito-serverless-operator/config/rbac/role_binding.yaml b/packages/kogito-serverless-operator/config/rbac/role_binding.yaml new file mode 100644 index 00000000000..d5925c3ac9a --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: manager-role +subjects: + - kind: ServiceAccount + name: controller-manager + namespace: system diff --git a/packages/kogito-serverless-operator/config/rbac/service_account.yaml b/packages/kogito-serverless-operator/config/rbac/service_account.yaml new file mode 100644 index 00000000000..7cd6025bfc4 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/service_account.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: controller-manager + namespace: system diff --git a/packages/kogito-serverless-operator/config/rbac/service_discovery_role.yaml b/packages/kogito-serverless-operator/config/rbac/service_discovery_role.yaml new file mode 100644 index 00000000000..ea72098fa29 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/service_discovery_role.yaml @@ -0,0 +1,58 @@ +--- +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/packages/kogito-serverless-operator/config/rbac/service_discovery_role_binding.yaml b/packages/kogito-serverless-operator/config/rbac/service_discovery_role_binding.yaml new file mode 100644 index 00000000000..00518a3ea47 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/service_discovery_role_binding.yaml @@ -0,0 +1,13 @@ +--- +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/packages/kogito-serverless-operator/config/rbac/sonataflow_editor_role.yaml b/packages/kogito-serverless-operator/config/rbac/sonataflow_editor_role.yaml new file mode 100644 index 00000000000..d7a1634d12b --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/sonataflow_editor_role.yaml @@ -0,0 +1,24 @@ +# 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/packages/kogito-serverless-operator/config/rbac/sonataflow_viewer_role.yaml b/packages/kogito-serverless-operator/config/rbac/sonataflow_viewer_role.yaml new file mode 100644 index 00000000000..f1cacbb89a5 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/sonataflow_viewer_role.yaml @@ -0,0 +1,20 @@ +# 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/packages/kogito-serverless-operator/config/rbac/sonataflowbuild_editor_role.yaml b/packages/kogito-serverless-operator/config/rbac/sonataflowbuild_editor_role.yaml new file mode 100644 index 00000000000..76fdb8dd3ef --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/sonataflowbuild_editor_role.yaml @@ -0,0 +1,24 @@ +# 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/packages/kogito-serverless-operator/config/rbac/sonataflowbuild_viewer_role.yaml b/packages/kogito-serverless-operator/config/rbac/sonataflowbuild_viewer_role.yaml new file mode 100644 index 00000000000..08fcc90e375 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/sonataflowbuild_viewer_role.yaml @@ -0,0 +1,20 @@ +# 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/packages/kogito-serverless-operator/config/rbac/sonataflowclusterplatform_editor_role.yaml b/packages/kogito-serverless-operator/config/rbac/sonataflowclusterplatform_editor_role.yaml new file mode 100644 index 00000000000..0218ffa5cea --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/sonataflowclusterplatform_editor_role.yaml @@ -0,0 +1,31 @@ +# 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/packages/kogito-serverless-operator/config/rbac/sonataflowclusterplatform_viewer_cluster_role_binding.yaml b/packages/kogito-serverless-operator/config/rbac/sonataflowclusterplatform_viewer_cluster_role_binding.yaml new file mode 100644 index 00000000000..27991fc0a01 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/sonataflowclusterplatform_viewer_cluster_role_binding.yaml @@ -0,0 +1,13 @@ +# 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/packages/kogito-serverless-operator/config/rbac/sonataflowclusterplatform_viewer_role.yaml b/packages/kogito-serverless-operator/config/rbac/sonataflowclusterplatform_viewer_role.yaml new file mode 100644 index 00000000000..72c7def9e12 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/sonataflowclusterplatform_viewer_role.yaml @@ -0,0 +1,27 @@ +# 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/packages/kogito-serverless-operator/config/rbac/sonataflowplatform_editor_role.yaml b/packages/kogito-serverless-operator/config/rbac/sonataflowplatform_editor_role.yaml new file mode 100644 index 00000000000..d0dd6550e47 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/sonataflowplatform_editor_role.yaml @@ -0,0 +1,24 @@ +# 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/packages/kogito-serverless-operator/config/rbac/sonataflowplatform_viewer_role.yaml b/packages/kogito-serverless-operator/config/rbac/sonataflowplatform_viewer_role.yaml new file mode 100644 index 00000000000..1f2edd009f9 --- /dev/null +++ b/packages/kogito-serverless-operator/config/rbac/sonataflowplatform_viewer_role.yaml @@ -0,0 +1,20 @@ +# 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/packages/kogito-serverless-operator/config/samples/kustomization.yaml b/packages/kogito-serverless-operator/config/samples/kustomization.yaml new file mode 100644 index 00000000000..13918f6235b --- /dev/null +++ b/packages/kogito-serverless-operator/config/samples/kustomization.yaml @@ -0,0 +1,7 @@ +## Append samples you want in your CSV to this file as resources ## +resources: + - sonataflow.org_v1alpha08_sonataflow.yaml + - sonataflow.org_v1alpha08_sonataflowplatform.yaml + - sonataflow.org_v1alpha08_sonataflowbuild.yaml + - sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml +#+kubebuilder:scaffold:manifestskustomizesamples diff --git a/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflow.yaml b/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflow.yaml new file mode 100644 index 00000000000..e094379fc14 --- /dev/null +++ b/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflow.yaml @@ -0,0 +1,42 @@ +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/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflow_devmodeWithConfigMapAndExternalResource.yaml b/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflow_devmodeWithConfigMapAndExternalResource.yaml new file mode 100644 index 00000000000..79f6cf80b6c --- /dev/null +++ b/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflow_devmodeWithConfigMapAndExternalResource.yaml @@ -0,0 +1,70 @@ +--- +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/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflowbuild.yaml b/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflowbuild.yaml new file mode 100644 index 00000000000..1b54d4ab0ec --- /dev/null +++ b/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflowbuild.yaml @@ -0,0 +1,6 @@ +apiVersion: sonataflow.org/v1alpha08 +kind: SonataFlowBuild +metadata: + name: greeting +spec: + timeout: 360s diff --git a/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml b/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml new file mode 100644 index 00000000000..2117a7a078a --- /dev/null +++ b/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml @@ -0,0 +1,8 @@ +apiVersion: sonataflow.org/v1alpha08 +kind: SonataFlowClusterPlatform +metadata: + name: sonataflow-clusterplatform +spec: + platformRef: + name: sonataflow-platform + namespace: sonataflow-operator-system diff --git a/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflowplatform.yaml b/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflowplatform.yaml new file mode 100644 index 00000000000..cc5b3cbb96c --- /dev/null +++ b/packages/kogito-serverless-operator/config/samples/sonataflow.org_v1alpha08_sonataflowplatform.yaml @@ -0,0 +1,10 @@ +apiVersion: sonataflow.org/v1alpha08 +kind: SonataFlowPlatform +metadata: + name: sonataflow-platform +spec: + build: + config: + registry: + address: quay.io/kiegroup + secret: regcred diff --git a/packages/kogito-serverless-operator/config/scorecard/bases/config.yaml b/packages/kogito-serverless-operator/config/scorecard/bases/config.yaml new file mode 100644 index 00000000000..707a5c25fd0 --- /dev/null +++ b/packages/kogito-serverless-operator/config/scorecard/bases/config.yaml @@ -0,0 +1,7 @@ +apiVersion: scorecard.operatorframework.io/v1alpha3 +kind: Configuration +metadata: + name: config +stages: + - parallel: true + tests: [] diff --git a/packages/kogito-serverless-operator/config/scorecard/kustomization.yaml b/packages/kogito-serverless-operator/config/scorecard/kustomization.yaml new file mode 100644 index 00000000000..ee7181bb3b0 --- /dev/null +++ b/packages/kogito-serverless-operator/config/scorecard/kustomization.yaml @@ -0,0 +1,16 @@ +resources: + - bases/config.yaml +patchesJson6902: + - 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:patchesJson6902 diff --git a/packages/kogito-serverless-operator/config/scorecard/patches/basic.config.yaml b/packages/kogito-serverless-operator/config/scorecard/patches/basic.config.yaml new file mode 100644 index 00000000000..9289982dc3a --- /dev/null +++ b/packages/kogito-serverless-operator/config/scorecard/patches/basic.config.yaml @@ -0,0 +1,10 @@ +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - basic-check-spec + image: quay.io/operator-framework/scorecard-test:v1.25.0 + labels: + suite: basic + test: basic-check-spec-test diff --git a/packages/kogito-serverless-operator/config/scorecard/patches/olm.config.yaml b/packages/kogito-serverless-operator/config/scorecard/patches/olm.config.yaml new file mode 100644 index 00000000000..a921027f024 --- /dev/null +++ b/packages/kogito-serverless-operator/config/scorecard/patches/olm.config.yaml @@ -0,0 +1,50 @@ +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-bundle-validation + image: quay.io/operator-framework/scorecard-test:v1.25.0 + labels: + suite: olm + test: olm-bundle-validation-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-crds-have-validation + image: quay.io/operator-framework/scorecard-test:v1.25.0 + labels: + suite: olm + test: olm-crds-have-validation-test +- op: add + path: /stages/0/tests/- + value: + 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 +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-spec-descriptors + image: quay.io/operator-framework/scorecard-test:v1.25.0 + labels: + suite: olm + test: olm-spec-descriptors-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-status-descriptors + image: quay.io/operator-framework/scorecard-test:v1.25.0 + labels: + suite: olm + test: olm-status-descriptors-test diff --git a/packages/kogito-serverless-operator/container-builder/Makefile b/packages/kogito-serverless-operator/container-builder/Makefile new file mode 100644 index 00000000000..c6b29c8df76 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/Makefile @@ -0,0 +1,39 @@ +.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 -v + +.PHONY: kaniko-docker-integration-test +kaniko-docker-integration-test: ## Test kaniko integration docker tests + go test ./... -tags integration_kaniko_docker diff --git a/packages/kogito-serverless-operator/container-builder/README.md b/packages/kogito-serverless-operator/container-builder/README.md new file mode 100644 index 00000000000..bd81dd1a733 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/README.md @@ -0,0 +1,157 @@ +# 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/packages/kogito-serverless-operator/container-builder/api/build_types.go b/packages/kogito-serverless-operator/container-builder/api/build_types.go new file mode 100644 index 00000000000..a90b1825b67 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/api/build_types.go @@ -0,0 +1,246 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 quay.io/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/packages/kogito-serverless-operator/container-builder/api/common_type.go b/packages/kogito-serverless-operator/container-builder/api/common_type.go new file mode 100644 index 00000000000..540c1c3da85 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/api/common_type.go @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/container-builder/api/doc.go b/packages/kogito-serverless-operator/container-builder/api/doc.go new file mode 100644 index 00000000000..75dfbd19cd9 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/api/doc.go @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/container-builder/api/platform_types.go b/packages/kogito-serverless-operator/container-builder/api/platform_types.go new file mode 100644 index 00000000000..51a47d328b4 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/api/platform_types.go @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/container-builder/api/zz_generated.deepcopy.go b/packages/kogito-serverless-operator/container-builder/api/zz_generated.deepcopy.go new file mode 100644 index 00000000000..46f2ddaea84 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/api/zz_generated.deepcopy.go @@ -0,0 +1,357 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT 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 ( + "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/packages/kogito-serverless-operator/container-builder/builder/kaniko_docker_integration_test.go b/packages/kogito-serverless-operator/container-builder/builder/kaniko_docker_integration_test.go new file mode 100644 index 00000000000..f5da34e6cae --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kaniko_docker_integration_test.go @@ -0,0 +1,88 @@ +//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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/common" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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) +} + +func checkImageOnDockerRegistry(suite *KanikoDockerTestSuite, imageName string, repos []string, registry common.RegistryContainer) { + pushErr := suite.Docker.PushImage(imageName, imageName, "", "") + assert.Nil(suite.T(), pushErr) + repos, _ = registry.GetRepositories() + assert.True(suite.T(), len(repos) == 1) +} + +func checkEmptyDockerRegistry(suite *KanikoDockerTestSuite) (common.RegistryContainer, error, []string) { + assert.Truef(suite.T(), suite.RegistryID != "", "Registry not started") + registry, err := common.GetRegistryContainer() + if err != nil { + klog.V(log.E).ErrorS(err, "registry not found") + } + repos, _ := registry.GetRepositories() + assert.True(suite.T(), len(repos) == 0) + assert.Nil(suite.T(), err) + return registry, err, repos +} diff --git a/packages/kogito-serverless-operator/container-builder/builder/kaniko_integration_test_suite.go b/packages/kogito-serverless-operator/container-builder/builder/kaniko_integration_test_suite.go new file mode 100644 index 00000000000..5683a7129a8 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kaniko_integration_test_suite.go @@ -0,0 +1,77 @@ +//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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/common" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kaniko_vanilla.go b/packages/kogito-serverless-operator/container-builder/builder/kaniko_vanilla.go new file mode 100644 index 00000000000..5d1a1035679 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kaniko_vanilla.go @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/action.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/action.go new file mode 100644 index 00000000000..9f79a808e1e --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/action.go @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/build_pod.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/build_pod.go new file mode 100644 index 00000000000..ada17847a8f --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/build_pod.go @@ -0,0 +1,185 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/builder.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/builder.go new file mode 100644 index 00000000000..7b35615fc20 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/builder.go @@ -0,0 +1,235 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/builder_kaniko.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/builder_kaniko.go new file mode 100644 index 00000000000..fde5c29cff6 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/builder_kaniko.go @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/builder_kaniko_test.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/builder_kaniko_test.go new file mode 100644 index 00000000000..a344829067e --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/builder_kaniko_test.go @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/util" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/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: "quay.io/kiegroup/buildexample: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/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: "quay.io/kiegroup/buildexample: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() + + // 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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/builder_test.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/builder_test.go new file mode 100644 index 00000000000..9d35004d2b9 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/builder_test.go @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/util/test" +) + +func TestNewBuild(t *testing.T) { + ns := "test" + c := test.NewFakeClient() + + dockerFile, err := os.ReadFile("testdata/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: "quay.io/kiegroup/buildexample: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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/env.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/env.go new file mode 100644 index 00000000000..70b303b3077 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/env.go @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/error.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/error.go new file mode 100644 index 00000000000..7cd43fe8665 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/error.go @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/initialize_pod.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/initialize_pod.go new file mode 100644 index 00000000000..aaee17571ce --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/initialize_pod.go @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/kaniko.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/kaniko.go new file mode 100644 index 00000000000..8898d62b762 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/kaniko.go @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/util/minikube" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/kanikoSecurityContext.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/kanikoSecurityContext.go new file mode 100644 index 00000000000..e6aa114ea4c --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/kanikoSecurityContext.go @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/monitor_pod.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/monitor_pod.go new file mode 100644 index 00000000000..6bb69e21e9c --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/monitor_pod.go @@ -0,0 +1,283 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/mount.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/mount.go new file mode 100644 index 00000000000..57e204c4448 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/mount.go @@ -0,0 +1,188 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/mount_test.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/mount_test.go new file mode 100644 index 00000000000..b0ebf123424 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/mount_test.go @@ -0,0 +1,178 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/recovery.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/recovery.go new file mode 100644 index 00000000000..851a1eba49f --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/recovery.go @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/util/log" + + "github.com/jpillora/backoff" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/schedule.go b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/schedule.go new file mode 100644 index 00000000000..f583a5c42a7 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/schedule.go @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/builder/kubernetes/testdata/Dockerfile b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/testdata/Dockerfile new file mode 100644 index 00000000000..80d51e15b50 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/testdata/Dockerfile @@ -0,0 +1,49 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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 quay.io/kiegroup/kogito-swf-builder-nightly:latest AS builder + +# Kogito User +USER 1001 + +# User home from base image +WORKDIR /home/kogito/kogito-sw-base + +# Copy from build context to skeleton project +COPY * ./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-sw-base/target/quarkus-app/lib/ /deployments/lib/ +COPY --from=builder --chown=185 /home/kogito/kogito-sw-base/target/quarkus-app/*.jar /deployments/ +COPY --from=builder --chown=185 /home/kogito/kogito-sw-base/target/quarkus-app/app/ /deployments/app/ +COPY --from=builder --chown=185 /home/kogito/kogito-sw-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" \ No newline at end of file diff --git a/packages/kogito-serverless-operator/container-builder/builder/kubernetes/testdata/greetings.sw.json b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/testdata/greetings.sw.json new file mode 100644 index 00000000000..a619b3b8bc7 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/builder/kubernetes/testdata/greetings.sw.json @@ -0,0 +1,67 @@ +{ + "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/packages/kogito-serverless-operator/container-builder/cleaner/cleaner.go b/packages/kogito-serverless-operator/container-builder/cleaner/cleaner.go new file mode 100644 index 00000000000..8dfb4e690b8 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/cleaner/cleaner.go @@ -0,0 +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. + */ + +package cleaner + +type RegistryCleaner interface { + RemoveImagesUntagged() (bool, error) + RemoveDanglingImages() (bool, error) + PurgeImages() (bool, error) + RemoveImagesFiltered(repo string, tag string) (bool, error) +} diff --git a/packages/kogito-serverless-operator/container-builder/cleaner/docker_integration_test.go b/packages/kogito-serverless-operator/container-builder/cleaner/docker_integration_test.go new file mode 100644 index 00000000000..797f6aa09c3 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/cleaner/docker_integration_test.go @@ -0,0 +1,84 @@ +//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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/common" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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() { + registryContainer, err := common.GetRegistryContainer() + assert.NotNil(suite.T(), registryContainer) + assert.Nil(suite.T(), err) + repos, err := registryContainer.GetRepositories() + initialSize := len(repos) + assert.Nil(suite.T(), err) + 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") + //give the time to update the registry status + time.Sleep(2 * time.Second) + repos, err = registryContainer.GetRepositories() + assert.Nil(suite.T(), err) + assert.NotNil(suite.T(), repos) + assert.True(suite.T(), len(repos) == initialSize+1) + + digest, erroDIgest := registryContainer.Connection.ManifestDigest(testImg, latestTag) + assert.Nil(suite.T(), erroDIgest) + assert.NotNil(suite.T(), digest) + assert.NotNil(suite.T(), registryContainer.DeleteImage(testImg, latestTag), "Delete Image not allowed") +} diff --git a/packages/kogito-serverless-operator/container-builder/cleaner/docker_integration_test_suite.go b/packages/kogito-serverless-operator/container-builder/cleaner/docker_integration_test_suite.go new file mode 100644 index 00000000000..b7e63ae153c --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/cleaner/docker_integration_test_suite.go @@ -0,0 +1,63 @@ +//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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/common" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/cleaner/registry_docker_integration_test.go b/packages/kogito-serverless-operator/container-builder/cleaner/registry_docker_integration_test.go new file mode 100644 index 00000000000..de0a2c76922 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/cleaner/registry_docker_integration_test.go @@ -0,0 +1,93 @@ +//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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/common" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/util/log" +) + +const ( + testImgSecond = "alpine" + testImgSecondTag = "alpine:latest" + testImgSecondLocalTag = "localhost:5000/alpine:latest" +) + +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") +} + +func (suite *DockerTestSuite) TestPullTagPush() { + assert.Truef(suite.T(), suite.RegistryID != "", "Registry not started") + registryContainer, err := common.GetRegistryContainer() + assert.Nil(suite.T(), err) + reposInitial, _ := registryContainer.GetRepositories() + initialRepoSize := len(reposInitial) + repos := CheckRepositoriesSize(suite.T(), initialRepoSize, registryContainer) + + result := dockerPullTagPushOnRegistryContainer(suite) + assert.True(suite.T(), result) + + time.Sleep(2 * time.Second) // Needed on CI + repos = CheckRepositoriesSize(suite.T(), initialRepoSize+1, registryContainer) + klog.V(log.I).InfoS("Repo Size after pull image", "size", len(repos)) +} + +func dockerPullTagPushOnRegistryContainer(suite *DockerTestSuite) bool { + dockerSocketConn := suite.Docker.Connection + d := common.Docker{Connection: dockerSocketConn} + + err := d.PullImage(testImgSecond) + time.Sleep(2 * time.Second) // needed on CI + if err != nil { + assert.Fail(suite.T(), "Pull Image Failed", err) + return false + } + + err = d.TagImage(testImgSecondTag, testImgSecondLocalTag) + if err != nil { + assert.Fail(suite.T(), "Tag Image Failed", err) + return false + } + + err = d.PushImage(testImgSecondLocalTag, common.RegistryContainerUrlFromDockerSocket, "", "") + if err != nil { + assert.Fail(suite.T(), "Push Image Failed", err) + return false + } + return true +} diff --git a/packages/kogito-serverless-operator/container-builder/cleaner/test_utils.go b/packages/kogito-serverless-operator/container-builder/cleaner/test_utils.go new file mode 100644 index 00000000000..73431e97361 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/cleaner/test_utils.go @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/common" + + "github.com/stretchr/testify/assert" +) + +func CheckRepositoriesSize(t *testing.T, size int, registryContainer common.RegistryContainer) []string { + repos, err := registryContainer.GetRepositories() + assert.Nil(t, err, "Error calling GetRepositories()") + assert.True(t, len(repos) == size) + return repos +} diff --git a/packages/kogito-serverless-operator/container-builder/client/client.go b/packages/kogito-serverless-operator/container-builder/client/client.go new file mode 100644 index 00000000000..077db005315 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/client/client.go @@ -0,0 +1,227 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/client/fastmapper.go b/packages/kogito-serverless-operator/container-builder/client/fastmapper.go new file mode 100644 index 00000000000..3fc7d2bf587 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/client/fastmapper.go @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/common/docker.go b/packages/kogito-serverless-operator/container-builder/common/docker.go new file mode 100644 index 00000000000..27e0739126b --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/common/docker.go @@ -0,0 +1,232 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/util" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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 = types.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/packages/kogito-serverless-operator/container-builder/common/registry.go b/packages/kogito-serverless-operator/container-builder/common/registry.go new file mode 100644 index 00000000000..d1bcb9463ac --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/common/registry.go @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + "net/http" + "os" + "time" + + "k8s.io/klog/v2" + + "github.com/docker/docker/client" + registryContainer "github.com/heroku/docker-registry-client/registry" + "github.com/opencontainers/go-digest" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/util/log" +) + +const ( + RegistryContainerUrlFromDockerSocket = "tcp://localhost:5000" + RegistryImg = "registry" + registryImgFullTag = "docker.io/library/registry:latest" + registryContainerUrl = "http://localhost:5000" +) + +type Registry interface { + StartRegistry() + StopRegistry() +} + +type DockerLocalRegistry struct { + Connection *client.Client +} + +type RegistryContainer struct { + Connection registryContainer.Registry + URL string + Client *http.Client +} + +func (r RegistryContainer) GetRepositories() ([]string, error) { + return r.Connection.Repositories() +} + +func (r RegistryContainer) GetRepositoriesTags(repo string) ([]string, error) { + return r.Connection.Tags(repo) +} + +func (r RegistryContainer) DeleteManifest(repo string, tag string) error { + digest, error := r.Connection.ManifestDigest(repo, tag) + if error != nil { + return error + } + return r.Connection.DeleteManifest(repo, digest) +} + +func (r RegistryContainer) DeleteImageByDigest(repository string, digest digest.Digest) error { + url := r.url("/v2/%s/manifests/%s", repository, digest) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return err + } + resp, err := r.Connection.Client.Do(req) + if resp != nil { + defer resp.Body.Close() + } + if err != nil { + return err + } + return nil +} + +func (r RegistryContainer) DeleteImage(repository string, tag string) error { + url := r.url("/v2/%s/manifests/%s", repository, tag) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return err + } + resp, err := r.Connection.Client.Do(req) + if resp != nil { + defer resp.Body.Close() + } + if err != nil { + klog.V(log.E).ErrorS(err, "error during DeleteImage") + return err + } + return nil +} + +func (r *RegistryContainer) url(pathTemplate string, args ...interface{}) string { + pathSuffix := fmt.Sprintf(pathTemplate, args...) + url := fmt.Sprintf("%s%s", r.Connection.URL, pathSuffix) + return url +} + +func GetRegistryContainer() (RegistryContainer, error) { + registryContainerConnection, err := GetRegistryConnection(registryContainerUrl, "", "") + if err != nil { + klog.V(log.E).ErrorS(err, "Can't connect to the RegistryContainer") + return RegistryContainer{}, err + } + return RegistryContainer{Connection: *registryContainerConnection}, nil +} + +func IsPortAvailable(port string) bool { + ln, err := net.Listen("tcp", ":"+port) + if err != nil { + fmt.Fprintf(os.Stderr, "Can't listen on port %q: %s", port, err) + return false + } + ln.Close() + return true +} + +func GetRegistryConnection(url string, username string, password string) (*registryContainer.Registry, error) { + registryConn, err := registryContainer.New(url, username, password) + if err != nil { + klog.V(log.E).ErrorS(err, "First Attempt to connect with RegistryContainer") + } + // we try ten times if the machine is slow and the registry needs time to start + if err != nil { + klog.V(log.I).InfoS("Waiting for a correct ping with RegistryContainer") + + for i := 0; i < 10; i++ { + time.Sleep(1 * time.Second) + if registryConn == nil { + registryConn, _ = registryContainer.New(url, username, password) + } + if registryConn != nil { + if err := registryConn.Ping(); err != nil { + continue + } + } + } + } + return registryConn, err +} diff --git a/packages/kogito-serverless-operator/container-builder/common/registry_docker.go b/packages/kogito-serverless-operator/container-builder/common/registry_docker.go new file mode 100644 index 00000000000..4ab893d09e4 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/common/registry_docker.go @@ -0,0 +1,226 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/examples/api/Build_usingKanikowithCacheAndCustomizations.yaml b/packages/kogito-serverless-operator/container-builder/examples/api/Build_usingKanikowithCacheAndCustomizations.yaml new file mode 100644 index 00000000000..4e4bc69826e --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/examples/api/Build_usingKanikowithCacheAndCustomizations.yaml @@ -0,0 +1,15 @@ +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/packages/kogito-serverless-operator/container-builder/examples/api/PlatformBuild_usingKanikowithCache.yaml b/packages/kogito-serverless-operator/container-builder/examples/api/PlatformBuild_usingKanikowithCache.yaml new file mode 100644 index 00000000000..788da52bba7 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/examples/api/PlatformBuild_usingKanikowithCache.yaml @@ -0,0 +1,9 @@ +name: platform-kaniko-using-cache +spec: + publishStrategy: "Kaniko" + baseImage: quay.io/kiegroup/kogito-swf-builder-nightly:latest + registry: + address: quay.io/kiegroup + secret: regcred + PublishStrategyOptions: + KanikoBuildCacheEnabled: "true" diff --git a/packages/kogito-serverless-operator/container-builder/examples/app.yaml b/packages/kogito-serverless-operator/container-builder/examples/app.yaml new file mode 100644 index 00000000000..5e93dd8f9ab --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/examples/app.yaml @@ -0,0 +1,28 @@ +# 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/packages/kogito-serverless-operator/container-builder/examples/dockerfiles/SonataFlow.dockerfile b/packages/kogito-serverless-operator/container-builder/examples/dockerfiles/SonataFlow.dockerfile new file mode 100644 index 00000000000..6ca872b26dc --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/examples/dockerfiles/SonataFlow.dockerfile @@ -0,0 +1,48 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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 quay.io/kiegroup/kogito-swf-builder-nightly:latest 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/packages/kogito-serverless-operator/container-builder/examples/service.yaml b/packages/kogito-serverless-operator/container-builder/examples/service.yaml new file mode 100644 index 00000000000..c9702464535 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/examples/service.yaml @@ -0,0 +1,39 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/container-builder/examples/sources/sonataflowgreetings.sw.json b/packages/kogito-serverless-operator/container-builder/examples/sources/sonataflowgreetings.sw.json new file mode 100644 index 00000000000..a619b3b8bc7 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/examples/sources/sonataflowgreetings.sw.json @@ -0,0 +1,67 @@ +{ + "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/packages/kogito-serverless-operator/container-builder/go.mod b/packages/kogito-serverless-operator/container-builder/go.mod new file mode 100644 index 00000000000..447c53ba5eb --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/go.mod @@ -0,0 +1,90 @@ +module github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder + +go 1.21 + +require ( + github.com/docker/docker v24.0.9+incompatible + github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11 + github.com/google/uuid v1.3.1 + github.com/heroku/docker-registry-client v0.0.0-20211012143308-9463674c8930 + github.com/jpillora/backoff v1.0.0 + github.com/mitchellh/go-homedir v1.1.0 + github.com/opencontainers/go-digest v1.0.0 + github.com/pkg/errors v0.9.1 + github.com/stretchr/testify v1.8.4 + golang.org/x/net v0.17.0 + k8s.io/api v0.27.6 + k8s.io/apimachinery v0.27.6 + k8s.io/client-go v0.27.6 + k8s.io/klog/v2 v2.100.1 + sigs.k8s.io/controller-runtime v0.15.0 +) + +require ( + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect + github.com/emicklei/go-restful/v3 v3.10.2 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.7.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-logr/logr v1.2.4 // 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.3 // indirect + github.com/google/gnostic v0.6.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 // indirect + github.com/gorilla/mux v1.8.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/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/moby/spdystream v0.2.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/onsi/ginkgo/v2 v2.13.0 // indirect + github.com/onsi/gomega v1.30.0 // indirect + github.com/opencontainers/image-spec v1.1.0-rc2 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.11.1 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.26.0 // indirect + golang.org/x/mod v0.13.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.14.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.33.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.0.3 // indirect + k8s.io/apiextensions-apiserver v0.27.6 // indirect + k8s.io/component-base v0.27.6 // indirect + k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 // indirect + k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/packages/kogito-serverless-operator/container-builder/go.sum b/packages/kogito-serverless-operator/container-builder/go.sum new file mode 100644 index 00000000000..54cd5675dd1 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/go.sum @@ -0,0 +1,490 @@ +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= +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/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OpenPeeDeeP/depguard v1.0.0/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +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/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +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/docker/distribution v0.0.0-20171011171712-7484e51bf6af/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= +github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0= +github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11 h1:IPrmumsT9t5BS7XcPhgsCTlkWbYg80SEXUzDpReaU6Y= +github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11/go.mod h1:a6bNUGTbQBsY6VRHTr4h/rkOXjl244DyRD0tx3fgq4Q= +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/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= +github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE= +github.com/emicklei/go-restful/v3 v3.10.2/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/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +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.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= +github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-critic/go-critic v0.3.5-0.20190526074819-1df300866540/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA= +github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +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 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-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= +github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= +github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg= +github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= +github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= +github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk= +github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= +github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks= +github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +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-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.0.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +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.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/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= +github.com/golangci/go-tools v0.0.0-20190318055746-e32c54105b7c/go.mod h1:unzUULGw35sjyOYjUt0jMTXqHlZPpPc6e+xfO4cd6mM= +github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o= +github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= +github.com/golangci/gofmt v0.0.0-20181222123516-0b8337e80d98/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= +github.com/golangci/golangci-lint v1.17.2-0.20190909185456-6163a8a79084/go.mod h1:jXakAOSd+FMU9dP3D6IfBK7HyD1q/RLHI9NOY8veycY= +github.com/golangci/gosec v0.0.0-20190211064107-66fb7fc33547/go.mod h1:0qUabqiIQgfmlAmulqxyiGkkyF6/tOGSnY2cnPVwrzU= +github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= +github.com/golangci/lint-1 v0.0.0-20190420132249-ee948d087217/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI= +github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= +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.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.5.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-20230705174524-200ffdc848b8 h1:n6vlPhxsA+BW/XsS5+uqi7GyzaLa5MH7qlSLBZtRdiA= +github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= +github.com/heroku/docker-registry-client v0.0.0-20211012143308-9463674c8930 h1:mNL9ktJqBuzPTV/QP/fKd4y1uOFvfiv6zhe0G7lg9OA= +github.com/heroku/docker-registry-client v0.0.0-20211012143308-9463674c8930/go.mod h1:Yho0S7KhsnHQRCC5lDraYF1SsLMeWtf/tKdufKu3TJA= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +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/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +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 v0.0.0-20161130080628-0de1eaf82fa3/go.mod h1:jxZFDH7ILpTPQTk+E2s+z4CUas9lVNjIuKR4c5/zKgM= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +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/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= +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/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +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/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= +github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587/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/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= +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/nbutton23/zxcvbn-go v0.0.0-20160627004424-a22cb81b2ecd/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +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-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= +github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +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.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= +github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +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/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +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/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.0/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.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= +github.com/ultraware/funlen v0.0.1/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= +github.com/valyala/quicktemplate v1.1.1/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +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/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +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-20190313024323-a1f597ede03a/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-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +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-20180911220305-26e67e76b6c3/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-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +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-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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +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-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.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +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-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-20190507160741-ecd444e8653b/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-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/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.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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20170915040203-e531a2a1c15f/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/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-20190121143147-24cd39ecf745/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-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +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.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +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/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.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +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.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +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/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +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.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.0-20200615113413-eeeca48fe776/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.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/api v0.27.6 h1:PBWu/lywJe2qQcshMjubzcBg7+XDZOo7O8JJAWuYtUo= +k8s.io/api v0.27.6/go.mod h1:AQYj0UsFCp3qJE7bOVnUuy4orCsXVkvHefnbYQiNWgk= +k8s.io/apiextensions-apiserver v0.27.6 h1:mOwSBJtThZhpJr+8gEkc3wFDIjq87E3JspR5mtZxIg8= +k8s.io/apiextensions-apiserver v0.27.6/go.mod h1:AVNlLYRrESG5Poo6ASRUhY2pvoKPcNt8y/IuZ4lx3o8= +k8s.io/apimachinery v0.27.6 h1:mGU8jmBq5o8mWBov+mLjdTBcU+etTE19waies4AQ6NE= +k8s.io/apimachinery v0.27.6/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= +k8s.io/client-go v0.27.6 h1:vzI8804gpUtpMCNaFjIFyJrifH7u//LJCJPy8fQuYQg= +k8s.io/client-go v0.27.6/go.mod h1:PMsXcDKiJTW7PHJ64oEsIUJF319wm+EFlCj76oE5QXM= +k8s.io/component-base v0.27.6 h1:hF5WxX7Tpi9/dXAbLjPVkIA6CA6Pi6r9JOHyo0uCDYI= +k8s.io/component-base v0.27.6/go.mod h1:NvjLtaneUeb0GgMPpCBF+4LNB9GuhDHi16uUTjBhQfU= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 h1:OmK1d0WrkD3IPfkskvroRykOulHVHf0s0ZIFRjyt+UI= +k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515/go.mod h1:kzo02I3kQ4BTtEfVLaPbjvCkX97YqGve33wzlb3fofQ= +k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc= +k8s.io/utils v0.0.0-20230711102312-30195339c3c7/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34/go.mod h1:H6SUd1XjIs+qQCyskXg5OFSrilMRUkD8ePJpHKDPaeY= +sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= +sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +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.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= +sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +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/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/packages/kogito-serverless-operator/container-builder/hack/boilerplate.go.txt b/packages/kogito-serverless-operator/container-builder/hack/boilerplate.go.txt new file mode 100644 index 00000000000..7220975503b --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/hack/boilerplate.go.txt @@ -0,0 +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. + */ \ No newline at end of file diff --git a/packages/kogito-serverless-operator/container-builder/hack/btrfs_installed_tag.sh b/packages/kogito-serverless-operator/container-builder/hack/btrfs_installed_tag.sh new file mode 100755 index 00000000000..0073717f76a --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/hack/btrfs_installed_tag.sh @@ -0,0 +1,24 @@ +#!/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/packages/kogito-serverless-operator/container-builder/hack/btrfs_tag.sh b/packages/kogito-serverless-operator/container-builder/hack/btrfs_tag.sh new file mode 100755 index 00000000000..479fee3c550 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/hack/btrfs_tag.sh @@ -0,0 +1,24 @@ +#!/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/packages/kogito-serverless-operator/container-builder/main.go b/packages/kogito-serverless-operator/container-builder/main.go new file mode 100644 index 00000000000..72b32df36d5 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/main.go @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/util/log/log.go b/packages/kogito-serverless-operator/container-builder/util/log/log.go new file mode 100644 index 00000000000..544fea7b7f5 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/util/log/log.go @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/container-builder/util/minikube/registry.go b/packages/kogito-serverless-operator/container-builder/util/minikube/registry.go new file mode 100644 index 00000000000..8bc98930f10 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/util/minikube/registry.go @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/util/registry/kep_1755.go b/packages/kogito-serverless-operator/container-builder/util/registry/kep_1755.go new file mode 100644 index 00000000000..64c4eefa843 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/util/registry/kep_1755.go @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/util/test/client.go b/packages/kogito-serverless-operator/container-builder/util/test/client.go new file mode 100644 index 00000000000..d993f862682 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/util/test/client.go @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/container-builder/util/util.go b/packages/kogito-serverless-operator/container-builder/util/util.go new file mode 100644 index 00000000000..5da6d54b778 --- /dev/null +++ b/packages/kogito-serverless-operator/container-builder/util/util.go @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/builder/builder.go b/packages/kogito-serverless-operator/controllers/builder/builder.go new file mode 100644 index 00000000000..e7e46f64760 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/builder/builder.go @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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) + 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/packages/kogito-serverless-operator/controllers/builder/config.go b/packages/kogito-serverless-operator/controllers/builder/config.go new file mode 100644 index 00000000000..d6590f8ef53 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/builder/config.go @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/cfg" + "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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/controllers/builder/containerbuilder.go b/packages/kogito-serverless-operator/controllers/builder/containerbuilder.go new file mode 100644 index 00000000000..20d60bba0ec --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/builder/containerbuilder.go @@ -0,0 +1,215 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/cfg" + "k8s.io/klog/v2" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/workflowdef" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/rest" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + clientr "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/api" + builder "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/builder/kubernetes" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" +) + +const ( + resourceDockerfile = "Dockerfile" +) + +var _ BuildManager = &containerBuilderManager{} + +type kanikoBuildInput struct { + name string + task *api.KanikoTask + workflowDefinition []byte + workflow *operatorapi.SonataFlow + 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, + 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) + } + + 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) +} diff --git a/packages/kogito-serverless-operator/controllers/builder/kogitoserverlessbuild_manager.go b/packages/kogito-serverless-operator/controllers/builder/kogitoserverlessbuild_manager.go new file mode 100644 index 00000000000..5d452de0b36 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/builder/kogitoserverlessbuild_manager.go @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apimachinery/pkg/api/errors" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" +) + +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); err != nil { + return nil, err + } + buildInstance.Spec.BuildTemplate = plat.Spec.Build.Template + 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, + } +} diff --git a/packages/kogito-serverless-operator/controllers/builder/openshiftbuilder.go b/packages/kogito-serverless-operator/controllers/builder/openshiftbuilder.go new file mode 100644 index 00000000000..d6f968f64ed --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/builder/openshiftbuilder.go @@ -0,0 +1,295 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/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/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj" + + kubeutil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/workflowdef" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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 { + if len(workflow.Spec.Resources.ConfigMaps) == 0 { + return nil + } + var configMapSources []buildv1.ConfigMapBuildSource + for _, workflowRes := range workflow.Spec.Resources.ConfigMaps { + configMapSources = append(configMapSources, buildv1.ConfigMapBuildSource{ + ConfigMap: workflowRes.ConfigMap, + DestinationDir: workflowRes.WorkflowPath, + }) + } + 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/packages/kogito-serverless-operator/controllers/builder/openshiftbuilder_test.go b/packages/kogito-serverless-operator/controllers/builder/openshiftbuilder_test.go new file mode 100644 index 00000000000..4dac25a7095 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/builder/openshiftbuilder_test.go @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/workflowdef" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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}}) + + 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, 1) +} + +func Test_openshiftbuilder_forcePull(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)) + + 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/packages/kogito-serverless-operator/controllers/cfg/controllers_cfg.go b/packages/kogito-serverless-operator/controllers/cfg/controllers_cfg.go new file mode 100644 index 00000000000..6ec5414e7f5 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/cfg/controllers_cfg.go @@ -0,0 +1,95 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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" + "os" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "github.com/imdario/mergo" + "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/klog/v2" +) + +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", + BuilderConfigMapName: "sonataflow-operator-builder-config", +} + +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"` + SonataFlowBaseBuilderImageTag string `yaml:"sonataFlowBaseBuilderImageTag,omitempty"` + SonataFlowDevModeImageTag string `yaml:"sonataFlowDevModeImageTag,omitempty"` + BuilderConfigMapName string `yaml:"builderConfigMapName,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 + } + 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, main.go calls InitializeControllersCfg to set the cache. + if controllersCfg == nil { + return defaultControllersCfg + } + return controllersCfg +} diff --git a/packages/kogito-serverless-operator/controllers/cfg/controllers_cfg_test.go b/packages/kogito-serverless-operator/controllers/cfg/controllers_cfg_test.go new file mode 100644 index 00000000000..d2d092dc8e9 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/cfg/controllers_cfg_test.go @@ -0,0 +1,52 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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) +} + +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/packages/kogito-serverless-operator/controllers/cfg/testdata/controllers-cfg-invalid.yaml b/packages/kogito-serverless-operator/controllers/cfg/testdata/controllers-cfg-invalid.yaml new file mode 100644 index 00000000000..3d10351d14c --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/cfg/testdata/controllers-cfg-invalid.yaml @@ -0,0 +1,15 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/controllers/cfg/testdata/controllers-cfg-test.yaml b/packages/kogito-serverless-operator/controllers/cfg/testdata/controllers-cfg-test.yaml new file mode 100644 index 00000000000..66ec30d8e34 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/cfg/testdata/controllers-cfg-test.yaml @@ -0,0 +1,23 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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" diff --git a/packages/kogito-serverless-operator/controllers/clusterplatform/action.go b/packages/kogito-serverless-operator/controllers/clusterplatform/action.go new file mode 100644 index 00000000000..81c128713e6 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/clusterplatform/action.go @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + + v08 "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/controllers/clusterplatform/clusterplatform.go b/packages/kogito-serverless-operator/controllers/clusterplatform/clusterplatform.go new file mode 100644 index 00000000000..ef8bd5a9ff5 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/clusterplatform/clusterplatform.go @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + PlatformServices operatorapi.WorkFlowCapability = "services" +) + +// GetActiveClusterPlatform returns the currently installed active cluster platform. +func GetActiveClusterPlatform(ctx context.Context, c ctrl.Client) (*operatorapi.SonataFlowClusterPlatform, error) { + return getClusterPlatform(ctx, c, true) +} + +// getClusterPlatform returns the currently active cluster platform or any cluster platform existing in the cluster. +func getClusterPlatform(ctx context.Context, c ctrl.Client, active bool) (*operatorapi.SonataFlowClusterPlatform, error) { + klog.V(log.D).InfoS("Finding available cluster platforms") + + lst, err := listPrimaryClusterPlatforms(ctx, c) + 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, c ctrl.Reader) (*operatorapi.SonataFlowClusterPlatformList, error) { + lst, err := listAllClusterPlatforms(ctx, c) + 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, c ctrl.Reader) bool { + lst, err := listAllClusterPlatforms(ctx, c) + 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, c ctrl.Reader) (*operatorapi.SonataFlowClusterPlatformList, error) { + lst := operatorapi.NewSonataFlowClusterPlatformList() + if err := c.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/packages/kogito-serverless-operator/controllers/clusterplatform/defaults.go b/packages/kogito-serverless-operator/controllers/clusterplatform/defaults.go new file mode 100644 index 00000000000..0bc2c74c34e --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/clusterplatform/defaults.go @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime/pkg/client" +) + +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/packages/kogito-serverless-operator/controllers/clusterplatform/initialize.go b/packages/kogito-serverless-operator/controllers/clusterplatform/initialize.go new file mode 100644 index 00000000000..fd38fed402e --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/clusterplatform/initialize.go @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "k8s.io/klog/v2" +) + +// 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, action.client) +} + +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().MarkTrueWithReason(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().MarkFalse(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().MarkUnknown(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, action.client) + 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/packages/kogito-serverless-operator/controllers/const.go b/packages/kogito-serverless-operator/controllers/const.go new file mode 100644 index 00000000000..55dafef1b79 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/const.go @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package controllers + +const ( + // ComponentName just a name to identify this package/component/application + ComponentName = "sonataflow-manager" +) diff --git a/packages/kogito-serverless-operator/controllers/discovery/discovery.go b/packages/kogito-serverless-operator/controllers/discovery/discovery.go new file mode 100644 index 00000000000..6d5dba33179 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/discovery.go @@ -0,0 +1,246 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/discovery/discovery_knative_test.go b/packages/kogito-serverless-operator/controllers/discovery/discovery_knative_test.go new file mode 100644 index 00000000000..6fc281f3e5b --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/discovery_knative_test.go @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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{ + 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/packages/kogito-serverless-operator/controllers/discovery/discovery_openshift_test.go b/packages/kogito-serverless-operator/controllers/discovery/discovery_openshift_test.go new file mode 100644 index 00000000000..ac54da721f1 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/discovery_openshift_test.go @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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:80") +} + +func Test_QueryOpenShiftRouteWithTLS(t *testing.T) { + doTestQueryOpenShiftRoute(t, true, "https://openshiftroutehost1:443") +} + +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/packages/kogito-serverless-operator/controllers/discovery/discovery_test.go b/packages/kogito-serverless-operator/controllers/discovery/discovery_test.go new file mode 100644 index 00000000000..12175ca1f71 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/discovery_test.go @@ -0,0 +1,258 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/discovery/knative_catalog.go b/packages/kogito-serverless-operator/controllers/discovery/knative_catalog.go new file mode 100644 index 00000000000..730e445fb64 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/knative_catalog.go @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/knative" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "k8s.io/client-go/rest" + "k8s.io/klog/v2" + + 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/packages/kogito-serverless-operator/controllers/discovery/kubernetes_catalog.go b/packages/kogito-serverless-operator/controllers/discovery/kubernetes_catalog.go new file mode 100644 index 00000000000..077adbf7249 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/kubernetes_catalog.go @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/discovery/kubernetes_constants.go b/packages/kogito-serverless-operator/controllers/discovery/kubernetes_constants.go new file mode 100644 index 00000000000..78d472d169e --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/kubernetes_constants.go @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/discovery/openshift_catalog.go b/packages/kogito-serverless-operator/controllers/discovery/openshift_catalog.go new file mode 100644 index 00000000000..7514f70fe10 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/openshift_catalog.go @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/openshift" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + appsv1 "github.com/openshift/client-go/apps/clientset/versioned/typed/apps/v1" + routev1 "github.com/openshift/client-go/route/clientset/versioned/typed/route/v1" + + 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 + port := defaultHttpPort + if route.Spec.TLS != nil { + scheme = httpsProtocol + port = defaultHttpsPort + } + return buildURI(scheme, route.Spec.Host, port), 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/packages/kogito-serverless-operator/controllers/discovery/port_utils.go b/packages/kogito-serverless-operator/controllers/discovery/port_utils.go new file mode 100644 index 00000000000..0a966c90a65 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/port_utils.go @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" + corev1 "k8s.io/api/core/v1" +) + +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/packages/kogito-serverless-operator/controllers/discovery/port_utils_test.go b/packages/kogito-serverless-operator/controllers/discovery/port_utils_test.go new file mode 100644 index 00000000000..9e01b9bcb94 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/port_utils_test.go @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/discovery/queries.go b/packages/kogito-serverless-operator/controllers/discovery/queries.go new file mode 100644 index 00000000000..37a7e1a6902 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/queries.go @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/discovery/queries_test.go b/packages/kogito-serverless-operator/controllers/discovery/queries_test.go new file mode 100644 index 00000000000..b0500b78e52 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/queries_test.go @@ -0,0 +1,281 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/discovery/test_utils.go b/packages/kogito-serverless-operator/controllers/discovery/test_utils.go new file mode 100644 index 00000000000..c05fea11c80 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/test_utils.go @@ -0,0 +1,211 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/discovery/uri_parser.go b/packages/kogito-serverless-operator/controllers/discovery/uri_parser.go new file mode 100644 index 00000000000..09f9aec0c77 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/uri_parser.go @@ -0,0 +1,242 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/discovery/uri_parser_test.go b/packages/kogito-serverless-operator/controllers/discovery/uri_parser_test.go new file mode 100644 index 00000000000..4b80e3ca34f --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/uri_parser_test.go @@ -0,0 +1,330 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/discovery/uri_utils.go b/packages/kogito-serverless-operator/controllers/discovery/uri_utils.go new file mode 100644 index 00000000000..8c0f442fbff --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/uri_utils.go @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" + corev1 "k8s.io/api/core/v1" +) + +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/packages/kogito-serverless-operator/controllers/discovery/uri_utils_test.go b/packages/kogito-serverless-operator/controllers/discovery/uri_utils_test.go new file mode 100644 index 00000000000..3d2961147c6 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/discovery/uri_utils_test.go @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/knative/knative.go b/packages/kogito-serverless-operator/controllers/knative/knative.go new file mode 100644 index 00000000000..929a96cc5d0 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/knative/knative.go @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" + clienteventingv1 "knative.dev/eventing/pkg/client/clientset/versioned/typed/eventing/v1" + clientservingv1 "knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1" +) + +var servingClient clientservingv1.ServingV1Interface +var eventingClient clienteventingv1.EventingV1Interface + +type Availability struct { + Eventing bool + Serving bool +} + +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 := discovery.NewDiscoveryClientForConfig(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 == "serving.knative.dev" { + result.Serving = true + } + if group.Name == "eventing.knative.dev" { + result.Eventing = true + } + } + return result, nil + } +} diff --git a/packages/kogito-serverless-operator/controllers/openshift/openshift.go b/packages/kogito-serverless-operator/controllers/openshift/openshift.go new file mode 100644 index 00000000000..57abc481e91 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/openshift/openshift.go @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/platform/action.go b/packages/kogito-serverless-operator/controllers/platform/action.go new file mode 100644 index 00000000000..b4c1e5a7b5a --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/action.go @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + + v08 "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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 platform + CanHandle(platform *v08.SonataFlowPlatform) bool + + // executes the handling function + Handle(ctx context.Context, platform *v08.SonataFlowPlatform) (*v08.SonataFlowPlatform, error) +} + +type baseAction struct { + client client.Client +} + +func (action *baseAction) InjectClient(client client.Client) { + action.client = client +} diff --git a/packages/kogito-serverless-operator/controllers/platform/create.go b/packages/kogito-serverless-operator/controllers/platform/create.go new file mode 100644 index 00000000000..c66c38d40ce --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/create.go @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + v08 "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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, error) { + //TODO: Perform the actions needed for the Platform creation + platform.Status.Manager().MarkTrue(api.SucceedConditionType) + + return platform, nil +} diff --git a/packages/kogito-serverless-operator/controllers/platform/defaults.go b/packages/kogito-serverless-operator/controllers/platform/defaults.go new file mode 100644 index 00000000000..0f94b6fa6a5 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/defaults.go @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" +) + +const defaultSonataFlowPlatformName = "sonataflow-platform" + +func ConfigureDefaults(ctx context.Context, c client.Client, 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, c, 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 createOrUpdatePlatform(ctx, c, p) +} + +func createOrUpdatePlatform(ctx context.Context, c client.Client, p *operatorapi.SonataFlowPlatform) error { + config := operatorapi.SonataFlowPlatform{} + err := c.Get(ctx, ctrl.ObjectKey{Namespace: p.Namespace, Name: p.Name}, &config) + if errors.IsNotFound(err) { + klog.V(log.D).ErrorS(err, "Platform not found, creating it") + return c.Create(ctx, p) + } else if err != nil { + klog.V(log.E).ErrorS(err, "Error reading the Platform") + return err + } + + config.Spec = p.Spec + config.Status.Cluster = p.Status.Cluster + err = c.Update(ctx, &config) + if err != nil { + klog.V(log.E).ErrorS(err, "Error updating the BuildPlatform") + } + return err +} + +func newDefaultSonataFlowPlatform(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", + }, + }, + }, + }, + } +} diff --git a/packages/kogito-serverless-operator/controllers/platform/initialize.go b/packages/kogito-serverless-operator/controllers/platform/initialize.go new file mode 100644 index 00000000000..b48a31cf1c1 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/initialize.go @@ -0,0 +1,176 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/cfg" + "k8s.io/klog/v2" + + 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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, error) { + duplicate, err := action.isPrimaryDuplicate(ctx, platform) + if err != nil { + return 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 + } + + return nil, nil + } + + if err = ConfigureDefaults(ctx, action.client, platform, true); err != nil { + return 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, 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, 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 +} + +// 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.ResourceRequirements{ + 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/packages/kogito-serverless-operator/controllers/platform/k8s.go b/packages/kogito-serverless-operator/controllers/platform/k8s.go new file mode 100644 index 00000000000..bceda7f8b2a --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/k8s.go @@ -0,0 +1,277 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform/services" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/variables" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + kubeutil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +// 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, error) { + // Refresh applied configuration + if err := ConfigureDefaults(ctx, action.client, platform, false); err != nil { + return nil, err + } + + psDI := services.NewDataIndexHandler(platform) + if psDI.IsServiceSetInSpec() { + if err := createOrUpdateServiceComponents(ctx, action.client, platform, psDI); err != nil { + return nil, err + } + } + + psJS := services.NewJobServiceHandler(platform) + if psJS.IsServiceSetInSpec() { + if err := createOrUpdateServiceComponents(ctx, action.client, platform, psJS); err != nil { + return nil, err + } + } + + return platform, nil +} + +func createOrUpdateServiceComponents(ctx context.Context, client client.Client, platform *operatorapi.SonataFlowPlatform, psh services.PlatformServiceHandler) error { + if err := createOrUpdateConfigMap(ctx, client, platform, psh); err != nil { + return err + } + if err := createOrUpdateDeployment(ctx, client, platform, psh); err != nil { + return err + } + return createOrUpdateService(ctx, client, platform, psh) +} + +func createOrUpdateDeployment(ctx context.Context, client client.Client, platform *operatorapi.SonataFlowPlatform, psh services.PlatformServiceHandler) 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) + dataDeployContainer := &corev1.Container{ + Image: imageTag, + ImagePullPolicy: kubeutil.GetImagePullPolicy(imageTag), + Env: psh.GetEnvironmentVariables(), + Resources: psh.GetPodResourceRequirements(), + ReadinessProbe: readyProbe, + LivenessProbe: liveProbe, + Ports: []corev1.ContainerPort{ + { + Name: utils.HttpScheme, + ContainerPort: int32(constants.DefaultHTTPWorkflowPortInt), + Protocol: corev1.ProtocolTCP, + }, + }, + VolumeMounts: []corev1.VolumeMount{ + { + Name: "application-config", + MountPath: "/home/kogito/config", + }, + }, + } + dataDeployContainer = psh.ConfigurePersistence(dataDeployContainer) + dataDeployContainer, err := psh.MergeContainerSpec(dataDeployContainer) + if err != nil { + return err + } + + // immutable + dataDeployContainer.Name = psh.GetContainerName() + + replicas := psh.GetReplicaCount() + lbl, selectorLbl := getLabels(platform, psh) + dataDeploySpec := appsv1.DeploymentSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: selectorLbl, + }, + Replicas: &replicas, + 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(), + }, + }, + }, + }, + }, + }, + }, + } + + dataDeploySpec.Template.Spec, err = psh.MergePodSpec(dataDeploySpec.Template.Spec) + if err != nil { + return err + } + kubeutil.AddOrReplaceContainer(dataDeployContainer.Name, *dataDeployContainer, &dataDeploySpec.Template.Spec) + + dataDeploy := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: platform.Namespace, + Name: psh.GetServiceName(), + Labels: lbl, + }} + if err := controllerutil.SetControllerReference(platform, dataDeploy, client.Scheme()); err != nil { + return err + } + + // Create or Update the deployment + if op, err := controllerutil.CreateOrUpdate(ctx, client, dataDeploy, func() error { + dataDeploy.Spec = dataDeploySpec + + return nil + }); err != nil { + return err + } else { + klog.V(log.I).InfoS("Deployment successfully reconciled", "operation", op) + } + + 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.HttpScheme, + 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 +} + +func getLabels(platform *operatorapi.SonataFlowPlatform, psh services.PlatformServiceHandler) (map[string]string, map[string]string) { + lbl := map[string]string{ + workflowproj.LabelApp: platform.Name, + workflowproj.LabelService: psh.GetServiceName(), + } + selectorLbl := map[string]string{ + workflowproj.LabelService: psh.GetServiceName(), + } + return lbl, selectorLbl +} + +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) + configMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: psh.GetServiceCmName(), + Namespace: platform.Namespace, + Labels: lbl, + }, + Data: map[string]string{ + workflowproj.ApplicationPropertiesFileName: handler.Build(), + }, + } + 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(configMap.Data[workflowproj.ApplicationPropertiesFileName]).Build() + + return nil + }); err != nil { + return err + } else { + klog.V(log.I).InfoS("ConfigMap successfully reconciled", "operation", op) + } + + return nil +} diff --git a/packages/kogito-serverless-operator/controllers/platform/kaniko_cache.go b/packages/kogito-serverless-operator/controllers/platform/kaniko_cache.go new file mode 100644 index 00000000000..402c51a7af1 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/kaniko_cache.go @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/cfg" + "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" + + v08 "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/controllers/platform/monitor.go b/packages/kogito-serverless-operator/controllers/platform/monitor.go new file mode 100644 index 00000000000..80c5bc19c79 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/monitor.go @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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, 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 := ConfigureDefaults(ctx, action.client, platform, false); err != nil { + return nil, err + } + + return platform, nil +} diff --git a/packages/kogito-serverless-operator/controllers/platform/platform.go b/packages/kogito-serverless-operator/controllers/platform/platform.go new file mode 100644 index 00000000000..fca10709e57 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/platform.go @@ -0,0 +1,306 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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. +func GetActivePlatform(ctx context.Context, c ctrl.Client, namespace string) (*operatorapi.SonataFlowPlatform, error) { + return getLocalPlatform(ctx, c, namespace, true) +} + +// getLocalPlatform returns the currently installed platform or any platform existing in local namespace. +func getLocalPlatform(ctx context.Context, c ctrl.Client, namespace string, active bool) (*operatorapi.SonataFlowPlatform, error) { + klog.V(log.D).InfoS("Finding available platforms") + + 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 build 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 local build platform", "platform", res.Name) + return &res, nil + } + klog.V(log.I).InfoS("Not found a local build platform", "Namespace", namespace) + klog.V(log.I).InfoS("Creating a default SonataFlowPlatform", "Namespace", namespace) + sfp := newDefaultSonataFlowPlatform(namespace) + if err = c.Create(ctx, sfp); err != nil { + return nil, err + } + return sfp, nil +} + +// 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/packages/kogito-serverless-operator/controllers/platform/platformutils.go b/packages/kogito-serverless-operator/controllers/platform/platformutils.go new file mode 100644 index 00000000000..4cac8d61b2e --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/platformutils.go @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + "runtime" + "strings" + "time" + + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/yaml" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/workflowdef" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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 + +func configureRegistry(ctx context.Context, c client.Client, 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, c) + 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 +} + +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 +} + +// 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 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 +} + +// GetCustomizedBuilderDockerfile gets the Dockerfile as defined in the default platform ConfigMap, apply any custom requirements and return. +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) + } + return dockerfile +} + +func GetFromImageTagDockerfile(dockerfile string) string { + res := builderDockerfileFromRE.FindAllStringSubmatch(dockerfile, 1) + return strings.Trim(res[0][1], " ") +} diff --git a/packages/kogito-serverless-operator/controllers/platform/platformutils_test.go b/packages/kogito-serverless-operator/controllers/platform/platformutils_test.go new file mode 100644 index 00000000000..024b5782f16 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/platformutils_test.go @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "os" + "regexp" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" +) + +func TestSonataFlowBuildController(t *testing.T) { + platform := test.GetBasePlatform() + dockerfileBytes, err := os.ReadFile("../../test/builder/Dockerfile") + if err != nil { + assert.Fail(t, "Unable to read base Dockerfile") + } + dockerfile := string(dockerfileBytes) + // 1 - Let's verify that the default image is used (for this unit test is quay.io/kiegroup/kogito-swf-builder-nightly:latest) + resDefault := GetCustomizedBuilderDockerfile(dockerfile, *platform) + foundDefault, err := regexp.MatchString("FROM quay.io/kiegroup/kogito-swf-builder-nightly:latest AS builder", resDefault) + assert.NoError(t, err) + assert.True(t, foundDefault) + + // 2 - Let's try to override using the productized image + platform.Spec.Build.Config.BaseImage = "registry.access.redhat.com/openshift-serverless-1-tech-preview/logic-swf-builder-rhel8" + resProductized := GetCustomizedBuilderDockerfile(dockerfile, *platform) + foundProductized, err := regexp.MatchString("FROM registry.access.redhat.com/openshift-serverless-1-tech-preview/logic-swf-builder-rhel8 AS builder", resProductized) + assert.NoError(t, err) + assert.True(t, foundProductized) +} diff --git a/packages/kogito-serverless-operator/controllers/platform/services/properties.go b/packages/kogito-serverless-operator/controllers/platform/services/properties.go new file mode 100644 index 00000000000..a79a0ae1044 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/services/properties.go @@ -0,0 +1,204 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + "k8s.io/klog/v2" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/workflowdef" + + "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") + 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") + 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/v2/jobs/events", constants.JobServiceURLProtocol)) + 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 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/packages/kogito-serverless-operator/controllers/platform/services/properties_services_test.go b/packages/kogito-serverless-operator/controllers/platform/services/properties_services_test.go new file mode 100644 index 00000000000..f38b2ea7970 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/services/properties_services_test.go @@ -0,0 +1,266 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "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.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.datasource.reactive.url", "postgresql://postgres:5432/sonataflow?search_path=myschema") + 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.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.datasource.reactive.url", "postgresql://postgres:5432/sonataflow?search_path=myschema") + 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.ServiceSpec{} + } + 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.ServiceSpec{} + } + 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.ServiceSpec{} + } + } +} + +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.ServiceSpec{} + } + } +} + +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.ServiceSpec{} + } + 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.ServiceSpec{} + } + 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/packages/kogito-serverless-operator/controllers/platform/services/properties_test.go b/packages/kogito-serverless-operator/controllers/platform/services/properties_test.go new file mode 100644 index 00000000000..b1ffd865779 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/services/properties_test.go @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/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/packages/kogito-serverless-operator/controllers/platform/services/services.go b/packages/kogito-serverless-operator/controllers/platform/services/services.go new file mode 100644 index 00000000000..c7bc0c8f7f4 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/services/services.go @@ -0,0 +1,484 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/cfg" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/persistence" + "github.com/magiconair/properties" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/version" + "github.com/imdario/mergo" +) + +const ( + quarkusHibernateORMDatabaseGeneration string = "QUARKUS_HIBERNATE_ORM_DATABASE_GENERATION" + quarkusFlywayMigrateAtStart string = "QUARKUS_FLYWAY_MIGRATE_AT_START" +) + +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 + + // 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) + + // 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 + // 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) +} + +type DataIndexHandler struct { + platform *operatorapi.SonataFlowPlatform +} + +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 + } + var tag = version.GetMajorMinor() + var suffix = "" + if version.IsSnapshot() { + tag = "latest" + //TODO, remove + suffix = constants.ImageNameNightlySuffix + } + // returns "quay.io/kiegroup/kogito-data-index-:" + return fmt.Sprintf("%s-%s-%s:%s", constants.ImageNamePrefix, constants.DataIndexName, persistenceType.String()+suffix, tag) +} + +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) 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.KogitoServiceURLProtocol, d.platform.Namespace, d.GetServiceName()) +} + +func (d DataIndexHandler) GetEnvironmentVariables() []corev1.EnvVar { + return []corev1.EnvVar{ + { + Name: "KOGITO_DATA_INDEX_QUARKUS_PROFILE", + Value: "http-events-support", + }, + { + Name: "QUARKUS_HTTP_CORS", + Value: "true", + }, + { + Name: "QUARKUS_HTTP_CORS_ORIGINS", + Value: "/.*/", + }, + } +} + +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 (d DataIndexHandler) ConfigurePersistence(containerSpec *corev1.Container) *corev1.Container { + if d.hasPostgreSQLConfigured() { + p := persistence.RetrieveConfiguration(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)...) + // specific to DataIndex + c.Env = append(c.Env, corev1.EnvVar{Name: quarkusHibernateORMDatabaseGeneration, Value: "update"}, corev1.EnvVar{Name: quarkusFlywayMigrateAtStart, Value: "true"}) + return c + } + return containerSpec +} + +func (d DataIndexHandler) MergeContainerSpec(containerSpec *corev1.Container) (*corev1.Container, error) { + c := containerSpec.DeepCopy() + err := mergo.Merge(c, d.platform.Spec.Services.DataIndex.PodTemplate.Container.ToContainer(), mergo.WithOverride) + return c, err +} + +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) GetServiceCmName() string { + return fmt.Sprintf("%s-props", d.GetServiceName()) +} + +func (d DataIndexHandler) GenerateServiceProperties() (*properties.Properties, error) { + props := properties.NewProperties() + props.Set(constants.KogitoServiceURLProperty, d.GetLocalServiceBaseUrl()) + props.Set(constants.DataIndexKafkaSmallRyeHealthProperty, "false") + return props, nil +} + +type JobServiceHandler struct { + platform *operatorapi.SonataFlowPlatform +} + +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 + } + var tag = version.GetMajorMinor() + var suffix = "" + if version.IsSnapshot() { + tag = "latest" + //TODO remove + suffix = constants.ImageNameNightlySuffix + } + // returns "quay.io/kiegroup/kogito-jobs-service-:" + return fmt.Sprintf("%s-%s-%s:%s", constants.ImageNamePrefix, constants.JobServiceName, persistenceType.String()+suffix, tag) +} + +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) 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.JobServiceURLProtocol, j.platform.Namespace, j.GetServiceName()) +} + +func (j JobServiceHandler) GetEnvironmentVariables() []corev1.EnvVar { + return []corev1.EnvVar{ + { + Name: "QUARKUS_HTTP_CORS", + Value: "true", + }, + { + Name: "QUARKUS_HTTP_CORS_ORIGINS", + Value: "/.*/", + }, + } +} + +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 { + return 1 +} + +func (j JobServiceHandler) MergeContainerSpec(containerSpec *corev1.Container) (*corev1.Container, error) { + c := containerSpec.DeepCopy() + err := mergo.Merge(c, j.platform.Spec.Services.JobService.PodTemplate.Container.ToContainer(), mergo.WithOverride) + return c, err +} + +// 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.RetrieveConfiguration(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)...) + // Specific to Job Service + c.Env = append(c.Env, corev1.EnvVar{Name: "QUARKUS_FLYWAY_MIGRATE_AT_START", Value: "true"}) + 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") + // add data source reactive URL + if j.hasPostgreSQLConfigured() { + p := persistence.RetrieveConfiguration(j.platform.Spec.Services.JobService.Persistence, j.platform.Spec.Persistence, j.GetServiceName()) + dataSourceReactiveURL, err := generateReactiveURL(p.PostgreSQL, j.GetServiceName(), j.platform.Namespace, constants.DefaultDatabaseName, constants.DefaultPostgreSQLPort) + if err != nil { + return nil, err + } + props.Set(constants.JobServiceDataSourceReactiveURL, dataSourceReactiveURL) + } + + if isDataIndexEnabled(j.platform) { + di := NewDataIndexHandler(j.platform) + props.Set(constants.JobServiceStatusChangeEvents, "true") + props.Set(constants.JobServiceStatusChangeEventsURL, di.GetLocalServiceBaseUrl()+"/jobs") + } + 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 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 +} diff --git a/packages/kogito-serverless-operator/controllers/platform/services/services_suite_test.go b/packages/kogito-serverless-operator/controllers/platform/services/services_suite_test.go new file mode 100644 index 00000000000..0a4e1019441 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/services/services_suite_test.go @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/platform/warm.go b/packages/kogito-serverless-operator/controllers/platform/warm.go new file mode 100644 index 00000000000..0ceb09f256d --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/platform/warm.go @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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, 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, 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 + case corev1.PodFailed: + return 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 + } +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/common/constants/objects.go b/packages/kogito-serverless-operator/controllers/profiles/common/constants/objects.go new file mode 100644 index 00000000000..caddd1a10a8 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/constants/objects.go @@ -0,0 +1,24 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/profiles/common/constants/platform_services.go b/packages/kogito-serverless-operator/controllers/profiles/common/constants/platform_services.go new file mode 100644 index 00000000000..30b25fb2fb0 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/constants/platform_services.go @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + 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" + JobServiceStatusChangeEvents = "kogito.jobs-service.http.job-status-change-events" + JobServiceStatusChangeEventsURL = "mp.messaging.outgoing.kogito-job-service-job-status-events-http.url" + JobServiceURLProtocol = "http" + JobServiceDataSourceReactiveURL = "quarkus.datasource.reactive.url" + JobServiceJobEventsPath = "/v2/jobs/events" + + KogitoProcessInstancesEventsURL = "mp.messaging.outgoing.kogito-processinstances-events.url" + KogitoProcessInstancesEventsEnabled = "kogito.events.processinstances.enabled" + KogitoProcessInstancesEventsPath = "/processes" + 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" + // 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."org.kie.kogito.jobs.service.messaging.http.health.knative.KSinkInjectionHealthCheck".enabled` + + DataIndexServiceName = "data-index-service" + JobServiceName = "jobs-service" + ImageNamePrefix = "quay.io/kiegroup/kogito" + //TODO, the usage of this constant was temporary introduced since only the nightly images are being updated for the + //data-index and jobs-service. And this is causing issues at the time of using the workflows integrated with these, etc. + //This will be removed when the CI is fixed. + ImageNameNightlySuffix = "-nightly" + DataIndexName = "data-index" + + 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/packages/kogito-serverless-operator/controllers/profiles/common/constants/reconcile.go b/packages/kogito-serverless-operator/controllers/profiles/common/constants/reconcile.go new file mode 100644 index 00000000000..a2a4a7ac1df --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/constants/reconcile.go @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 +) diff --git a/packages/kogito-serverless-operator/controllers/profiles/common/constants/workflows.go b/packages/kogito-serverless-operator/controllers/profiles/common/constants/workflows.go new file mode 100644 index 00000000000..8087f963bc8 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/constants/workflows.go @@ -0,0 +1,26 @@ +// Copyright 2023 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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 ( + MicroprofileServiceCatalogPropertyPrefix = "org.kie.kogito.addons.discovery." + 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}" + KnativeEventingBrokerDefault = "default" +) diff --git a/packages/kogito-serverless-operator/controllers/profiles/common/deployment.go b/packages/kogito-serverless-operator/controllers/profiles/common/deployment.go new file mode 100644 index 00000000000..9dedbf5c034 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/deployment.go @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/klog/v2" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + kubeutil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" +) + +var _ WorkflowDeploymentManager = &deploymentHandler{} + +// 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) RolloutDeployment(ctx context.Context, workflow *operatorapi.SonataFlow) error { + deployment := &appsv1.Deployment{} + if err := d.c.Get(ctx, client.ObjectKeyFromObject(workflow), deployment); err != nil { + // Deployment not found, nothing to do. + if errors.IsNotFound(err) { + return 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 := &appsv1.Deployment{} + if err := d.c.Get(ctx, client.ObjectKeyFromObject(workflow), deployment); err != 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") + 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) + 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) + 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() + 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, "") + 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/packages/kogito-serverless-operator/controllers/profiles/common/ensurer.go b/packages/kogito-serverless-operator/controllers/profiles/common/ensurer.go new file mode 100644 index 00000000000..f5b2421758c --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/ensurer.go @@ -0,0 +1,185 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" +) + +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 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 +} + +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 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 + } + } + 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 +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/common/knative.go b/packages/kogito-serverless-operator/controllers/profiles/common/knative.go new file mode 100644 index 00000000000..1d4e237c4e9 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/knative.go @@ -0,0 +1,76 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/knative" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +var _ KnativeEventingHandler = &knativeObjectManager{} + +type knativeObjectManager struct { + sinkBinding ObjectEnsurer + trigger ObjectsEnsurer + *StateSupport +} + +func NewKnativeEventingHandler(support *StateSupport) KnativeEventingHandler { + return &knativeObjectManager{ + sinkBinding: NewObjectEnsurer(support.C, SinkBindingCreator), + trigger: NewObjectsEnsurer(support.C, TriggersCreator), + 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 + + if workflow.Spec.Flow.Events == nil { + // skip if no event is found + klog.V(log.I).InfoS("skip knative resource creation as no event is found") + } else if workflow.Spec.Sink == nil { + klog.V(log.I).InfoS("Spec.Sink is not provided") + } else if knativeAvail, err := knative.GetKnativeAvailability(k.Cfg); err != nil || knativeAvail == nil || !knativeAvail.Eventing { + klog.V(log.I).InfoS("Knative Eventing is not installed") + } else { + // create sinkBinding and trigger + sinkBinding, _, err := k.sinkBinding.Ensure(ctx, workflow) + if err != nil { + return objs, err + } else if sinkBinding != nil { + objs = append(objs, sinkBinding) + } + + triggers := k.trigger.Ensure(ctx, workflow) + for _, trigger := range triggers { + if trigger.Error != nil { + return objs, trigger.Error + } + objs = append(objs, trigger.Object) + } + } + return objs, nil +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/common/mutate_visitors.go b/packages/kogito-serverless-operator/controllers/profiles/common/mutate_visitors.go new file mode 100644 index 00000000000..999782d898c --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/mutate_visitors.go @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/discovery" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/properties" + "github.com/imdario/mergo" + 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" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + kubeutil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj" +) + +// 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 + } + } +} + +// 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 + } + return EnsureDeployment(original.(*appsv1.Deployment), object.(*appsv1.Deployment)) + } + } +} + +// 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() + + // Clean up the volumes, they are inherited from original, additional are added by other visitors + 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) +} + +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) + err := kubeutil.AnnotateDeploymentConfigChecksum(workflow, deployment, userPropsCM, managedPropsCM) + return err + } + } +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/common/object_creators.go b/packages/kogito-serverless-operator/controllers/profiles/common/object_creators.go new file mode 100644 index 00000000000..c8016d040d3 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/object_creators.go @@ -0,0 +1,314 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/workflowdef" + + cncfmodel "github.com/serverlessworkflow/sdk-go/v2/model" + + "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" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/tracker" + "sigs.k8s.io/controller-runtime/pkg/client" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/persistence" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/properties" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/variables" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + kubeutil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/openshift" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj" +) + +// 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) + +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: lbl, + }, + 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 +} + +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.HttpScheme, + 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, + }, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + HTTPGet: &corev1.HTTPGetAction{ + Path: constants.QuarkusHealthPathReady, + Port: variables.DefaultHTTPWorkflowPortIntStr, + }, + }, + TimeoutSeconds: healthTimeoutSeconds, + }, + 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 + } + 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.ConfigurePersistence(defaultFlowContainer, p, workflow.Name, workflow.Namespace) + } + // immutable + defaultFlowContainer.Name = operatorapi.DefaultContainerName + portIdx := -1 + for i := range defaultFlowContainer.Ports { + if defaultFlowContainer.Ports[i].Name == utils.HttpScheme || + 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{{ + 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) (client.Object, error) { + lbl := workflowproj.GetMergedLabels(workflow) + + // skip if no produced event is found + if workflow.Spec.Sink == nil || !workflowdef.ContainsEventKind(workflow, cncfmodel.EventKindProduced) { + return nil, nil + } + + sink := workflow.Spec.Sink + + // 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: "apps/v1", + Kind: "Deployment", + }, + }, + }, + } + return sinkBinding, nil +} + +// 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) ([]client.Object, error) { + var resultObjects []client.Object + lbl := workflowproj.GetMergedLabels(workflow) + + //consumed + events := workflow.Spec.Flow.Events + for _, event := range events { + // filter out produce events + if event.Kind == cncfmodel.EventKindProduced { + continue + } + + // construct eventingv1.Trigger + trigger := &eventingv1.Trigger{ + ObjectMeta: metav1.ObjectMeta{ + Name: strings.ToLower(fmt.Sprintf("%s-%s-trigger", workflow.Name, event.Name)), + Namespace: workflow.Namespace, + Labels: lbl, + }, + Spec: eventingv1.TriggerSpec{ + Broker: constants.KnativeEventingBrokerDefault, + Filter: &eventingv1.TriggerFilter{ + Attributes: eventingv1.TriggerFilterAttributes{ + "type": event.Type, + }, + }, + Subscriber: duckv1.Destination{ + Ref: &duckv1.KReference{ + Name: workflow.Name, + Namespace: workflow.Namespace, + APIVersion: "v1", + Kind: "Service", + }, + }, + }, + } + 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 +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/common/object_creators_test.go b/packages/kogito-serverless-operator/controllers/profiles/common/object_creators_test.go new file mode 100644 index 00000000000..68d84e2cd1f --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/object_creators_test.go @@ -0,0 +1,631 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" + + "github.com/magiconair/properties" + "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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + kubeutil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj" +) + +func Test_ensureWorkflowPropertiesConfigMapMutator(t *testing.T) { + workflow := test.GetBaseSonataFlowWithDevProfile(t.Name()) + platform := test.GetBasePlatform() + // 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, nil, 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.GetBasePlatform() + 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, nil, 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.PodTemplateSpec{ + Container: v1alpha08.ContainerSpec{ + // this one we can override + Image: "quay.io/example/my-workflow:1.0.0", + Ports: []corev1.ContainerPort{ + // let's override a immutable attribute + {Name: utils.HttpScheme, 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, "quay.io/example/my-workflow:1.0.0", 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 TestMergePodSpec_OverrideContainers(t *testing.T) { + workflow := test.GetBaseSonataFlow(t.Name()) + workflow.Spec.PodTemplate = v1alpha08.PodTemplateSpec{ + PodSpec: v1alpha08.PodSpec{ + // Try to override the workflow container via the podspec + Containers: []corev1.Container{ + { + Name: v1alpha08.DefaultContainerName, + Image: "quay.io/example/my-workflow:1.0.0", + Ports: []corev1.ContainerPort{ + {Name: utils.HttpScheme, 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, "quay.io/example/my-workflow:1.0.0", flowContainer.Image) + assert.Equal(t, int32(8080), flowContainer.Ports[0].ContainerPort) + assert.Empty(t, flowContainer.Env) +} + +func Test_ensureWorkflowSinkBindingIsCreated(t *testing.T) { + workflow := test.GetVetEventSonataFlow(t.Name()) + + //On Kubernetes we want the service exposed in Dev with NodePort + sinkBinding, _ := SinkBindingCreator(workflow) + 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.NotNil(t, reflectSinkBinding.GetLabels()) + assert.Equal(t, reflectSinkBinding.ObjectMeta.Labels, map[string]string{"app": "vet", "sonataflow.org/workflow-app": "vet"}) +} + +func Test_ensureWorkflowTriggersAreCreated(t *testing.T) { + workflow := test.GetVetEventSonataFlow(t.Name()) + + //On Kubernetes we want the service exposed in Dev with NodePort + triggers, _ := TriggersCreator(workflow) + + assert.NotEmpty(t, triggers) + assert.Len(t, triggers, 2) + for _, trigger := range triggers { + assert.Contains(t, []string{"vet-vetappointmentrequestreceived-trigger", "vet-vetappointmentinfo-trigger"}, trigger.GetName()) + assert.NotNil(t, trigger.GetLabels()) + assert.Equal(t, trigger.GetLabels(), map[string]string{"app": "vet", "sonataflow.org/workflow-app": "vet"}) + } +} + +func TestMergePodSpec_WithPostgreSQL_and_JDBC_URL_field(t *testing.T) { + workflow := test.GetBaseSonataFlow(t.Name()) + workflow.Spec = v1alpha08.SonataFlowSpec{ + PodTemplate: v1alpha08.PodTemplateSpec{ + Container: v1alpha08.ContainerSpec{ + // this one we can override + Image: "quay.io/example/my-workflow:1.0.0", + Ports: []corev1.ContainerPort{ + // let's override a immutable attribute + {Name: utils.HttpScheme, 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", + }, + { + Name: "KOGITO_PERSISTENCE_PROTO_MARSHALLER", + Value: "false", + }, + { + Name: "KOGITO_PERSISTENCE_QUERY_TIMEOUT_MILLIS", + Value: "10000", + }, + } + 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, "quay.io/example/my-workflow:1.0.0", 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.PodTemplateSpec{ + PodSpec: v1alpha08.PodSpec{ + // Try to override the workflow container via the podspec + Containers: []corev1.Container{ + { + Name: v1alpha08.DefaultContainerName, + Image: "quay.io/example/my-workflow:1.0.0", + Ports: []corev1.ContainerPort{ + {Name: utils.HttpScheme, 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", + }, + { + Name: "KOGITO_PERSISTENCE_PROTO_MARSHALLER", + Value: "false", + }, + { + Name: "KOGITO_PERSISTENCE_QUERY_TIMEOUT_MILLIS", + Value: "10000", + }, + } + 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", + }, + { + Name: "KOGITO_PERSISTENCE_PROTO_MARSHALLER", + Value: "false", + }, + { + Name: "KOGITO_PERSISTENCE_QUERY_TIMEOUT_MILLIS", + Value: "10000", + }, + } + 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.PodTemplateSpec{ + PodSpec: v1alpha08.PodSpec{ + // Try to override the workflow container via the podspec + Containers: []corev1.Container{ + { + Name: v1alpha08.DefaultContainerName, + Image: "quay.io/example/my-workflow:1.0.0", + Ports: []corev1.ContainerPort{ + {Name: utils.HttpScheme, 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", + }, + { + Name: "KOGITO_PERSISTENCE_PROTO_MARSHALLER", + Value: "false", + }, + { + Name: "KOGITO_PERSISTENCE_QUERY_TIMEOUT_MILLIS", + Value: "10000", + }, + } + 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) +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/common/persistence/postgresql.go b/packages/kogito-serverless-operator/controllers/profiles/common/persistence/postgresql.go new file mode 100644 index 00000000000..faf5ade6c15 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/persistence/postgresql.go @@ -0,0 +1,147 @@ +// Copyright 2023 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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" + + corev1 "k8s.io/api/core/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" +) + +const ( + defaultDatabaseName = "sonataflow" + timeoutSeconds = 3 + failureThreshold = 5 + initialPeriodSeconds = 15 + initialDelaySeconds = 10 + successThreshold = 1 + + postgreSQLCPULimit = "500m" + postgreSQLMemoryLimit = "256Mi" + postgreSQLMemoryRequest = "256Mi" + postgreSQLCPURequest = "100m" + + defaultPostgreSQLUsername = "sonataflow" + defaultPostgresSQLPassword = "sonataflow" +) + +func ConfigurePostgreSQLEnv(postgresql *operatorapi.PersistencePostgreSQL, databaseSchema, databaseNamespace string) []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 + } + return []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, + }, + { + Name: "KOGITO_PERSISTENCE_TYPE", + Value: "jdbc", + }, + { + Name: "KOGITO_PERSISTENCE_PROTO_MARSHALLER", + Value: "false", + }, + { + Name: "KOGITO_PERSISTENCE_QUERY_TIMEOUT_MILLIS", + Value: "10000", + }, + } +} + +func ConfigurePersistence(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)...) + return c +} + +func RetrieveConfiguration(primary *v1alpha08.PersistenceOptionsSpec, platformPersistence *v1alpha08.PlatformPersistenceOptionsSpec, schema string) *v1alpha08.PersistenceOptionsSpec { + if primary != nil { + return primary + } + if platformPersistence == nil { + return nil + } + 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 +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/common/properties/discovery.go b/packages/kogito-serverless-operator/controllers/profiles/common/properties/discovery.go new file mode 100644 index 00000000000..4caf1a8b931 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/properties/discovery.go @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/discovery" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "github.com/magiconair/properties" + "k8s.io/klog/v2" +) + +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/packages/kogito-serverless-operator/controllers/profiles/common/properties/discovery_test.go b/packages/kogito-serverless-operator/controllers/profiles/common/properties/discovery_test.go new file mode 100644 index 00000000000..0008b5bf028 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/properties/discovery_test.go @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/magiconair/properties" + "github.com/serverlessworkflow/sdk-go/v2/model" + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +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/packages/kogito-serverless-operator/controllers/profiles/common/properties/knative.go b/packages/kogito-serverless-operator/controllers/profiles/common/properties/knative.go new file mode 100644 index 00000000000..a37e8a76e35 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/properties/knative.go @@ -0,0 +1,49 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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 ( + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/workflowdef" + "github.com/magiconair/properties" + cncfmodel "github.com/serverlessworkflow/sdk-go/v2/model" +) + +// generateKnativeEventingWorkflowProperties returns the set of application properties required for the workflow to produce or consume +// Knative Events. +// Never nil. +func generateKnativeEventingWorkflowProperties(workflow *operatorapi.SonataFlow) (*properties.Properties, error) { + props := properties.NewProperties() + if workflow == nil || workflow.Spec.Sink == nil { + props.Set(constants.KnativeHealthEnabled, "false") + return props, nil + } + // verify ${K_SINK} + 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) + var path = "/" + if workflow.Spec.Sink.URI != nil { + path = workflow.Spec.Sink.URI.Path + } + props.Set(constants.KogitoIncomingEventsPath, path) + } + return props, nil +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/common/properties/managed.go b/packages/kogito-serverless-operator/controllers/profiles/common/properties/managed.go new file mode 100644 index 00000000000..be8d0d232ae --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/properties/managed.go @@ -0,0 +1,191 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/discovery" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform/services" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + + "github.com/magiconair/properties" + + "k8s.io/klog/v2" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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)) + } + 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 { + var kogitoServiceUrl string + if len(a.workflow.Namespace) > 0 { + kogitoServiceUrl = fmt.Sprintf("%s://%s.%s", constants.KogitoServiceURLProtocol, a.workflow.Name, a.workflow.Namespace) + } else { + kogitoServiceUrl = fmt.Sprintf("%s://%s", constants.KogitoServiceURLProtocol, a.workflow.Name) + } + return a.addDefaultManagedProperty(constants.KogitoServiceURLProperty, kogitoServiceUrl) +} + +// 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.DataIndexKafkaSmallRyeHealthProperty, + "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() + props.Set(constants.KogitoUserTasksEventsEnabled, "false") + if platform != nil { + p, err := resolvePlatformWorkflowProperties(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) + if err != nil { + return nil, err + } + props.Merge(p) + props.Sort() + + handler.defaultManagedProperties = props + return handler.withKogitoServiceUrl(), nil +} + +// 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/packages/kogito-serverless-operator/controllers/profiles/common/properties/managed_test.go b/packages/kogito-serverless-operator/controllers/profiles/common/properties/managed_test.go new file mode 100644 index 00000000000..ac4441ea163 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/properties/managed_test.go @@ -0,0 +1,685 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/discovery" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform/services" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + + "github.com/magiconair/properties" + + "github.com/stretchr/testify/assert" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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 + jobServiceDevProperties *properties.Properties + jobServiceProdProperties *properties.Properties + dataIndexDevProperties *properties.Properties + dataIndexProdProperties *properties.Properties + dataIndexJobServiceDevProperties *properties.Properties + dataIndexJobServiceProdProperties *properties.Properties +) + +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") + props, err := ApplicationManagedProperties(workflow, nil) + 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") + props, err := NewManagedPropertyHandler(workflow, nil) + assert.NoError(t, err) + generatedProps, propsErr := properties.LoadString(props.WithUserProperties(userProperties).Build()) + assert.NoError(t, propsErr) + assert.Equal(t, 7, 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, "")) +} + +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) + props, err := NewManagedPropertyHandler(workflow, nil) + 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, 21, 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") +} + +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.ServiceSpec{ + Enabled: &enabled, + }, + JobService: &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, 11, 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, 17, 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, 12, 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, 11, 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, "")) +} + +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")), + generateJobServiceWorkflowDevProperties()), + 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")), + generateJobServiceWorkflowDevProperties()), + 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")), + generateJobServiceWorkflowDevProperties()), + Entry("has enabled field undefined and workflow with no profile", + generateFlow(setWorkflowName("foo"), setWorkflowNamespace("default")), + generatePlatform(setJobServiceEnabledValue(nil), setPlatformName("foo"), setPlatformNamespace("default")), + generateJobServiceWorkflowDevProperties()), + ) + + 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")), + generateDataIndexWorkflowDevProperties()), + 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")), + generateDataIndexWorkflowDevProperties()), + 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")), + generateDataIndexWorkflowDevProperties()), + 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")), + generateDataIndexWorkflowDevProperties()), + ) + + 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")), + generateDataIndexAndJobServiceWorkflowDevProperties()), + 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")), + generateDataIndexAndJobServiceWorkflowDevProperties()), + 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")), + generateDataIndexAndJobServiceWorkflowDevProperties()), + 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")), + generateDataIndexAndJobServiceWorkflowDevProperties()), + 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")), + generateDataIndexAndJobServiceWorkflowDevProperties()), + ) + }) + }) + +}) + +func generateJobServiceWorkflowDevProperties() *properties.Properties { + if jobServiceDevProperties == nil { + jobServiceDevProperties = properties.NewProperties() + jobServiceDevProperties.Set("kogito.service.url", "http://foo.default") + jobServiceDevProperties.Set("quarkus.http.host", "0.0.0.0") + jobServiceDevProperties.Set("quarkus.http.port", "8080") + jobServiceDevProperties.Set("quarkus.devservices.enabled", "false") + jobServiceDevProperties.Set("quarkus.kogito.devservices.enabled", "false") + jobServiceDevProperties.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") + jobServiceDevProperties.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://localhost/v2/jobs/events") + jobServiceDevProperties.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") + jobServiceDevProperties.Set("kogito.events.processdefinitions.enabled", "false") + jobServiceDevProperties.Set("kogito.events.processinstances.enabled", "false") + jobServiceDevProperties.Set("kogito.events.usertasks.enabled", "false") + jobServiceDevProperties.Sort() + } + return jobServiceDevProperties +} + +func generateJobServiceWorkflowProductionProperties() *properties.Properties { + if jobServiceProdProperties == nil { + jobServiceProdProperties = properties.NewProperties() + jobServiceProdProperties.Set("kogito.service.url", "http://foo.default") + jobServiceProdProperties.Set("kogito.jobs-service.url", "http://foo-jobs-service.default") + jobServiceProdProperties.Set("quarkus.http.host", "0.0.0.0") + jobServiceProdProperties.Set("quarkus.http.port", "8080") + jobServiceProdProperties.Set("quarkus.kogito.devservices.enabled", "false") + jobServiceProdProperties.Set("quarkus.devservices.enabled", "false") + jobServiceProdProperties.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") + jobServiceProdProperties.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") + jobServiceProdProperties.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://foo-jobs-service.default/v2/jobs/events") + jobServiceProdProperties.Set("kogito.events.processdefinitions.enabled", "false") + jobServiceProdProperties.Set("kogito.events.processinstances.enabled", "false") + jobServiceProdProperties.Set("kogito.events.usertasks.enabled", "false") + jobServiceProdProperties.Sort() + } + return jobServiceProdProperties +} + +func generateDataIndexWorkflowDevProperties() *properties.Properties { + if dataIndexDevProperties == nil { + dataIndexDevProperties = properties.NewProperties() + dataIndexDevProperties.Set("kogito.service.url", "http://foo.default") + dataIndexDevProperties.Set("quarkus.http.host", "0.0.0.0") + dataIndexDevProperties.Set("quarkus.http.port", "8080") + dataIndexDevProperties.Set("quarkus.devservices.enabled", "false") + dataIndexDevProperties.Set("quarkus.kogito.devservices.enabled", "false") + dataIndexDevProperties.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") + dataIndexDevProperties.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") + dataIndexDevProperties.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://localhost/v2/jobs/events") + dataIndexDevProperties.Set("kogito.events.processdefinitions.enabled", "false") + dataIndexDevProperties.Set("kogito.events.processinstances.enabled", "false") + dataIndexDevProperties.Set("kogito.events.usertasks.enabled", "false") + dataIndexDevProperties.Sort() + } + return dataIndexDevProperties +} + +func generateDataIndexWorkflowProductionProperties() *properties.Properties { + if dataIndexProdProperties == nil { + dataIndexProdProperties = properties.NewProperties() + dataIndexProdProperties.Set("kogito.service.url", "http://foo.default") + dataIndexProdProperties.Set("kogito.data-index.url", "http://foo-data-index-service.default") + dataIndexProdProperties.Set("kogito.data-index.health-enabled", "true") + dataIndexProdProperties.Set("quarkus.http.host", "0.0.0.0") + dataIndexProdProperties.Set("quarkus.http.port", "8080") + dataIndexProdProperties.Set("quarkus.devservices.enabled", "false") + dataIndexProdProperties.Set("quarkus.kogito.devservices.enabled", "false") + dataIndexProdProperties.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") + dataIndexProdProperties.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") + dataIndexProdProperties.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://localhost/v2/jobs/events") + dataIndexProdProperties.Set("mp.messaging.outgoing.kogito-processdefinitions-events.url", "http://foo-data-index-service.default/definitions") + dataIndexProdProperties.Set("mp.messaging.outgoing.kogito-processinstances-events.url", "http://foo-data-index-service.default/processes") + dataIndexProdProperties.Set("kogito.events.processdefinitions.enabled", "true") + dataIndexProdProperties.Set("kogito.events.processdefinitions.errors.propagate", "true") + dataIndexProdProperties.Set("kogito.events.processinstances.enabled", "true") + dataIndexProdProperties.Set("kogito.events.usertasks.enabled", "false") + dataIndexProdProperties.Sort() + } + return dataIndexProdProperties +} + +func generateDataIndexAndJobServiceWorkflowDevProperties() *properties.Properties { + if dataIndexJobServiceDevProperties == nil { + dataIndexJobServiceDevProperties = properties.NewProperties() + dataIndexJobServiceDevProperties.Set("kogito.service.url", "http://foo.default") + dataIndexJobServiceDevProperties.Set("quarkus.http.host", "0.0.0.0") + dataIndexJobServiceDevProperties.Set("quarkus.http.port", "8080") + dataIndexJobServiceDevProperties.Set("quarkus.kogito.devservices.enabled", "false") + dataIndexJobServiceDevProperties.Set("quarkus.devservices.enabled", "false") + dataIndexJobServiceDevProperties.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") + dataIndexJobServiceDevProperties.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") + dataIndexJobServiceDevProperties.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://localhost/v2/jobs/events") + dataIndexJobServiceDevProperties.Set("kogito.events.processdefinitions.enabled", "false") + dataIndexJobServiceDevProperties.Set("kogito.events.processinstances.enabled", "false") + dataIndexJobServiceDevProperties.Set("kogito.events.usertasks.enabled", "false") + dataIndexJobServiceDevProperties.Sort() + } + return dataIndexJobServiceDevProperties +} + +func generateDataIndexAndJobServiceWorkflowProductionProperties() *properties.Properties { + if dataIndexJobServiceProdProperties == nil { + dataIndexJobServiceProdProperties = properties.NewProperties() + dataIndexJobServiceProdProperties.Set("kogito.service.url", "http://foo.default") + dataIndexJobServiceProdProperties.Set("kogito.data-index.url", "http://foo-data-index-service.default") + dataIndexJobServiceProdProperties.Set("kogito.data-index.health-enabled", "true") + dataIndexJobServiceProdProperties.Set("kogito.jobs-service.url", "http://foo-jobs-service.default") + dataIndexJobServiceProdProperties.Set("quarkus.http.host", "0.0.0.0") + dataIndexJobServiceProdProperties.Set("quarkus.http.port", "8080") + dataIndexJobServiceProdProperties.Set("quarkus.kogito.devservices.enabled", "false") + dataIndexJobServiceProdProperties.Set("quarkus.devservices.enabled", "false") + dataIndexJobServiceProdProperties.Set("org.kie.kogito.addons.knative.eventing.health-enabled", "false") + dataIndexJobServiceProdProperties.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.connector", "quarkus-http") + dataIndexJobServiceProdProperties.Set("mp.messaging.outgoing.kogito-job-service-job-request-events.url", "http://foo-jobs-service.default/v2/jobs/events") + dataIndexJobServiceProdProperties.Set("kogito.events.processdefinitions.enabled", "true") + dataIndexJobServiceProdProperties.Set("kogito.events.processdefinitions.errors.propagate", "true") + dataIndexJobServiceProdProperties.Set("kogito.events.processinstances.enabled", "true") + dataIndexJobServiceProdProperties.Set("kogito.events.usertasks.enabled", "false") + dataIndexJobServiceProdProperties.Set("mp.messaging.outgoing.kogito-processdefinitions-events.url", "http://foo-data-index-service.default/definitions") + dataIndexJobServiceProdProperties.Set("mp.messaging.outgoing.kogito-processinstances-events.url", "http://foo-data-index-service.default/processes") + dataIndexJobServiceProdProperties.Sort() + } + return dataIndexJobServiceProdProperties +} + +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.ServiceSpec{} + } + 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.ServiceSpec{} + } + 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.ServiceSpec{} + } + 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/packages/kogito-serverless-operator/controllers/profiles/common/properties/platform.go b/packages/kogito-serverless-operator/controllers/profiles/common/properties/platform.go new file mode 100644 index 00000000000..74bbe064b2d --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/properties/platform.go @@ -0,0 +1,87 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + "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" +) + +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/packages/kogito-serverless-operator/controllers/profiles/common/properties/platform_test.go b/packages/kogito-serverless-operator/controllers/profiles/common/properties/platform_test.go new file mode 100644 index 00000000000..73775ec5ef6 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/properties/platform_test.go @@ -0,0 +1,119 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + "github.com/stretchr/testify/assert" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +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"}, + }, + }, + }, + }, + } + + client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(platform, secret, cm).WithStatusSubresource(platform).Build() + utils.SetClient(client) + + 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"}, + }, + }, + }, + }, + } + + client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(platform).WithStatusSubresource(platform).Build() + utils.SetClient(client) + + 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/packages/kogito-serverless-operator/controllers/profiles/common/properties/properties_suite_test.go b/packages/kogito-serverless-operator/controllers/profiles/common/properties/properties_suite_test.go new file mode 100644 index 00000000000..4d5aa706ab0 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/properties/properties_suite_test.go @@ -0,0 +1,27 @@ +// Copyright 2023 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/profiles/common/properties/properties_test.go b/packages/kogito-serverless-operator/controllers/profiles/common/properties/properties_test.go new file mode 100644 index 00000000000..81c91ef89df --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/properties/properties_test.go @@ -0,0 +1,28 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/profiles/common/reconciler.go b/packages/kogito-serverless-operator/controllers/profiles/common/reconciler.go new file mode 100644 index 00000000000..49c77a0737d --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/reconciler.go @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/discovery" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform/services" + + "k8s.io/client-go/tools/record" + + "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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) + if err != nil { + return false, err + } + workflow.Status.ObservedGeneration = workflow.Generation + services.SetServiceUrlsInWorkflowStatus(pl, workflow) + 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/packages/kogito-serverless-operator/controllers/profiles/common/status_enricher.go b/packages/kogito-serverless-operator/controllers/profiles/common/status_enricher.go new file mode 100644 index 00000000000..99ca6b92416 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/status_enricher.go @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/controllers/profiles/common/variables/k8s.go b/packages/kogito-serverless-operator/controllers/profiles/common/variables/k8s.go new file mode 100644 index 00000000000..9a905f18b8d --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/common/variables/k8s.go @@ -0,0 +1,24 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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 ( + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + "k8s.io/apimachinery/pkg/util/intstr" +) + +var ( + DefaultHTTPWorkflowPortIntStr = intstr.FromInt(constants.DefaultHTTPWorkflowPortInt) +) diff --git a/packages/kogito-serverless-operator/controllers/profiles/dev/object_creators_dev.go b/packages/kogito-serverless-operator/controllers/profiles/dev/object_creators_dev.go new file mode 100644 index 00000000000..27e93d6b2a8 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/dev/object_creators_dev.go @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/cfg" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles" + 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" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/workflowdef" + kubeutil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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 + } + common.EnsureDeployment(original.(*appsv1.Deployment), object.(*appsv1.Deployment)) + return nil + } + } +} + +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(flowContainerIdx, &deployment.Spec.Template.Spec, volumeMounts...) + + return nil + } + } +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/dev/object_creators_dev_test.go b/packages/kogito-serverless-operator/controllers/profiles/dev/object_creators_dev_test.go new file mode 100644 index 00000000000..4ddb91df90e --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/dev/object_creators_dev_test.go @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/stretchr/testify/assert" + v1 "k8s.io/api/core/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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{"test": "test", "app": "greeting", "sonataflow.org/workflow-app": "greeting"}) +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/dev/profile_dev.go b/packages/kogito-serverless-operator/controllers/profiles/dev/profile_dev.go new file mode 100644 index 00000000000..c542ec5f653 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/dev/profile_dev.go @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/discovery" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/record" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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), + 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), + 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 + 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/packages/kogito-serverless-operator/controllers/profiles/dev/profile_dev_test.go b/packages/kogito-serverless-operator/controllers/profiles/dev/profile_dev_test.go new file mode 100644 index 00000000000..db469b01c27 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/dev/profile_dev_test.go @@ -0,0 +1,430 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/cfg" + "k8s.io/client-go/rest" + + corev1 "k8s.io/api/core/v1" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + kubeutil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/workflowdef" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" +) + +func Test_OverrideStartupProbe(t *testing.T) { + workflow := test.GetBaseSonataFlow(t.Name()) + + client := test.NewSonataFlowClientBuilder().WithRuntimeObjects(workflow).WithStatusSubresource(workflow).Build() + + 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() + + 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() + + 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() + 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() + 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, "quay.io/customgroup/custom-swf-builder-nightly:42.43.7", 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() + 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() + 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() + + 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() + + 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/packages/kogito-serverless-operator/controllers/profiles/dev/states_dev.go b/packages/kogito-serverless-operator/controllers/profiles/dev/states_dev.go new file mode 100644 index 00000000000..07e56dba052 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/dev/states_dev.go @@ -0,0 +1,272 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/workflowdef" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + kubeutil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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) + if err != nil { + return ctrl.Result{Requeue: false}, objs, err + } + if pl != nil && len(pl.Spec.DevMode.BaseImage) > 0 { + devBaseContainerImage = pl.Spec.DevMode.BaseImage + } + 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.StateSupport.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().MarkFalse(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) + + route, _, err := e.ensurers.network.Ensure(ctx, workflow) + if err != nil { + return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, objs, err + } + objs = append(objs, route) + + if knativeObjs, err := common.NewKnativeEventingHandler(e.StateSupport).Ensure(ctx, workflow); err != nil { + return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, objs, err + } else { + objs = append(objs, knativeObjs...) + } + + // 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) 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().MarkFalse(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/packages/kogito-serverless-operator/controllers/profiles/dev/status_enricher_dev.go b/packages/kogito-serverless-operator/controllers/profiles/dev/status_enricher_dev.go new file mode 100644 index 00000000000..37d6a513171 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/dev/status_enricher_dev.go @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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{workflowproj.LabelApp: labels[workflowproj.LabelApp]}, + } + 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/packages/kogito-serverless-operator/controllers/profiles/dev/status_enricher_dev_test.go b/packages/kogito-serverless-operator/controllers/profiles/dev/status_enricher_dev_test.go new file mode 100644 index 00000000000..9f614448b0c --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/dev/status_enricher_dev_test.go @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common" + + apiv08 "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/controllers/profiles/factory/factory.go b/packages/kogito-serverless-operator/controllers/profiles/factory/factory.go new file mode 100644 index 00000000000..1f31a78e919 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/factory/factory.go @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/gitops" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/preview" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/dev" +) + +const ( + defaultProfile = metadata.PreviewProfile +) + +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 := workflow.Annotations[metadata.Profile] + if len(profile) == 0 { + profile = defaultProfile.String() + } + // keep backward compatibility + if profile == metadata.ProdProfile.String() { + klog.V(log.W).Infof("Profile %s is deprecated, please use '%s' instead.", metadata.ProdProfile, metadata.PreviewProfile) + profile = metadata.PreviewProfile.String() + } + // Enforce GitOps profile if the .spec.podTemplate.container.image is set in the Preview profile. + if (profile == metadata.PreviewProfile.String() || profile == metadata.ProdProfile.String()) && workflow.HasContainerSpecImage() { + workflow.Annotations[metadata.Profile] = metadata.GitOpsProfile.String() + return profileBuilders[metadata.GitOpsProfile] + } + if _, ok := profileBuilders[metadata.ProfileType(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, defaultProfile) + return profileBuilders[defaultProfile] + } + return profileBuilders[metadata.ProfileType(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/packages/kogito-serverless-operator/controllers/profiles/gitops/alias.go b/packages/kogito-serverless-operator/controllers/profiles/gitops/alias.go new file mode 100644 index 00000000000..13c9ace53fc --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/gitops/alias.go @@ -0,0 +1,25 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/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/packages/kogito-serverless-operator/controllers/profiles/gitops/profile_gitops.go b/packages/kogito-serverless-operator/controllers/profiles/gitops/profile_gitops.go new file mode 100644 index 00000000000..824f794f838 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/gitops/profile_gitops.go @@ -0,0 +1,56 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/discovery" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/record" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +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/packages/kogito-serverless-operator/controllers/profiles/gitops/profile_gitops_test.go b/packages/kogito-serverless-operator/controllers/profiles/gitops/profile_gitops_test.go new file mode 100644 index 00000000000..39e1160b5df --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/gitops/profile_gitops_test.go @@ -0,0 +1,68 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" + "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" +) + +func Test_Reconciler_ProdOps(t *testing.T) { + workflow := test.GetBaseSonataFlowWithProdOpsProfile(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() + 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{"test": "test", "app": "simple", "sonataflow.org/workflow-app": "simple"}) +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/gitops/states_gitops.go b/packages/kogito-serverless-operator/controllers/profiles/gitops/states_gitops.go new file mode 100644 index 00000000000..6bc8561415b --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/gitops/states_gitops.go @@ -0,0 +1,71 @@ +// Copyright 2023 Red Hat, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/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 { + //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/packages/kogito-serverless-operator/controllers/profiles/preview/deployment_handler.go b/packages/kogito-serverless-operator/controllers/profiles/preview/deployment_handler.go new file mode 100644 index 00000000000..146e79ac423 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/preview/deployment_handler.go @@ -0,0 +1,131 @@ +// Copyright 2023 Red Hat, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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" + + v1 "k8s.io/api/core/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/reconcile" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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.reconcileWithBuiltImage(ctx, workflow, "") +} + +func (d *DeploymentReconciler) reconcileWithBuiltImage(ctx context.Context, workflow *operatorapi.SonataFlow, image string) (reconcile.Result, []client.Object, error) { + pl, _ := platform.GetActivePlatform(ctx, d.C, workflow.Namespace) + 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") + _, err = d.PerformStatusUpdate(ctx, workflow) + return ctrl.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") + _, err = d.PerformStatusUpdate(ctx, workflow) + return ctrl.Result{}, nil, err + } + + deployment, deploymentOp, err := + d.ensurers.deployment.Ensure( + ctx, + workflow, + pl, + d.getDeploymentMutateVisitors(workflow, pl, image, userPropsCM.(*v1.ConfigMap), managedPropsCM.(*v1.ConfigMap))..., + ) + if err != nil { + workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.DeploymentUnavailableReason, "Unable to perform the deploy due to ", err) + _, err = d.PerformStatusUpdate(ctx, workflow) + return reconcile.Result{}, nil, err + } + + service, _, err := d.ensurers.service.Ensure(ctx, workflow, common.ServiceMutateVisitor(workflow)) + if err != nil { + workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.DeploymentUnavailableReason, "Unable to make the service available due to ", err) + _, err = d.PerformStatusUpdate(ctx, workflow) + return reconcile.Result{}, nil, err + } + + knativeObjs, err := common.NewKnativeEventingHandler(d.StateSupport).Ensure(ctx, workflow) + if err != nil { + return ctrl.Result{RequeueAfter: constants.RequeueAfterFailure}, nil, err + } + objs := []client.Object{deployment, service, managedPropsCM} + objs = append(objs, knativeObjs...) + + if deploymentOp == controllerutil.OperationResultCreated { + workflow.Status.Manager().MarkFalse(api.RunningConditionType, api.WaitingForDeploymentReason, "") + if _, err := d.PerformStatusUpdate(ctx, workflow); err != nil { + return reconcile.Result{Requeue: false}, nil, err + } + return reconcile.Result{RequeueAfter: constants.RequeueAfterFollowDeployment, Requeue: true}, objs, nil + } + + // Follow deployment status + result, err := common.DeploymentManager(d.C).SyncDeploymentStatus(ctx, workflow) + if err != nil { + return reconcile.Result{Requeue: false}, nil, err + } + + if _, err := d.PerformStatusUpdate(ctx, workflow); err != nil { + return reconcile.Result{Requeue: false}, nil, err + } + return result, objs, nil +} + +func (d *DeploymentReconciler) getDeploymentMutateVisitors( + workflow *operatorapi.SonataFlow, + plf *operatorapi.SonataFlowPlatform, + image string, + userPropsCM *v1.ConfigMap, + managedPropsCM *v1.ConfigMap) []common.MutateVisitor { + if utils.IsOpenShift() { + return []common.MutateVisitor{common.DeploymentMutateVisitor(workflow, plf), + mountProdConfigMapsMutateVisitor(workflow, userPropsCM, managedPropsCM), + addOpenShiftImageTriggerDeploymentMutateVisitor(workflow, image), + common.ImageDeploymentMutateVisitor(workflow, image), + common.RolloutDeploymentIfCMChangedMutateVisitor(workflow, userPropsCM, managedPropsCM), + } + } + return []common.MutateVisitor{common.DeploymentMutateVisitor(workflow, plf), + common.ImageDeploymentMutateVisitor(workflow, image), + mountProdConfigMapsMutateVisitor(workflow, userPropsCM, managedPropsCM), + common.RolloutDeploymentIfCMChangedMutateVisitor(workflow, userPropsCM, managedPropsCM)} +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/preview/deployment_handler_test.go b/packages/kogito-serverless-operator/controllers/profiles/preview/deployment_handler_test.go new file mode 100644 index 00000000000..2435f757fbe --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/preview/deployment_handler_test.go @@ -0,0 +1,184 @@ +// Copyright 2023 Red Hat, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj" + "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" +) + +func Test_CheckPodTemplateChangesReflectDeployment(t *testing.T) { + workflow := test.GetBaseSonataFlowWithProdOpsProfile(t.Name()) + + client := test.NewSonataFlowClientBuilder(). + WithRuntimeObjects(workflow). + WithStatusSubresource(workflow). + Build() + stateSupport := fakeReconcilerSupport(client) + 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 := "quay.io/apache/my-new-workflow:1.0.0" + 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) + 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 + } + } +} + +func Test_CheckDeploymentRolloutAfterCMChange(t *testing.T) { + workflow := test.GetBaseSonataFlowWithProdOpsProfile(t.Name()) + + client := test.NewSonataFlowClientBuilder(). + WithRuntimeObjects(workflow). + WithStatusSubresource(workflow). + Build() + stateSupport := fakeReconcilerSupport(client) + 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.GetBaseSonataFlowWithProdOpsProfile(t.Name()) + + client := test.NewSonataFlowClientBuilder(). + WithRuntimeObjects(workflow). + WithStatusSubresource(workflow). + Build() + stateSupport := fakeReconcilerSupport(client) + 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/packages/kogito-serverless-operator/controllers/profiles/preview/object_creators_preview.go b/packages/kogito-serverless-operator/controllers/profiles/preview/object_creators_preview.go new file mode 100644 index 00000000000..51898699132 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/preview/object_creators_preview.go @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + kubeutil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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 + } + } +} + +// mountDevConfigMapsMutateVisitor mounts the required configMaps in the Workflow Dev Deployment +func mountProdConfigMapsMutateVisitor(workflow *operatorapi.SonataFlow, userPropsCM *v1.ConfigMap, managedPropsCM *v1.ConfigMap) common.MutateVisitor { + return func(object client.Object) controllerutil.MutateFn { + return func() error { + deployment := object.(*appsv1.Deployment) + _, idx := kubeutil.GetContainerByName(v1alpha08.DefaultContainerName, &deployment.Spec.Template.Spec) + + if len(deployment.Spec.Template.Spec.Volumes) == 0 { + deployment.Spec.Template.Spec.Volumes = make([]v1.Volume, 0, 1) + } + if len(deployment.Spec.Template.Spec.Containers[idx].VolumeMounts) == 0 { + deployment.Spec.Template.Spec.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(&deployment.Spec.Template.Spec, defaultResourcesVolume) + kubeutil.AddOrReplaceVolumeMount(idx, &deployment.Spec.Template.Spec, + kubeutil.VolumeMount(constants.ConfigMapWorkflowPropsVolumeName, true, quarkusProdConfigMountPath)) + + return kubeutil.AnnotateDeploymentConfigChecksum(workflow, deployment, userPropsCM, managedPropsCM) + } + } +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/preview/profile_preview.go b/packages/kogito-serverless-operator/controllers/profiles/preview/profile_preview.go new file mode 100644 index 00000000000..28f7e2870cc --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/preview/profile_preview.go @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + "k8s.io/client-go/rest" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/discovery" + "k8s.io/client-go/tools/record" + + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/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 Production 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 common.ObjectEnsurerWithPlatform + service common.ObjectEnsurer + userPropsConfigMap common.ObjectEnsurer + managedPropsConfigMap common.ObjectEnsurerWithPlatform +} + +// NewObjectEnsurers common.ObjectEnsurer(s) for the preview profile. +func NewObjectEnsurers(support *common.StateSupport) *ObjectEnsurers { + return &ObjectEnsurers{ + deployment: common.NewObjectEnsurerWithPlatform(support.C, common.DeploymentCreator), + service: common.NewObjectEnsurer(support.C, common.ServiceCreator), + 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}, + &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/packages/kogito-serverless-operator/controllers/profiles/preview/profile_preview_test.go b/packages/kogito-serverless-operator/controllers/profiles/preview/profile_preview_test.go new file mode 100644 index 00000000000..d45fc562380 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/preview/profile_preview_test.go @@ -0,0 +1,202 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" + "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" +) + +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() + _, 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{"test": "test", "app": "greeting", "sonataflow.org/workflow-app": "greeting"}) +} + +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() + + 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()) + build := test.GetLocalSucceedSonataFlowBuild(workflow.Name, workflow.Namespace) + client := test.NewSonataFlowClientBuilder(). + WithRuntimeObjects(workflow, platform, build). + WithStatusSubresource(workflow, platform, build). + Build() + 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, 3) + + 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) +} + +func Test_GenerationAnnotationCheck(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() + + 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 a workflow with metadata.generation set to 1 + workflowChanged := &operatorapi.SonataFlow{} + err = client.Get(context.TODO(), clientruntime.ObjectKeyFromObject(workflow), workflowChanged) + assert.NoError(t, err) + //we set the generation to 1 + workflowChanged.Generation = int64(1) + err = client.Update(context.TODO(), workflowChanged) + assert.NoError(t, err) + // reconcile + 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(), + } +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/preview/states_preview.go b/packages/kogito-serverless-operator/controllers/profiles/preview/states_preview.go new file mode 100644 index 00000000000..e1b29437531 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/preview/states_preview.go @@ -0,0 +1,207 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/builder" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + kubeutil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" +) + +type newBuilderState struct { + *common.StateSupport +} + +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) { + _, err := platform.GetActivePlatform(ctx, h.C, workflow.Namespace) + if err != nil { + if errors.IsNotFound(err) { + workflow.Status.Manager().MarkFalse(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 + } + // 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().MarkFalse(api.BuiltConditionType, api.BuildFailedReason, + "Failed to retrieve or create a Build CR", 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().MarkFalse(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) + if err != nil { + workflow.Status.Manager().MarkFalse(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 + } + + if h.isWorkflowChanged(workflow) { // 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 + return NewDeploymentReconciler(h.StateSupport, h.ensurers).reconcileWithBuiltImage(ctx, workflow, build.Status.ImageTag) +} + +func (h *deployWithBuildWorkflowState) 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 +} + +// isWorkflowChanged marks the workflow status as unknown to require a new build reconciliation +func (h *deployWithBuildWorkflowState) isWorkflowChanged(workflow *operatorapi.SonataFlow) bool { + generation := kubeutil.GetLastGeneration(workflow.Namespace, workflow.Name, h.C, context.TODO()) + if generation > workflow.Status.ObservedGeneration { + return true + } + return false +} diff --git a/packages/kogito-serverless-operator/controllers/profiles/profile.go b/packages/kogito-serverless-operator/controllers/profiles/profile.go new file mode 100644 index 00000000000..251bf0bf433 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/profile.go @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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 diff --git a/packages/kogito-serverless-operator/controllers/profiles/profile_test.go b/packages/kogito-serverless-operator/controllers/profiles/profile_test.go new file mode 100644 index 00000000000..1c40c456867 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/profiles/profile_test.go @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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)) +} diff --git a/packages/kogito-serverless-operator/controllers/sonataflow_controller.go b/packages/kogito-serverless-operator/controllers/sonataflow_controller.go new file mode 100644 index 00000000000..6e66ce62767 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/sonataflow_controller.go @@ -0,0 +1,191 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package controllers + +import ( + "context" + "fmt" + + "k8s.io/klog/v2" + + profiles "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/factory" + + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/rest" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform" +) + +// 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/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 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 + } + + // 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 profiles.NewReconciler(r.Client, r.Config, r.Recorder, workflow).Reconcile(ctx, workflow) +} + +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 { + return ctrl.NewControllerManagedBy(mgr). + For(&operatorapi.SonataFlow{}). + Owns(&appsv1.Deployment{}). + 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) + })). + Complete(r) +} diff --git a/packages/kogito-serverless-operator/controllers/sonataflow_controller_test.go b/packages/kogito-serverless-operator/controllers/sonataflow_controller_test.go new file mode 100644 index 00000000000..755e1a4c8d9 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/sonataflow_controller_test.go @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package controllers + +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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" +) + +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) + // 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 + + 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) + }) +} diff --git a/packages/kogito-serverless-operator/controllers/sonataflowbuild_controller.go b/packages/kogito-serverless-operator/controllers/sonataflowbuild_controller.go new file mode 100644 index 00000000000..52c4e8a65c2 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/sonataflowbuild_controller.go @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package controllers + +import ( + "context" + "fmt" + "reflect" + "time" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/workflows" + kubeutil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" + "k8s.io/klog/v2" + + 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/builder" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/controllers/sonataflowbuild_controller_test.go b/packages/kogito-serverless-operator/controllers/sonataflowbuild_controller_test.go new file mode 100644 index 00000000000..16957d3952c --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/sonataflowbuild_controller_test.go @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package controllers + +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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/controllers/sonataflowclusterplatform_controller.go b/packages/kogito-serverless-operator/controllers/sonataflowclusterplatform_controller.go new file mode 100644 index 00000000000..c7120eafd11 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/sonataflowclusterplatform_controller.go @@ -0,0 +1,175 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package controllers + +import ( + "context" + "fmt" + "time" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + clientr "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/clusterplatform" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + 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" +) + +// 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, r.Client) + 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/packages/kogito-serverless-operator/controllers/sonataflowplatform_controller.go b/packages/kogito-serverless-operator/controllers/sonataflowplatform_controller.go new file mode 100644 index 00000000000..c1a6a5de539 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/sonataflowplatform_controller.go @@ -0,0 +1,286 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package controllers + +import ( + "context" + "fmt" + "time" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + clientr "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/clusterplatform" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform/services" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + appsv1 "k8s.io/api/apps/v1" + 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" +) + +// 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 + +// 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.SonataFlowPlatformUpdateStatus(ctx, req, target); err != nil { + return reconcile.Result{}, err + } + + 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, err = a.Handle(ctx, target) + if err != nil { + if target != 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 SonataFlowPlaform: %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 platform condition %s", instance.Status.GetTopLevelCondition())) + return reconcile.Result{}, err + } + + if err := r.Client.Update(ctx, target); err != nil { + r.Recorder.Event(&instance, corev1.EventTypeNormal, "Spec Updated", fmt.Sprintf("Updated platform condition to %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 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 + +} + +// If an active cluster platform exists, update platform.Status accordingly +func (r *SonataFlowPlatformReconciler) SonataFlowPlatformUpdateStatus(ctx context.Context, req reconcile.Request, target *operatorapi.SonataFlowPlatform) error { + // Fetch the active SonataFlowClusterPlatform instance + sfcPlatform, err := clusterplatform.GetActiveClusterPlatform(ctx, r.Client) + 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 { + return 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)). + 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 { + platform := object.(*operatorapi.SonataFlowPlatform) + sfcPlatform, err := clusterplatform.GetActiveClusterPlatform(ctx, r.Client) + 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(platform) == 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 _, platform := range plList.Items { + sfpNsName := client.ObjectKeyFromObject(&platform) + // 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 +} diff --git a/packages/kogito-serverless-operator/controllers/sonataflowplatform_controller_test.go b/packages/kogito-serverless-operator/controllers/sonataflowplatform_controller_test.go new file mode 100644 index 00000000000..b814a9e6486 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/sonataflowplatform_controller_test.go @@ -0,0 +1,830 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package controllers + +import ( + "context" + "testing" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/clusterplatform" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform/services" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" + "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" + "sigs.k8s.io/controller-runtime/pkg/reconcile" +) + +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() + // 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, "quay.io/kiegroup", 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.ServiceSpec{}, + } + + // Create a fake client to mock API calls. + cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build() + // 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, "quay.io/kiegroup", 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.ServiceSpec{ + PodTemplate: v1alpha08.PodTemplateSpec{ + Replicas: &replicas, + Container: v1alpha08.ContainerSpec{ + Command: []string{"test:latest"}, + }, + }, + }, + } + + di := services.NewDataIndexHandler(ksp) + + // Create a fake client to mock API calls. + cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build() + // 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, "quay.io/kiegroup", 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.ServiceSpec{}, + JobService: &v1alpha08.ServiceSpec{}, + }, + 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() + // 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", + } + 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) + }) + + 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.ServiceSpec{ + Persistence: &v1alpha08.PersistenceOptionsSpec{ + PostgreSQL: &v1alpha08.PersistencePostgreSQL{ + SecretRef: v1alpha08.PostgreSQLSecretOptions{Name: "dataIndex"}, + JdbcUrl: urlDI, + }, + }, + }, + JobService: &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() + // 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.ServiceSpec{}, + } + + // Create a fake client to mock API calls. + cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build() + // 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, "quay.io/kiegroup", 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.ServiceSpec{ + PodTemplate: v1alpha08.PodTemplateSpec{ + Replicas: &replicas, + Container: v1alpha08.ContainerSpec{ + Command: []string{"test:latest"}, + }, + }, + }, + } + + js := services.NewJobServiceHandler(ksp) + + // Create a fake client to mock API calls. + cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build() + // 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, "quay.io/kiegroup", 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.ServiceSpec{}, + JobService: &v1alpha08.ServiceSpec{}, + } + + di := services.NewDataIndexHandler(ksp) + js := services.NewJobServiceHandler(ksp) + // Create a fake client to mock API calls. + cl := test.NewKogitoClientBuilderWithOpenShift().WithRuntimeObjects(ksp).WithStatusSubresource(ksp).Build() + // 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, "quay.io/kiegroup", 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.ServiceSpec{}, + JobService: &v1alpha08.ServiceSpec{}, + } + 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() + + // 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, "quay.io/kiegroup", 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) + }) +} diff --git a/packages/kogito-serverless-operator/controllers/suite_test.go b/packages/kogito-serverless-operator/controllers/suite_test.go new file mode 100644 index 00000000000..1f1b76d469b --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/suite_test.go @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package controllers + +import ( + "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" + + apiv08 "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + //+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 + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "Controller Suite") +} + +var _ = BeforeSuite(func() { + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")}, + ErrorIfCRDPathMissing: true, + } + + var err error + // 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") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/packages/kogito-serverless-operator/controllers/workflowdef/configmap.go b/packages/kogito-serverless-operator/controllers/workflowdef/configmap.go new file mode 100644 index 00000000000..f04580b8c21 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/workflowdef/configmap.go @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/kubernetes" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/controllers/workflowdef/image.go b/packages/kogito-serverless-operator/controllers/workflowdef/image.go new file mode 100644 index 00000000000..41a2f112c91 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/workflowdef/image.go @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/cfg" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/version" +) + +const ( + latestImageTag = "latest" + nightlySuffix = "nightly" + defaultWorkflowDevModeImage = "quay.io/kiegroup/kogito-swf-devmode" + defaultWorkflowBuilderImage = "quay.io/kiegroup/kogito-swf-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 + ":" + 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 { + if version.IsSnapshot() { + imgTag += "-" + nightlySuffix + } + imgTag += ":" + if version.IsLatestVersion() { + imgTag += latestImageTag + } else { + imgTag += version.GetMajorMinor() + } + return imgTag +} diff --git a/packages/kogito-serverless-operator/controllers/workflowdef/json.go b/packages/kogito-serverless-operator/controllers/workflowdef/json.go new file mode 100644 index 00000000000..0fd786753e4 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/workflowdef/json.go @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + + "k8s.io/klog/v2" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/controllers/workflowdef/json_test.go b/packages/kogito-serverless-operator/controllers/workflowdef/json_test.go new file mode 100644 index 00000000000..cca72c937df --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/workflowdef/json_test.go @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/controllers/workflowdef/services.go b/packages/kogito-serverless-operator/controllers/workflowdef/services.go new file mode 100644 index 00000000000..19b21812f98 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/workflowdef/services.go @@ -0,0 +1,29 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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 ( + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + cncfmodel "github.com/serverlessworkflow/sdk-go/v2/model" +) + +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/packages/kogito-serverless-operator/controllers/workflowdef/utils.go b/packages/kogito-serverless-operator/controllers/workflowdef/utils.go new file mode 100644 index 00000000000..83a65de58e2 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/workflowdef/utils.go @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/serverlessworkflow/sdk-go/v2/model" +) + +// 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) +} diff --git a/packages/kogito-serverless-operator/controllers/workflowdef/utils_suite_test.go b/packages/kogito-serverless-operator/controllers/workflowdef/utils_suite_test.go new file mode 100644 index 00000000000..aa3919a7508 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/workflowdef/utils_suite_test.go @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/controllers/workflowdef/utils_test.go b/packages/kogito-serverless-operator/controllers/workflowdef/utils_test.go new file mode 100644 index 00000000000..b83249e92fe --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/workflowdef/utils_test.go @@ -0,0 +1,285 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + cncfmodel "github.com/serverlessworkflow/sdk-go/v2/model" +) + +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/packages/kogito-serverless-operator/controllers/workflows/constants.go b/packages/kogito-serverless-operator/controllers/workflows/constants.go new file mode 100644 index 00000000000..afcf157a1b6 --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/workflows/constants.go @@ -0,0 +1,24 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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 + +const ( + QuarkusFlywayMigrateAtStart string = "quarkus.flyway.migrate-at-start" + 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" +) diff --git a/packages/kogito-serverless-operator/controllers/workflows/workflows.go b/packages/kogito-serverless-operator/controllers/workflows/workflows.go new file mode 100644 index 00000000000..5e6d53f87be --- /dev/null +++ b/packages/kogito-serverless-operator/controllers/workflows/workflows.go @@ -0,0 +1,60 @@ +// Copyright 2023 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +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/packages/kogito-serverless-operator/docs/CONTRIBUTING.md b/packages/kogito-serverless-operator/docs/CONTRIBUTING.md new file mode 100644 index 00000000000..9fbfff4876a --- /dev/null +++ b/packages/kogito-serverless-operator/docs/CONTRIBUTING.md @@ -0,0 +1,239 @@ +# We love contributions! + +- [We love contributions!](#we-love-contributions) + - [How can I contribute?](#how-can-i-contribute) + - [Contributing to the SonataFlow Operator codebase](#contributing-to-the-sonataflow-operator-codebase) + - [Contributing to the SonataFlow Operator](#contributing-to-the-sonataflow-operator) + - [Prerequisites](#prerequisites) + - [Getting Started](#getting-started) + - [Test It Out locally](#test-it-out-locally) + - [How-tos](#how-tos) + - [Modifying the API definitions](#modifying-the-api-definitions) + - [Building](#building) + - [Deploy](#deploy) + - [Undeploy](#undeploy) + - [Running the operator on the cluster](#running-the-operator-on-the-cluster) + - [Configuration](#configuration) + - [Customize Builder Image](#customize-builder-image) +- [Development status](#development-status) + - [General notes](#general-notes) + - [Workflow CR](#workflow-cr) + - [Platform CR](#platform-cr) + - [Improvements](#improvements) +- [Tekton Pipeline to build and deploy the Operator](#tekton-pipeline-to-build-and-deploy-the-operator) + +## How can I contribute? + +There are many ways you can contribute to SonataFlow Operator, not only software development, as well as +with the rest of Kogito community: + +- Contribute actively to development (see the section below) +- Use it and report any feedback, improvement or bug you may find via Github, mailing list or chat. +- Contribute by writing missing documentation or blog posts about the features around Kogito +- Tweet, like and socialize Kogito in your preferred social network +- Enjoy the talks that the contributors submit in various conferences around the world + +## Contributing to the SonataFlow Operator codebase + +The main project is written in go. +SonataFlow Operator is built on top of Kubernetes through Custom Resource Definitions. + +- Workflow +- Platform +- Build + +This project aims to follow the +Kubernetes [Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) + +It uses [Controllers](https://kubernetes.io/docs/concepts/architecture/controller/) +which provides a reconcile function responsible for synchronizing resources untile the desired state is reached on the +cluster + +## Contributing to the SonataFlow Operator + +### Prerequisites + +The Operator's controllers and the configurations are generated using the Operator sdk, the tasks are executed using a +Makefile. + +More information about annotations can be found via +the [Kubebuilder Documentation](https://book.kubebuilder.io/introduction.html) + +In order to build the project, you need to comply with the following requirements: + +- [operator-sdk-v1.25.0+](https://sdk.operatorframework.io/docs/building-operators/golang/installation/) +- [Go 1.21+](https://go.dev/dl/) +- [Kubebuilder 3.7.0+](https://github.com/kubernetes-sigs/kubebuilder/releases) +- [CEKit 4.8.0+](https://cekit.io/) + +GNU Make: +Used to define composite build actions. This should be already installed or available as a +package (https://www.gnu.org/software/make/). + +> **NOTE:** Run `make help` for more information on all potential `make` targets + +### Getting Started + +You’ll need a Kubernetes cluster to run against. You can use: + +- [KIND](https://sigs.k8s.io/kind) +- [MINIKUBE](https://minikube.sigs.k8s.io) +- [Openshift Local](https://console.redhat.com/openshift/create/local) +- [Openshift-developer-sandbox-trial](https://www.redhat.com/en/technologies/cloud-computing/openshift/openshift-developer-sandbox-trial) + +> **NOTE:** Your controller will automatically use the current context in your kubeconfig file (i.e. whatever +> cluster `kubectl cluster-info` shows). + +> **IMPORTANT**: Please make sure that your [kubectl](https://kubernetes.io/docs/tasks/tools/) is version 1.24.0 or +> later +> since there's a bug performing validation on default attributes in Custom Resources. + +### Test It Out locally + +You can launch the operator locally and bind to your cluster. + +1. Install the CRDs into the cluster: + +```sh +make install +``` + +2. Run your controller (this will run in the foreground, so switch to a new terminal if you want to leave it running): + +```sh Kubernetes cluster to run against. You can use: +make run +``` + +> **NOTE:** You can also run this in one step by running: `make install run` + +> **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) + +### How-tos + +#### Modifying the API definitions + +If you are editing the API definitions, generate the manifests such as CRs or CRDs using: + +```sh +make manifests +``` + +#### Building + +```sh +make container-build +``` + +#### Deploy + +```sh +make deploy +``` + +#### Undeploy + +```sh +make undeploy +``` + +### Change log level + +By Default the log level is set to show only ERRORS with + +```sh +- "--v=0" +``` + +inside the manager_auth_proxy_patch.yaml in the containers' section of kube-rbac-proxy and manager. + +With the + +```sh +make generate-all +``` + +whese values will be replicated on operator.yaml and on sonataflow-operator.clusterserviceversion.yaml containers' sections. + +If you want to see the INFO msg replace v=0 with v=2 in the files during the development or in the deployment files on the cluster + +The available levels are: + +- v=0 > Error +- v=1 > Warning +- v=2 >Info +- v=3 > Debug + +### Running the operator on the cluster + +See the section on [README](../README.md#getting-started) + +### Configuration + +A configmap called `sonataflow-operator-builder-config` will be created under the `sonataflow-operator-system` namespace +when the Operator will be installed, and it contains: + +- DEFAULT_WORKFLOW_EXTENSION = .sw.json +- Dockerfile = `` + +## Customize Builder Image + +At the startup a [Dockerfile](../config/manager/SonataFlow-Builder.containerfile) is placed in a configmap. This +Dockerfile uses a base image +called [kogito-swf-builder](https://github.com/kiegroup/kogito-images/tree/master/modules/kogito-swf-builder) with: + +- openjdk 11+ +- maven 3.8.6+ +- a Quarkus project `/home/kogito/serverless-workflow-project` with those extensions: + - quarkus-kubernetes + - kogito-quarkus-serverless-workflow + - kogito-addons-quarkus-knative-eventing +- all the dependencies of Quarkus and the extensions stored in the `/home/kogito/.m2` directory in the image. + +There are, in the base image, some additional scripts in case of need to apply changes like this: + +- add other quarkus extensions in `/home/kogito/launch/add-extension.sh` +- build the project after adding other files/java classes in `/home/kogito/launch/build-app.sh` +- create a new project in `/home/kogito/launch/create-app.sh` + +You can customize your final Image changing the Dockerfile in the configmap sonataflow-operator-builder-config +accordingly to your specific needs. + +# Development status + +## General notes + +### Workflow CR + +- At the moment we are supporting only deployment of services on Kubernetes + +### Platform CR + +- The only tested features are the ones related to the docker Registry customization and so: + +``` + apiVersion: sonataflow.org/v1alpha08 + kind: SonataFlowPlatform + metadata: + name: greeting-workflow-platform + spec: + platform: + registry: + address: // the URI to access + secret: // the secret where credentials are stored + insecure: true // if the container registry is insecure (ie, http only) + ca: // the configmap which stores the Certificate Authority + organization: // the registry organization +``` + +## Improvements + +- Introduce actions into Workflow and Build controller to improve code clarity +- Add Trait to the Platform CR in order to be able to deploy on different context (i.e. KNative) +- Test the Kaniko cache feature +- Improve the workflow converters in order to support all the SonataFlow Workflow features + +# Tekton Pipeline to build and deploy the Operator + +Setup a [pipeline](docs/PIPELINE.md) on a Openshift cluster. diff --git a/packages/kogito-serverless-operator/docs/PIPELINE.md b/packages/kogito-serverless-operator/docs/PIPELINE.md new file mode 100644 index 00000000000..18335811afc --- /dev/null +++ b/packages/kogito-serverless-operator/docs/PIPELINE.md @@ -0,0 +1,127 @@ +## Install and configure a Tekton pipeline on Openshift + +1. Install Red Hat OpenShift Pipelines on `latest` channel from the Operator Hub using the Openshift UI + +2. If you want interact via cli with the pipeline you can install locally Tekton cli + To interact with the pipelines, you can download from the details of the operator installed (i.e. crc link) : + https://tkn-cli-serve-openshift-pipelines.apps-crc.testing/tkn/tkn-linux-amd64.tar.gz + The version proposed by the Operator is correctly aligned version with the tekton version. + +3. If isn't yet created, create the project `sonataflow-operator-system` + +```sh +oc new-project sonataflow-operator-system +``` + +4. Install the Tekton `kubernetes-actions` task + +```sh +kubectl apply -f https://api.hub.tekton.dev/v1/resource/tekton/task/kubernetes-actions/0.2/raw +``` + +5. Apply the cluster role and cluster role binding + +```sh +kubectl create -f tekton/role/cluster_role.yaml +kubectl create -f tekton/role/cluster_role_binding.yaml +``` + +6. Create the pipeline + +```sh +kubectl apply -f tekton/pipeline/kogito_serverless_operator_pipeline.yaml +``` + +7. Create a pipeline run + +```sh +kubectl apply -f tekton/pipeline/kogito_serverless_operator_pipeline_run.yaml +``` + +or with the Tekton cli: + +```sh +tkn pipeline start kogito-serverless-operator-pipeline \ + -w name=shared-workspace,volumeClaimTemplateFile=https://raw.githubusercontent.com/apache/incubator-kie-kogito-serverless-operator/main/tekton/volume/persistent_volume.yaml \ + -p deployment-name=kogito-serverless-operator \ + -p git-url=https://github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator.git \ + -p git-revision=main \ + -p IMAGE='image-registry.openshift-image-registry.svc:5000/sonataflow-operator-system/kogito-serverless-operator:latest' \ + --use-param-defaults +``` + +8. Check the Pipeline execution + +Open the Pipeline menu under the namespace/project `sonataflow-operator-system` +or with the Tekton cli (use the pipeline run id): + +```sh +tkn pipelinerun logs kogito-serverless-operator-pipeline-run- -f -n +``` + +### How to see the content of the workspace + +1. Create the task `show_workspace_content` + +```sh +kubectl apply -f tekton/task/show_workspace_content.yaml +``` + +2. Add the task `show-workspace` in the pipeline after the `fetch-repository` or `build-image` + +### How to redeploy + +Go to the pipeline runs and ask for a rerun of a previous pipeline run + +## Trigger the pipeline on GithubEvents + +1. Create the trigger binding + +```sh +oc create -f tekton/trigger/trigger_binding.yaml +``` + +2. Create the trigger template + +```sh +oc create -f tekton/trigger/trigger_template.yaml +``` + +3. Create the trigger resource + +```sh +oc create -f tekton/trigger/trigger_resource.yaml +``` + +4. Add a label to enable the secure HTTPS connection to the Eventlistener resource + +```sh +oc label namespace sonataflow-operator-system operator.tekton.dev/enable-annotation=enabled +``` + +5. Create the Event listener trigger + +```sh +oc create -f tekton/trigger/trigger_event_listener.yaml +``` + +6. Create a route with the re-encrypted TLS termination + +```sh +oc create route reencrypt --service=el-kogito-serverless-operator-webhook --cert=tls.crt --key=tls.key --ca-cert=ca.crt --hostname= +``` + +7. Check the webhook + +```sh +tkn el -n kogito-serverless-operator-pipeline ls +``` + +```sh +kubectl get pods,svc -n kogito-serverless-operator-pipeline -l eventlistener=kogito-serverless-operator-webhook +``` + +8. Add a webhook in your github/gitlab repo with the url of the listener on openshift + +9. Authenticating pipelines using git secret + https://docs.openshift.com/container-platform/4.12/cicd/pipelines/authenticating-pipelines-using-git-secret.html diff --git a/packages/kogito-serverless-operator/env/index.js b/packages/kogito-serverless-operator/env/index.js new file mode 100644 index 00000000000..d3de48848c7 --- /dev/null +++ b/packages/kogito-serverless-operator/env/index.js @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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"); + +module.exports = composeEnv([require("@kie-tools/root-env/env")], { + vars: varsWithName({ + KOGITO_SERVERLESS_OPERATOR__registry: { + default: "quay.io", + description: "The image registry.", + }, + KOGITO_SERVERLESS_OPERATOR__account: { + default: "kiegroup", + description: "The image registry account.", + }, + KOGITO_SERVERLESS_OPERATOR__name: { + default: "kogito-serverless-operator-nightly", + description: "The image name.", + }, + KOGITO_SERVERLESS_OPERATOR__buildTag: { + default: "latest", + description: "The image tag", + }, + }), + get env() { + return { + kogitoServerlessOperator: { + registry: getOrDefault(this.vars.KOGITO_SERVERLESS_OPERATOR__registry), + account: getOrDefault(this.vars.KOGITO_SERVERLESS_OPERATOR__account), + name: getOrDefault(this.vars.KOGITO_SERVERLESS_OPERATOR__name), + tag: getOrDefault(this.vars.KOGITO_SERVERLESS_OPERATOR__buildTag), + version: require("../package.json").version, + }, + }; + }, +}); diff --git a/packages/kogito-serverless-operator/go.mod b/packages/kogito-serverless-operator/go.mod new file mode 100644 index 00000000000..a1ea3f0268b --- /dev/null +++ b/packages/kogito-serverless-operator/go.mod @@ -0,0 +1,135 @@ +module github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator + +go 1.21 + +// Internal dependencies +replace ( + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api v0.0.0 => ./api + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder v0.0.0 => ./container-builder + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj v0.0.0 => ./workflowproj +) + +// Direct dependencies (please keep organized, no indirects) +require ( + github.com/RHsyseng/operator-utils v1.4.13 + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api v0.0.0 + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder v0.0.0 + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj v0.0.0 + github.com/go-logr/logr v1.2.4 // indirect + github.com/magiconair/properties v1.8.7 + github.com/onsi/ginkgo/v2 v2.13.0 + github.com/onsi/gomega v1.30.0 + github.com/openshift/api v0.0.0-20230522130544-0eef84f63102 + github.com/openshift/client-go v0.0.0-20230503144108-75015d2347cb + 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.2.5 + github.com/stretchr/testify v1.8.4 + k8s.io/api v0.27.6 + k8s.io/apimachinery v0.27.6 + k8s.io/client-go v0.27.6 + knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c + knative.dev/serving v0.39.0 + sigs.k8s.io/controller-runtime v0.15.0 + sigs.k8s.io/yaml v1.3.0 +) + +require ( + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc + github.com/imdario/mergo v0.3.16 + k8s.io/klog/v2 v2.100.1 + knative.dev/eventing v0.26.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/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/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cloudevents/sdk-go/v2 v2.15.2 // indirect + github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect + github.com/emicklei/go-restful/v3 v3.10.2 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.7.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/ghodss/yaml v1.0.0 // 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.0 // indirect + github.com/go-playground/universal-translator v0.18.0 // indirect + github.com/go-playground/validator/v10 v10.11.1 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // 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.3 // indirect + github.com/google/gnostic v0.6.9 // 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-20230705174524-200ffdc848b8 // indirect + github.com/google/uuid v1.3.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.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/json-iterator/go v1.1.12 // indirect + github.com/kelseyhightower/envconfig v1.4.0 // indirect + github.com/leodido/go-urn v1.2.1 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/moby/spdystream v0.2.0 // 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/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.17.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/statsd_exporter v0.22.7 // indirect + github.com/relvacode/iso8601 v1.3.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/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect + go.opencensus.io v0.24.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.26.0 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/sync v0.4.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.14.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + google.golang.org/api v0.147.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect + google.golang.org/grpc v1.58.3 // indirect + google.golang.org/protobuf v1.33.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.27.6 // indirect + k8s.io/component-base v0.27.6 // indirect + k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 // indirect + k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // 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.3.0 // indirect +) diff --git a/packages/kogito-serverless-operator/go.sum b/packages/kogito-serverless-operator/go.sum new file mode 100644 index 00000000000..f6b34f6221e --- /dev/null +++ b/packages/kogito-serverless-operator/go.sum @@ -0,0 +1,1227 @@ +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 v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +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.0/go.mod h1:o7cosnyfuPVK0tB8q0QmaQNhGnptITnPQB+z1+qeFB0= +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= +contrib.go.opencensus.io/exporter/zipkin v0.1.2/go.mod h1:mP5xM3rrgOjpn79MM8fZbj3gsxcuytSqtH0dxSWW1RE= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +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/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/RHsyseng/operator-utils v1.4.13 h1:kCsvBXm1Y3AEfzjioUvk/RmOigM/+czd/U5YQ3SZXx8= +github.com/RHsyseng/operator-utils v1.4.13/go.mod h1:f+GrcLNALoHBPonk3P6KCwPK5kYyHhkqj4vuCP2Eijc= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/ahmetb/gen-crd-api-reference-docs v0.3.1-0.20210420163308-c1402a70e2f1/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8= +github.com/alecthomas/jsonschema v0.0.0-20180308105923-f2c93856175a/go.mod h1:qpebaTNSsyUn5rPSJMsfqEtDw71TTggXM6stUDI16HA= +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/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +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/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +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/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/c2h5oh/datasize v0.0.0-20171227191756-4eba002a5eae/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/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 v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.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/conformance v0.2.0/go.mod h1:rHKDwylBH89Rns6U3wL9ww8bg9/4GbwRCDNuyoC6bcc= +github.com/cloudevents/sdk-go/observability/opencensus/v2 v2.4.1/go.mod h1:lhEpxMrIUkeu9rVRgoAbyqZ8GR8Hd3DUy+thHUxAHoI= +github.com/cloudevents/sdk-go/v2 v2.4.1/go.mod h1:MZiMwmAh5tGj+fPFvtHv9hKurKqXtdB9haJYMJ/7GJY= +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/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11/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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-gk v0.0.0-20140819190930-201884a44051/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E= +github.com/dgryski/go-gk v0.0.0-20200319235926-a69029f61654/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E= +github.com/dgryski/go-lttb v0.0.0-20180810165845-318fcdf10a77/go.mod h1:Va5MyIzkU0rAM92tn3hb3Anb7oz7KcnixF49+2wOMe4= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +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/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE= +github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +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.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= +github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +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.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/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 v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.4.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.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +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.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +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/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +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.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +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-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/gobuffalo/flect v0.2.3/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +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/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= +github.com/gonum/diff v0.0.0-20181124234638-500114f11e71/go.mod h1:22dM4PLscQl+Nzf64qNBurVJvfyvZELT0iRW2l/NN70= +github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= +github.com/gonum/integrate v0.0.0-20181209220457-a422b5c0fdf2/go.mod h1:pDgmNM6seYpwvPos3q+zxlXMsbve6mOIPucUnUOrI7Y= +github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks= +github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A= +github.com/gonum/mathext v0.0.0-20181121095525-8a4bf007ea55/go.mod h1:fmo8aiSEWkJeiGXUJf+sPvuDgEFgqIoZSs843ePKrGg= +github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= +github.com/gonum/stat v0.0.0-20181125101827-41a0da705a5b/go.mod h1:Z4GIJBJO3Wa4gD4vbwQxXXZ+WHmW6E9ixmNrwvs0iZs= +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 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.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.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.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/go-github/v27 v27.0.6/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.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/mako v0.0.0-20190821191249-122f8dcef9e3/go.mod h1:YzLcVlL+NqWnmUEPuhS1LxDDwGO9WNbVlEXaF4IH35g= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/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-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 h1:n6vlPhxsA+BW/XsS5+uqi7GyzaLa5MH7qlSLBZtRdiA= +github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/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/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +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 v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +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/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +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.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +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/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a/go.mod h1:9GkyshztGufsdPQWjH+ifgnIr3xNUL5syI70g2dzU1o= +github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= +github.com/influxdata/tdigest v0.0.0-20191024211133-5d87a7585faa/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +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.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +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/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/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +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.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +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.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +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/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +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.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac/go.mod h1:Frd2bnT3w5FB5q49ENTfVlztJES+1k/7lyWX2+9gq/M= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +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.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +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/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/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/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.17/go.mod h1:WgzbA6oji13JREwiNsRDNfl7jYdPnmz+VEuLrA+/48M= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +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/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= +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/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +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/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +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/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.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.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +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.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +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.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ= +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.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +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-20230522130544-0eef84f63102 h1:DvXc9rkFXM8Q4Gva6MYoenwnvgX1Ij1cLkewLb91D5Q= +github.com/openshift/api v0.0.0-20230522130544-0eef84f63102/go.mod h1:4VWG+W22wrB4HfBL88P40DxLEpSOaiBVxUnfalfJo9k= +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/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pb33f/libopenapi v0.8.4 h1:hP6etldkapogvEfILaCVrBNh9DwzK/ZKGrNPm3qAIwU= +github.com/pb33f/libopenapi v0.8.4/go.mod h1:lvUmCtjgHUGVj6WzN3I5/CS9wkXtyN3Ykjh6ZZP5lrI= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml/v2 v2.0.0-beta.2/go.mod h1:+X+aW6gUj6Hda43TeYHVCIvYNG/jqY/8ZFXAeXXHl+Q= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +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/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +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 v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +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.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +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.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +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.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +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.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +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.2.0/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.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= +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/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/relvacode/iso8601 v1.3.0 h1:HguUjsGpIMh/zsTczGN3DVJFxTU/GX+MMmzcKoMO7ko= +github.com/relvacode/iso8601 v1.3.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 v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +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.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +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/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 h1:Dz0HrI1AtNSGCE8LXLLqoZU4iuOJXPWndenCsZfstA8= +github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46/go.mod h1:is8FVkzSi7PYLWEXT5MgWhglFsyyiW8ffxAoJqfuFZo= +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.2.5 h1:/TFqBBni0hDpTA0bKadGTWbyBRiQ0o2ppz2ScY6DdTM= +github.com/serverlessworkflow/sdk-go/v2 v2.2.5/go.mod h1:uIy7EgNRGUzuTsihdto7fN+xsz/HDHq0MP1aPIG7wHU= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +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/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +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/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518/go.mod h1:CKI4AZ4XmGV240rTHfO0hfE83S6/a3/Q1siZJ/vXf7A= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU= +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.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +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/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/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.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tsenart/go-tsz v0.0.0-20180814232043-cdeb9e1e981e/go.mod h1:SWZznP1z5Ki7hDT2ioqiFKEse8K9tU2OUvaRI0NeGQo= +github.com/tsenart/vegeta/v12 v12.8.4/go.mod h1:ZiJtwLn/9M4fTPdMY7bdbIeyNeFVE8/AHbWFqCsUuho= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +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/wavesoftware/go-ensure v1.0.0/go.mod h1:K2UAFSwMTvpiRGay/M3aEYYuurcR8S4A6HkQlJPV8k4= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/otel v0.16.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +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.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +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-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/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-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/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.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +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/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/lint v0.0.0-20201208152925-83fdc39ff7b5/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.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +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-20181023162649-9b4f9f5ad519/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/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-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-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-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/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.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +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-20210220032951-036812b2e83c/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.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +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-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/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-20181205085412-a5c9d58dba9a/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-20190616124812-15dcb6c0061f/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-20190826190057-c7b8b68b1456/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-20191026070338-33540a1f6037/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-20200519105757-fe76b779f299/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-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/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-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-20210806184541-e5e7981a1069/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.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +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.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-20190328211700-ab21143f2384/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-20190614205625-5aca471b1d59/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-20190624222133-a101b041ded4/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-20190907020128-2ca718005c18/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-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/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-20200505023115-26f46d2f7ef8/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-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +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.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +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.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.147.0 h1:Can3FaQo9LlVqxJCodNmeZW/ib3/qKAY3rFeXiHo5gc= +google.golang.org/api v0.147.0/go.mod h1:pQ/9j83DcmPd/5C9e2nFOdjjNkDZ1G+zkbK2uvdkJMs= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +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 v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210416161957-9910b6c460de/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c h1:jHkCUWkseRf+W+edG5hMzr/Uh1xkDREY4caybAq4dpY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +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.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +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-20200227125254-8fa46927fb4f/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +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/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +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.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +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.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +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.21.4/go.mod h1:fTVGP+M4D8+00FN2cMnJqk/eb/GH53bvmNs2SVTmpFk= +k8s.io/api v0.27.6 h1:PBWu/lywJe2qQcshMjubzcBg7+XDZOo7O8JJAWuYtUo= +k8s.io/api v0.27.6/go.mod h1:AQYj0UsFCp3qJE7bOVnUuy4orCsXVkvHefnbYQiNWgk= +k8s.io/apiextensions-apiserver v0.21.4/go.mod h1:OoC8LhI9LnV+wKjZkXIBbLUwtnOGJiTRE33qctH5CIk= +k8s.io/apiextensions-apiserver v0.27.6 h1:mOwSBJtThZhpJr+8gEkc3wFDIjq87E3JspR5mtZxIg8= +k8s.io/apiextensions-apiserver v0.27.6/go.mod h1:AVNlLYRrESG5Poo6ASRUhY2pvoKPcNt8y/IuZ4lx3o8= +k8s.io/apimachinery v0.19.7/go.mod h1:6sRbGRAVY5DOCuZwB5XkqguBqpqLU6q/kOaOdk29z6Q= +k8s.io/apimachinery v0.21.4/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI= +k8s.io/apimachinery v0.27.6 h1:mGU8jmBq5o8mWBov+mLjdTBcU+etTE19waies4AQ6NE= +k8s.io/apimachinery v0.27.6/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= +k8s.io/apiserver v0.21.4/go.mod h1:SErUuFBBPZUcD2nsUU8hItxoYheqyYr2o/pCINEPW8g= +k8s.io/client-go v0.21.4/go.mod h1:t0/eMKyUAq/DoQ7vW8NVVA00/nomlwC+eInsS8PxSew= +k8s.io/client-go v0.27.6 h1:vzI8804gpUtpMCNaFjIFyJrifH7u//LJCJPy8fQuYQg= +k8s.io/client-go v0.27.6/go.mod h1:PMsXcDKiJTW7PHJ64oEsIUJF319wm+EFlCj76oE5QXM= +k8s.io/code-generator v0.21.4/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo= +k8s.io/component-base v0.21.4/go.mod h1:ZKG0eHVX+tUDcaoIGpU3Vtk4TIjMddN9uhEWDmW6Nyg= +k8s.io/component-base v0.27.6 h1:hF5WxX7Tpi9/dXAbLjPVkIA6CA6Pi6r9JOHyo0uCDYI= +k8s.io/component-base v0.27.6/go.mod h1:NvjLtaneUeb0GgMPpCBF+4LNB9GuhDHi16uUTjBhQfU= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20210203185629-de9496dff47b/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= +k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= +k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 h1:OmK1d0WrkD3IPfkskvroRykOulHVHf0s0ZIFRjyt+UI= +k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515/go.mod h1:kzo02I3kQ4BTtEfVLaPbjvCkX97YqGve33wzlb3fofQ= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc= +k8s.io/utils v0.0.0-20230711102312-30195339c3c7/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +knative.dev/eventing v0.26.0 h1:osDUdav7S0FuChN0onfwL5cEcsdb54Kee2hjAPMpY7o= +knative.dev/eventing v0.26.0/go.mod h1:6tTam0lsPtBSJHJ63/195obj2VAHlTZZB7TLiBSeqk0= +knative.dev/hack v0.0.0-20210806075220-815cd312d65c/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= +knative.dev/hack/schema v0.0.0-20210806075220-815cd312d65c/go.mod h1:ffjwmdcrH5vN3mPhO8RrF2KfNnbHeCE2C60A+2cv3U0= +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-20210914164111-4857ab6939e3/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8= +knative.dev/pkg v0.0.0-20210919202233-5ae482141474/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8= +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/reconciler-test v0.0.0-20210915181908-49fac7555086/go.mod h1:6yDmb26SINSmgw6wVy9qQwgRMewiW8ddkkwGLR0ZvOY= +knative.dev/serving v0.39.0 h1:NVt8WthHmFFMWZ3qpBblXt47del8qqrbCegqwGBVSwk= +knative.dev/serving v0.39.0/go.mod h1:0QIp5mvgWa1oUC2MxMf+Q/JWgG8JhAsSdJKc6iTRlvE= +pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= +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/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= +sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +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.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= +sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/packages/kogito-serverless-operator/go.work b/packages/kogito-serverless-operator/go.work new file mode 100644 index 00000000000..94cf592e1d3 --- /dev/null +++ b/packages/kogito-serverless-operator/go.work @@ -0,0 +1,29 @@ +go 1.21 + +use ( + . + ./api + ./bddframework + ./container-builder + ./testbdd + ./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.2.5 + golang.org/x/crypto => golang.org/x/crypto v0.17.0 + // CVE-2023-40167 fix until third-party libs upgrade their side + golang.org/x/net => golang.org/x/net v0.17.0 + k8s.io/api => k8s.io/api v0.27.6 + k8s.io/apimachinery => k8s.io/apimachinery v0.27.6 + k8s.io/client-go => k8s.io/client-go v0.27.6 + k8s.io/klog/v2 => k8s.io/klog/v2 v2.100.1 + knative.dev/pkg => knative.dev/pkg v0.0.0-20230525143525-9bda38b21643 + sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.15.0 + sigs.k8s.io/yaml => sigs.k8s.io/yaml v1.3.0 +) diff --git a/packages/kogito-serverless-operator/go.work.sum b/packages/kogito-serverless-operator/go.work.sum new file mode 100644 index 00000000000..378d3f74099 --- /dev/null +++ b/packages/kogito-serverless-operator/go.work.sum @@ -0,0 +1,1894 @@ +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= +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.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +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/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/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/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/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/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/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/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/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.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/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/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/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/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/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/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/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/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/bigquery v1.8.0 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA= +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/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/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/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/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/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/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/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/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.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= +cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= +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/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.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +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/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/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/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/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/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/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/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/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/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/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/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ= +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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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.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/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/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/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/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/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/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU= +cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w= +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/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/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= +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/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/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/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/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/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/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/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/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/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/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/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/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.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/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.6.0 h1:rXyq+0+RSIm3HFypctp7WoXxIA563rn206CfMWdqXX4= +cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= +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/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= +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/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/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.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/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/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/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/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/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/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/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/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/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= +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/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/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/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/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/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/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= +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= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY= +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-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +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/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/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/k8s-cloud-provider v0.0.0-20200415212048-7901bc822317/go.mod h1:DF8FZRxMHMGv/vP2lQP6h+dYzzjpuRn24VeRiYn3qjQ= +github.com/IBM/sarama v1.40.1 h1:lL01NNg/iBeigUbT+wpPysuTYW6roHo6kc1QrffRf0k= +github.com/IBM/sarama v1.40.1/go.mod h1:+5OFwA5Du9I6QrznhaMHsuwWdWZNMjaBSIxEWEgKOYE= +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/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +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/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.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/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/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 v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves= +github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= +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.0/go.mod h1:d+tV/eHZZ7Dz7RPrFKtPK02tpr+c9/PEd/zm8mDS9Vg= +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-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/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/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/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/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/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/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/sdk-go/observability/opencensus/v2 v2.4.1 h1:UHjY9+DJyjELyFA8vU/KHHXix1F1z7QLFskzdJZkP+0= +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-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-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +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-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= +github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= +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/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-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +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/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/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/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/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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +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.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.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= +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.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.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= +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/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/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= +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/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/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7 h1:LofdAjjjqCSXMwLGgOgnE+rdPuvX9DxCqaHwKy7i/ko= +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/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is= +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-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-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-lintpack/lintpack v0.5.2 h1:DI5mA3+eKdWeJ40nU4d6Wc26qmdG8RCi/btYq0TuRN0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +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.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-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-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/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/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/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8= +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/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-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/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/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/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +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-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +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/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= +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/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= +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/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/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.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +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/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= +github.com/gophercloud/gophercloud v1.5.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= +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/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.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/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/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= +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/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +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/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.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-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +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/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.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-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1 h1:sNCoNyDEvN1xa+X0baata4RdcpKwcMS6DH+xwfqPgjw= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +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/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= +github.com/iancoleman/strcase v0.2.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/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +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/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/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/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/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/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= +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/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.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/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +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/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= +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/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/lyft/protoc-gen-star/v2 v2.0.3/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/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +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.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/goveralls v0.0.2 h1:7eJB6EqsPhRVxvwEXGnqdO2sJI0PTsrWoTMXEk9/OQc= +github.com/matttproud/golang_protobuf_extensions v1.0.2/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.1.17 h1:BhJxdA7bH51vKFZSY8Sn9pR7++LREvg0eYFzHA452ew= +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/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= +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/mapstructure v1.5.0/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/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +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/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +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/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.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +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.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +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/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/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-registry v1.6.1 h1:Ow0Ko9DRIZ4xvH55vFAslcTy6A9FhlIeXvm+FhyRd84= +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/v2 v2.0.0-beta.2 h1:f/g66OWmYXmVnYL3UAhqpM9YuWKFR2vjYfFNSDQcHPQ= +github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= +github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= +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.17/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/profile v1.2.1 h1:F++O52m40owAmADcojzM+9gyjmMOY/T4oYJkgFDH8RE= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= +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/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.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +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.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +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/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc= +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/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= +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/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.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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +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/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/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/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +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/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= +github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM= +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/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/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/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/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/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/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/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +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/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/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.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/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/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/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/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/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/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/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.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/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/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/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/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/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/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/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/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/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= +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/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +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/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= +golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= +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.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.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +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-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +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/sync v0.0.0-20220722155255-886fb9371eb4/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/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-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-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-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-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-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-20220422013727-9388b58f7150/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-20220722155257-8c9f86f7a55f/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.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/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +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.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +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/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +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.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.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.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.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= +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/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= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw= +gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e h1:jRyg0XfpwWlhEV8mDfdNGBeSJM2fuyh9Yjrnd8kF2Ts= +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.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= +google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750= +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-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-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-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +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-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-20230920204549-e6e6cdab5c13/go.mod h1:CCviP9RmpZ1mxVr8MUjCnSiY09IbAXZxhLE6EhHIdPU= +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-20230920204549-e6e6cdab5c13/go.mod h1:RdyHbowztCGQySiCvQPgWQWgWhGnouTdCflKoDBt32U= +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/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-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +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/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.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.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.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +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.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +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.29.1/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.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +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.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +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/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +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= +k8s.io/apiextensions-apiserver v0.26.5/go.mod h1:Olsde7ZNWnyz9rsL13iXYXmL1h7kWujtKeC3yWVCDPo= +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/cli-runtime v0.17.3 h1:0ZlDdJgJBKsu77trRUynNiWsRuAvAVPBNaQfnt/1qtc= +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/component-base v0.26.5/go.mod h1:wvfNAS05EtKdPeUxFceo8WNh8bGPcFY8QfPhv5MYjA4= +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/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= +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/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-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20230313181309-38a27ef9d749/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/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= +modernc.org/cc v1.0.0 h1:nPibNuDEx6tvYrUAtvDTTw98rx5juGsa5zuDnKwEEQQ= +modernc.org/golex v1.0.0 h1:wWpDlbK8ejRfSyi0frMyhilD3JBvtcx2AdGDnU+JtsE= +modernc.org/mathutil v1.0.0 h1:93vKjrJopTPrtTNpZ8XIovER7iCIH1QU7wNbOQXC60I= +modernc.org/strutil v1.0.0 h1:XVFtQwFVwc02Wk+0L/Z/zDDXO81r5Lhe6iMKmGX3KhE= +modernc.org/xc v1.0.0 h1:7ccXrupWZIS3twbUGrtKmHS2DXY6xegFua+6O3xgAFU= +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/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= +rsc.io/letsencrypt v0.0.3 h1:H7xDfhkaFFSYEJlKeq38RwX2jYcnTeHuDQyT+mMNMwM= +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/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= +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/packages/kogito-serverless-operator/hack/addheaders.sh b/packages/kogito-serverless-operator/hack/addheaders.sh new file mode 100755 index 00000000000..f5c5afee6e0 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/addheaders.sh @@ -0,0 +1,24 @@ +#!/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. + +if ! hash addlicense 2>/dev/null; then + go install github.com/google/addlicense@latest +fi + +# shellcheck disable=SC2035 +addlicense -c "Apache Software Foundation (ASF)" -l=apache -ignore=test/samples/*.yaml -ignore=container-builder/examples/**/*.yaml hack api bddframework controllers utils test testbdd container-builder workflowproj diff --git a/packages/kogito-serverless-operator/hack/boilerplate.go.txt b/packages/kogito-serverless-operator/hack/boilerplate.go.txt new file mode 100644 index 00000000000..99ad906f25d --- /dev/null +++ b/packages/kogito-serverless-operator/hack/boilerplate.go.txt @@ -0,0 +1,14 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/hack/bump-version.sh b/packages/kogito-serverless-operator/hack/bump-version.sh new file mode 100755 index 00000000000..5f59c10ef99 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/bump-version.sh @@ -0,0 +1,69 @@ +#!/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 + +script_dir_path=$(dirname "${BASH_SOURCE[0]}") +source "${script_dir_path}"/env.sh + +imageTag='quay.io/kiegroup/kogito-serverless-operator' +# shellcheck disable=SC2034 +old_version=$(getOperatorVersion) +latest_version=$(getOperatorLatestVersion) +new_version=$1 + +if [ -z "${new_version}" ]; then + echo "Please inform the new version" + exit 1 +fi + +imageSuffix=$(if [[ "${new_version}" == 0.0.0 ]]; then echo '-nightly'; else echo ''; fi) + +oldMajorMinorVersion=${old_version%.*} +newMajorMinorVersion=${new_version%.*} +if [ "${old_version}" = "${latest_version}" ]; then + oldMajorMinorVersion='latest' +fi +if [ "${new_version}" = "${latest_version}" ]; then + newMajorMinorVersion='latest' +fi + +echo "Set new version to ${new_version} (img_suffix = '${imageSuffix}', majorMinor = ${newMajorMinorVersion})" + + +node -p "require('replace-in-file').sync({ from: /\bVERSION\ \?=.*\b/g, to: 'VERSION ?= ${new_version}', files: ['./Makefile'] });" +node -p "require('replace-in-file').sync({ from: /\bREDUCED_VERSION\ \?=.*\b/g, to: 'REDUCED_VERSION ?= ${newMajorMinorVersion}', files: ['./Makefile'] });" +node -p "require('replace-in-file').sync({ from: /\bIMAGE_TAG_BASE\ \?=.*\b/g, to: 'IMAGE_TAG_BASE ?= ${imageTag}${imageSuffix}', files: ['./Makefile'] });" + +node -p "require('replace-in-file').sync({ from: /\bnewTag:.*\b/g, to: 'newTag: ${new_version}', files: ['./config/manager/kustomization.yaml'] });" +node -p "require('replace-in-file').sync({ from: /\bnewName:.*\b/g, to: 'newName: ${imageTag}${imageSuffix}', files: ['./config/manager/kustomization.yaml'] });" + +node -p "require('replace-in-file').sync({ from: /\bversion: .*\b/g, to: 'version: ${new_version}', files: ['./images/bundle.yaml'] });" +node -p "require('replace-in-file').sync({ from: /\bversion: .*\b/g, to: 'version: ${new_version}', files: ['./images/manager.yaml'] });" + +# Update kogito-swf-* images +node -p "require('replace-in-file').sync({ from: 'quay.io/kiegroup/kogito-swf-builder${imageSuffix}:${oldMajorMinorVersion}', to: 'quay.io/kiegroup/kogito-swf-builder${imageSuffix}:${newMajorMinorVersion}', files: ['**/*.yaml', '**/*.containerfile', '**/*.dockerfile', '**/*.Dockerfile', '**/*.go'] });" +node -p "require('replace-in-file').sync({ from: 'quay.io/kiegroup/kogito-swf-devmode${imageSuffix}:${oldMajorMinorVersion}', to: 'quay.io/kiegroup/kogito-swf-devmode${imageSuffix}:${newMajorMinorVersion}', files: ['**/*.yaml', '**/*.containerfile', '**/*.dockerfile', '**/*.Dockerfile', '**/*.go'] });" +node -p "require('replace-in-file').sync({ from: 'quay.io/kiegroup/kogito-serverless-operator${imageSuffix}:${oldMajorMinorVersion}', to: 'quay.io/kiegroup/kogito-serverless-operator${imageSuffix}:${newMajorMinorVersion}', files: ['**/*.yaml'] });" + +node -p "require('replace-in-file').sync({ from: /\bOperatorVersion = .*/g, to: 'OperatorVersion = \"${new_version}\"', files: ['version/version.go'] });" +node -p "require('replace-in-file').sync({ from: /\bcontainerImage:.*\b/g, to: 'containerImage: ${imageTag}${imageSuffix}:${newMajorMinorVersion}', files: ['$(getCsvFile)'] });" + +make generate-all +make vet + +echo "Version bumped to ${new_version}" diff --git a/packages/kogito-serverless-operator/hack/ci/create-kind-cluster-with-registry.sh b/packages/kogito-serverless-operator/hack/ci/create-kind-cluster-with-registry.sh new file mode 100755 index 00000000000..2feb2c2540c --- /dev/null +++ b/packages/kogito-serverless-operator/hack/ci/create-kind-cluster-with-registry.sh @@ -0,0 +1,93 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/bin/sh + +set -o errexit + +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 < Minikube version to install is ${MINIKUBE_VERSION}" + +# 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)}') + +if [ -e "${download_path}/minikube-${os}-${arch}" ]; then + echo "---> Minikube ${MINIKUBE_VERSION} (OS ${os} Architecture ${arch}) already exists in '${download_path}', skipping downloading" +else + mkdir -p "${download_path}" + cd "${download_path}" + echo "---> Downloading minikube ${MINIKUBE_VERSION} (OS ${os} Architecture ${arch}) to ${download_path}" + curl -LO "https://storage.googleapis.com/minikube/releases/${MINIKUBE_VERSION}/minikube-${os}-${arch}" + cd - +fi + +if [ -z "${install_path}" ]; then + install_path="${HOME}/runner/bin" + [[ "${os}" == "darwin" ]]; install_path="${HOME}/runner/bin" +fi + +echo "---> Ensuring minikube installation at ${install_path}" + +mkdir -p "${install_path}" +chmod +x "${install_path}" +cp "${download_path}/minikube-${os}-${arch}" "${install_path}/minikube" diff --git a/packages/kogito-serverless-operator/hack/ci/install-operator-sdk.sh b/packages/kogito-serverless-operator/hack/ci/install-operator-sdk.sh new file mode 100755 index 00000000000..047fa1d4ab3 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/ci/install-operator-sdk.sh @@ -0,0 +1,62 @@ +#!/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.25.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 + curl -L https://github.com/operator-framework/operator-sdk/releases/download/"${OPERATOR_SDK_VERSION}"/operator-sdk_"${os}"_"${arch}" -o "$GOPATH"/bin/operator-sdk + chmod +x "$GOPATH"/bin/operator-sdk +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/packages/kogito-serverless-operator/hack/clean-cluster-operators.sh b/packages/kogito-serverless-operator/hack/clean-cluster-operators.sh new file mode 100755 index 00000000000..cd71bbb2775 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/clean-cluster-operators.sh @@ -0,0 +1,32 @@ +#!/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. + +script_dir_path=`dirname "${BASH_SOURCE[0]}"` +source ${script_dir_path}/env.sh + +function clean_installed_operators() { + echo "--- Clean installplans in $1" + get_and_clean_resources $1 'installplans.operators.coreos.com' + echo "--- Clean subscriptions in $1" + get_and_clean_resources $1 'subscriptions.operators.coreos.com' + echo "--- Clean clusterserviceversions in $1" + get_and_clean_resources $1 'clusterserviceversions.operators.coreos.com' +} + +clean_installed_operators 'openshift-operators' +clean_installed_operators 'operators' diff --git a/packages/kogito-serverless-operator/hack/clean-crds.sh b/packages/kogito-serverless-operator/hack/clean-crds.sh new file mode 100755 index 00000000000..ffb26803265 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/clean-crds.sh @@ -0,0 +1,22 @@ +#!/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. + +script_dir_path=`dirname "${BASH_SOURCE[0]}"` +source ${script_dir_path}/env.sh + +clean_cluster_resources 'crds' "$(getAllDependentCrds)" \ No newline at end of file diff --git a/packages/kogito-serverless-operator/hack/clean-stuck-namespaces.sh b/packages/kogito-serverless-operator/hack/clean-stuck-namespaces.sh new file mode 100755 index 00000000000..00165d667b8 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/clean-stuck-namespaces.sh @@ -0,0 +1,47 @@ +#!/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. + +script_dir_path=`dirname "${BASH_SOURCE[0]}"` +source ${script_dir_path}/env.sh + +DIR=$(mktemp -d) + +oc get namespaces | grep "Terminating" | awk -F " " '{print $1}' > ${DIR}/projects + +while read project +do + echo "Stuck project ${project}" + + for resource in $(getAllDependentCrds all) + do + oc get $resource -n "${project}" | grep -v "NAME" | awk -F " " '{print $1}' > ${DIR}/$resource-instances + while read instance + do + echo "Remove finalizer from $resource ${instance} from project ${project}" + + oc patch $resource ${instance} -n ${project} -p '{"metadata":{"finalizers":[]}}' --type=merge + done < ${DIR}/$resource-instances + rm ${DIR}/$resource-instances + done +done < ${DIR}/projects + +echo "Projects deleted:" +cat ${DIR}/projects + +# Cleanup +rm ${DIR}/projects \ No newline at end of file diff --git a/packages/kogito-serverless-operator/hack/env.sh b/packages/kogito-serverless-operator/hack/env.sh new file mode 100755 index 00000000000..945175db22f --- /dev/null +++ b/packages/kogito-serverless-operator/hack/env.sh @@ -0,0 +1,99 @@ +#!/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. + +CSV_DIR="config/manifests/bases" +BUNDLE_DIR="bundle/manifests" + +getOperatorVersion() { + local version=$(grep -m 1 'OperatorVersion' version/version.go | awk -F\" '{print $2}') + echo "${version}" +} + +getOperatorLatestVersion() { + local version=$(grep -m 1 'latestVersion' version/version.go | awk -F\" '{print $2}') + echo "${version}" +} + +getOperatorImageName() { + local image_name=$(grep -m 1 'IMAGE_TAG_BASE ?=' Makefile | awk -F= '{print $2}' | tr -d ' ') + echo "${image_name}" +} + +getCsvFile() { + echo "${CSV_DIR}/sonataflow-operator.clusterserviceversion.yaml" +} + +getBundleCsvFile() { + echo "${BUNDLE_DIR}/sonataflow-operator.clusterserviceversion.yaml" +} + +DEPENDENT_CRDS_KEYS=(grafana hyperfoil infinispan kafka keycloak mongodb) # This list may need a revision +DEPENDENT_SENSITIVE_CRDS_KEYS=(prometheus) + +getAllDependentCrds() { + for crdKey in ${DEPENDENT_CRDS_KEYS[*]} + do + for crd in $(getDependentCrds ${crdKey}) + do + echo "$crd" + done + done + + if [ "$1" = "all" ] + then + for crdKey in ${DEPENDENT_SENSITIVE_CRDS_KEYS[*]} + do + for crd in $(getDependentCrds ${crdKey}) + do + echo "$crd" + done + done + fi +} + +getDependentCrds() { + oc get crds | grep $1 | awk -F' ' '{print $1}' +} + +# get_and_clean_cluster_resources namespace resourceName +get_and_clean_resources() { + clean_resources $1 $2 "$(oc get $2 -n $1 | grep -v NAME | awk '{print $1}')" +} + +# clean_cluster_resources namespace resourceName {list of resources} +clean_resources() { + for resourceName in $3 + do + echo "Delete $2 ${resourceName} in namespace $1" + oc delete $2 ${resourceName} -n $1 + done +} + +# get_and_clean_cluster_resources resourceName +get_and_clean_cluster_resources() { + clean_cluster_resources $1 "$(oc get $1 | grep -v NAME | awk '{print $1}')" +} + +# clean_cluster_resources resourceName {list of resources} +clean_cluster_resources() { + for resourceName in $2 + do + echo "Delete cluster $1 ${resourceName}" + oc delete $1 ${resourceName} --timeout=30s + done +} \ No newline at end of file diff --git a/packages/kogito-serverless-operator/hack/get-images-sha.sh b/packages/kogito-serverless-operator/hack/get-images-sha.sh new file mode 100755 index 00000000000..c2240b7a07f --- /dev/null +++ b/packages/kogito-serverless-operator/hack/get-images-sha.sh @@ -0,0 +1,52 @@ +#!/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. + +# +# This script fetches the sha256 of images built on Brew and tagged into a specific Brew tag. +# As an input it requires the OpenShift Serverless Logic produt version. +# +# Example to run: +# $ ./get-images-sha.sh 1.29 +# +# Note: brewkoji package is required. +# + +imagesBrewPackageName=("openshift-serverless-1-logic-rhel8-operator-container") + +if ! command -v brew > /dev/null; +then + echo "brew command not available in the system, please install brewkoji package" + exit 1 +fi + +if [ $# -eq 0 ]; +then + echo "$0: Missing the OpenShift Serverless Logic version input" + exit 1 +fi + +oslVersion=$1 +brewTag="openshift-serverless-${oslVersion}-rhel-8-container-candidate" +for brewPackageName in ${imagesBrewPackageName[@]}; do + echo "Finding latest Brew build for package ${brewPackageName}" + brewBuild=$(brew latest-build ${brewTag} ${brewPackageName} | tail -n1 | cut -d ' ' -f1) + echo "Found Brew build: ${brewBuild}" + imageSha=$(brew buildinfo "${brewBuild}" | awk -F'Extra: ' '{print $2}' | tr \' \" | sed 's|False|\"false\"|g' | sed 's|True|\"true\"|g' | sed 's|None|\"\"|g' | jq -r '.image.index.pull[0]'| cut -d "@" -f2) + echo "Image sha: ${imageSha}" + echo "---" +done diff --git a/packages/kogito-serverless-operator/hack/go-path.sh b/packages/kogito-serverless-operator/hack/go-path.sh new file mode 100755 index 00000000000..56066af80a0 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/go-path.sh @@ -0,0 +1,22 @@ +#!/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. + +# enforce GOROOT +# shellcheck disable=SC2155 +export GOROOT=$(go env GOROOT) +export GOPATH=$(go env GOPATH) \ No newline at end of file diff --git a/packages/kogito-serverless-operator/hack/goimports.sh b/packages/kogito-serverless-operator/hack/goimports.sh new file mode 100755 index 00000000000..8a6dc63e03b --- /dev/null +++ b/packages/kogito-serverless-operator/hack/goimports.sh @@ -0,0 +1,22 @@ +#!/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. + +source ./hack/go-path.sh + +command -v goimports >/dev/null || go install golang.org/x/tools/cmd/goimports@latest +goimports -local github.com/kiegroup -l -w . \ No newline at end of file diff --git a/packages/kogito-serverless-operator/hack/kube-utils.sh b/packages/kogito-serverless-operator/hack/kube-utils.sh new file mode 100755 index 00000000000..32fbf005ca5 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/kube-utils.sh @@ -0,0 +1,37 @@ +#!/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. + +getKubeSystemPodStatusConditions() { + kubectl get pods $1 -n kube-system -o json | jq '.items[].status.conditions[]' +} + +getKubeSystemPodReadyStatus() { + echo $(kubectl get pods $1 -n kube-system -o json | jq -r '.items[].status.conditions[] | select(.type == "Ready") | .status') +} + +waitKubeSystemForPodReady() { + local selector=${1} + local timeout_time=${2:-60s} + + export -f getKubeSystemPodStatusConditions + export -f getKubeSystemPodReadyStatus + + echo "Wait for Kube System pod with selector '${selector}' and timeout ${timeout_time}" + + timeout ${timeout_time} bash -c "getKubeSystemPodStatusConditions '${selector}' && while [[ \"$(getKubeSystemPodReadyStatus "${selector}")\" != "True" ]] ; do sleep 2 && getKubeSystemPodStatusConditions '${selector}'; done" +} \ No newline at end of file diff --git a/packages/kogito-serverless-operator/hack/local/build-simple-workflow.sh b/packages/kogito-serverless-operator/hack/local/build-simple-workflow.sh new file mode 100755 index 00000000000..c0886e45386 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/local/build-simple-workflow.sh @@ -0,0 +1,20 @@ +# Copyright 2023 Red Hat, Inc. and/or its affiliates +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +rm -rf /tmp/simpleworkflow +mkdir -p /tmp/simpleworkflow +cp ./config/manager/sonataflow_builder_dockerfile.yaml /tmp/simpleworkflow/Dockerfile +cp ./workflowproj/testdata/workflows/workflow-minimal.sw.json /tmp/simpleworkflow/workflow-minimal.sw.json + +docker build -t quay.io/kiegroup/sonataflow-minimal-example:latest /tmp/simpleworkflow/ diff --git a/packages/kogito-serverless-operator/hack/local/greeting_example_deploy.sh b/packages/kogito-serverless-operator/hack/local/greeting_example_deploy.sh new file mode 100755 index 00000000000..950217f1411 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/local/greeting_example_deploy.sh @@ -0,0 +1,44 @@ +#!/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. + + +registry=$1 + +if [ -z "${registry}" ]; then + registry="quay.io/${USERNAME}" + echo "No registry given. Setting up default." +fi + +img=${registry}/kogito-serverless-operator:local-test + +echo "Using registry '${registry}'" +echo "Using image '${img}'" + +kubectl create namespace sonataflow +kubectl create secret generic regcred --from-file=.dockerconfigjson=${HOME}/.docker/config.json --type=kubernetes.io/dockerconfigjson -n sonataflow + +# make sure cekit is installed: https://docs.cekit.io/en/latest/handbook/installation/instructions.html +make container-build BUILDER=docker IMG="${img}" +make deploy IMG="${img}" + +# shellcheck disable=SC2002 +cat config/samples/sonataflow.org_v1alpha08_sonataflowplatform.yaml | sed "s|address: .*|address: ${registry}|g" | kubectl apply -n sonataflow -f - + +sleep 10 + +kubectl apply -f config/samples/sonataflow.org_v1alpha08_sonataflowplatform.yaml -n sonataflow diff --git a/packages/kogito-serverless-operator/hack/local/greeting_example_remove.sh b/packages/kogito-serverless-operator/hack/local/greeting_example_remove.sh new file mode 100755 index 00000000000..449bb463e27 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/local/greeting_example_remove.sh @@ -0,0 +1,29 @@ +#!/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. + + +remove_operator=${1} + +kubectl delete -f config/samples/sonataflow.org_v1alpha08_sonataflow.yaml -n sonataflow + +if [ "${remove_operator}" = '-A' ] || [ "${remove_operator}" = '--all' ]; then + echo 'Removing the operator from the cluster' + + kubectl delete namespace sonataflow + make undeploy +fi \ No newline at end of file diff --git a/packages/kogito-serverless-operator/hack/local/run-e2e-crc.sh b/packages/kogito-serverless-operator/hack/local/run-e2e-crc.sh new file mode 100755 index 00000000000..c21a6faef3f --- /dev/null +++ b/packages/kogito-serverless-operator/hack/local/run-e2e-crc.sh @@ -0,0 +1,31 @@ +#!/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}"/kogito-serverless-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/packages/kogito-serverless-operator/hack/local/run-e2e.sh b/packages/kogito-serverless-operator/hack/local/run-e2e.sh new file mode 100755 index 00000000000..334190f9373 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/local/run-e2e.sh @@ -0,0 +1,37 @@ +#!/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} +echo "Using minikube profile ${MINIKUBE_PROFILE}" +export OPERATOR_IMAGE_NAME=localhost/kogito-serverless-operator:0.0.1 + +# clean up previous runs +kubectl get namespaces -o name | awk -F/ '/^namespace\/test/ {print $2}' | xargs kubectl delete namespace +make undeploy ignore-not-found=true +make deploy IMG="${OPERATOR_IMAGE_NAME}" + +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 + +make deploy IMG="${OPERATOR_IMAGE_NAME}" +make test-e2e diff --git a/packages/kogito-serverless-operator/hack/local/run-operator.sh b/packages/kogito-serverless-operator/hack/local/run-operator.sh new file mode 100755 index 00000000000..5cb8a73c923 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/local/run-operator.sh @@ -0,0 +1,32 @@ +#!/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 + +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/packages/kogito-serverless-operator/hack/run-tests.sh b/packages/kogito-serverless-operator/hack/run-tests.sh new file mode 100755 index 00000000000..b22b0d72a35 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/run-tests.sh @@ -0,0 +1,411 @@ +#!/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 all BDD tests for the operator +SCRIPT_NAME=`basename $0` +SCRIPT_DIR=`dirname "${BASH_SOURCE[0]}"` + +# tests configuration +BOOLEAN_TEST_PARAMS=(smoke performance cr_deployment_only) +STRING_TEST_PARAMS=(load_factor ci container_engine domain_suffix image_cache_mode http_retry_nb olm_namespace) + +# operator information +BOOLEAN_TEST_PARAMS+=(use_product_operator) +STRING_TEST_PARAMS+=(operator_image_tag operator_installation_source operator_catalog_image) + +# operator profiling +BOOLEAN_TEST_PARAMS+=(operator_profiling_enabled) +STRING_TEST_PARAMS+=(operator_profiling_data_access_yaml_uri operator_profiling_output_file_uri) + +# files/binaries +STRING_TEST_PARAMS+=(operator_yaml_uri cli_path rhpam_operator_yaml_uri) + +# runtime +STRING_TEST_PARAMS+=(services_.+_image_tag services_image_registry services_image_name_suffix services_image_version runtime_application_image_registry runtime_application_image_name_prefix runtime_application_image_name_suffix runtime_application_image_version) + +# build +BOOLEAN_TEST_PARAMS+=(custom_maven_repo_replace_default maven_ignore_self_signed_certificate disable_maven_native_build_container) +STRING_TEST_PARAMS+=(custom_maven_repo_url maven_mirror_url quarkus_platform_maven_mirror_url build_builder_image_tag build_runtime_jvm_image_tag build_runtime_native_image_tag native_builder_image) + +# examples repository +BOOLEAN_TEST_PARAMS+=(examples_ignore_ssl) +STRING_TEST_PARAMS+=(examples_uri examples_ref) + +# Infinispan +STRING_TEST_PARAMS+=(infinispan_installation_source infinispan_storage_class) + +# Hyperfoil +STRING_TEST_PARAMS+=(hyperfoil_output_directory hyperfoil_controller_image_version) + +# dev options +BOOLEAN_TEST_PARAMS+=(show_scenarios show_steps local_execution) +DEV_BOOLEAN_TEST_PARAMS=(local_cluster) +DEV_STRING_TEST_PARAMS=(namespace_name) + +arrayMatchElement() { + local value=$1 + local array=$2 + for pattern in ${array} + do + [[ "${value}" =~ ${pattern} ]] && return 0 + done + return 1 +} + +function usage(){ + printf "Run BDD tests." + printf "\n" + printf "\n${SCRIPT_NAME} [options]*" + printf "\n" + printf "\nOptions:" + printf "\n" + printf "\n-h | --help\n\tPrint the usage of this script." + + # tests configuration + printf "\n--test_main_dir {TEST_MAIN_DIR}\n\tWhere to find the 'main_test.go' file. Defaults to 'testbdd/'." + printf "\n--feature {FEATURE_PATH}\n\tRun a specific feature file." + printf "\n--tags {TAGS}\n\tFilter scenarios by tags." + printf "\n\tExpressions can be:" + printf "\n\t\t- '@wip': run all scenarios with wip tag" + printf "\n\t\t- '~@wip': exclude all scenarios with wip tag" + printf "\n\t\t- '@wip && ~@new': run wip scenarios, but exclude new" + printf "\n\t\t- '@wip,@undone': run wip or undone scenarios" + printf "\n\t Scenarios with '@disabled' tag are always ignored." + printf "\n--concurrent {NUMBER}\n\tSet the number of concurrent tests. Default is 1." + printf "\n--timeout {TIMEOUT_IN_MINUTES}\n\tSet a timeout overall tests run in minutes. Default is 240." + printf "\n--debug\n\tRun in debug mode." + printf "\n--smoke\n\tFilter to run only the tests tagged with '@smoke'." + printf "\n--performance\n\tFilter to run only the tests tagged with '@performance'. If not provided and the tag itself is not specified, these tests will be ignored." + printf "\n--load_factor {INT_VALUE}\n\tSet the tests load factor. Useful for the tests to take into account that the cluster can be overloaded, for example for the calculation of timeouts. Default value is 1." + printf "\n--ci {CI_NAME}\n\tSpecify whether you run test with ci, give also the name of the CI." + printf "\n--cr_deployment_only\n\tUse this option if you have no CLI to test against. It will use only direct CR deployments." + printf "\n--load_default_config\n\tTo be used if you want to directly use the default test config contained into ${SCRIPT_DIR}/../testbdd/.default_config" + printf "\n--format\n\tFormat to use for Godog output, possible values are 'pretty' or 'junit' (default)" + printf "\n--container_engine\n\tTo be used if you want to specify engine to interact with images and containers. Default is docker." + printf "\n--domain_suffix\n\tTo be used if you want to set a domain suffix for exposed services. Ignored when running tests on Openshift." + printf "\n--image_cache_mode\n\tUse this option to specify whether you want to use image cache for runtime images. Available options are 'always', 'never' or 'if-available'(default)." + printf "\n--http_retry_nb {INT_VALUE}\n\tSet the retry number for all HTTP calls in case it fails (and response code != 500). Default value is 3." + printf "\n--olm_namespace \n\tSet the namespace which is used for cluster scope operators. Default is 'openshift-operators'." + + # operator information + printf "\n--operator_image_tag {IMAGE_TAG}\n\tOperator image name." + printf "\n--operator_installation_source {TAG}\n\tDefines installation source for the Kogito operator. Options are 'olm' and 'yaml'. Default is yaml." + printf "\n--operator_catalog_image {TAG}\n\tDefines image containing operator catalog. Needs to be specified only when operator_installation_source is 'olm'." + printf "\n--use_product_operator {TAG}\n\tSet to true to deploy RHPAM Kogito operator, false for using Kogito operator. Default is false." + + # operator profiling + printf "\n--operator_profiling_enabled\n\tEnable the profiling of the operator. If enabled, operator will be automatically deployed with yaml files." + printf "\n--operator_profiling_data_access_yaml_uri {URI}\n\tUrl or Path to kogito-operator-profiling-data-access.yaml file." + printf "\n--operator_profiling_output_file_uri {URI}\n\tUrl or Path where to store the profiling outputs." + + # files/binaries + printf "\n--operator_yaml_uri {URI}\n\tUrl or Path to kogito-operator.yaml file." + printf "\n--cli_path {PATH}\n\tPath to built CLI to test. Default is local built one." + printf "\n--rhpam_operator_yaml_uri {URI}\n\tUrl or Path to kogito-operator.yaml file." + + # runtime + printf "\n--services_{image_type}_{persistence_type}_image_tag {IMAGE_TAG}\n\tSet the services (jobs-service, data-index, ...) image tag.\n\t\timage_type => data-index, explainibility, jobs-service, mgmt-console, task-console, trusty, trusty-ui\n\t\tpersistence_type => ephemeral, infinispan, mongodb, postgresql, redis" + printf "\n--services_image_registry {REGISTRY}\n\tSet the global services image registry." + printf "\n--services_image_name_suffix {NAMESPACE}\n\tSet the global services image name suffix to append to usual image names." + printf "\n--services_image_version {VERSION}\n\tSet the global services image version." + printf "\n--runtime_application_image_registry {REGISTRY}\n\tSet the registry for built runtime applications." + printf "\n--runtime_application_image_name_prefix {NAME_PREFIX}\n\tSet the image name suffix to prepend to usual image names for built runtime applications." + printf "\n--runtime_application_image_name_suffix {NAME_SUFFIX}\n\tSet the image name suffix to append to usual image names for built runtime applications." + printf "\n--runtime_application_image_version {VERSION}\n\tSet the version for built runtime applications." + + # build + printf "\n--custom_maven_repo_url {URI}\n\tSet a custom Maven repository url for S2I builds, in case your artifacts are in a specific repository. See https://github.com/kiegroup/kogito-images/README.md for more information." + printf "\n--custom_maven_repo_replace_default\n\tIf you specified the option 'custom_maven_repo' and you want that one to replace the main Apache repository (useful with snapshots)." + printf "\n--maven_mirror_url {URI}\n\tMaven mirror url to be used when building app in the tests." + printf "\n--quarkus_platform_maven_mirror_url {URI}\n\tMaven mirror url to be used when building app from source files with Quarkus, using the quarkus maven plugin." + printf "\n--maven_ignore_self_signed_certificate\n\tSet to true if maven build need to ignore self-signed certificate. This could happen when using internal maven mirror url." + printf "\n--build_builder_image_tag {IMAGE_TAG}\n\tSet the Builder image full tag." + printf "\n--build_runtime_jvm_image_tag {IMAGE_TAG}\n\tSet the Runtime JVM image full tag." + printf "\n--build_runtime_native_image_tag {IMAGE_TAG}\n\tSet the Runtime Native image full tag." + printf "\n--disable_maven_native_build_container\n\tBy default, Maven native builds are done in container (via container engine). Possibility to disable it." + + # examples repository + printf "\n--examples_uri {URI}\n\tSet the URI for the kogito-examples repository. Default is https://github.com/kiegroup/kogito-examples." + printf "\n--examples_ref {REF}\n\tSet the branch for the kogito-examples repository. Default is none." + printf "\n--examples_ignore_ssl\n\tTell Git to ignore SSL check when checking out examples repository." + + # Infinispan + printf "\n--infinispan_installation_source {TAG}\n\tDefines installation source for the Infinispan operator. Options are 'olm' and 'yaml'. Default is olm." + printf "\n--infinispan_storage_class {TAG}\n\tDefines storage class for Infinispan PVC to be used." + + # Hyperfoil + printf "\n--hyperfoil_output_directory {PATH}\n\tDefines output directory to store Hyperfoil run statistics. Default is test folder." + printf "\n--hyperfoil_controller_image_version {VERSION}\n\ttSet the Hyperfoil controller image version." + + # dev options + printf "\n--show_scenarios\n\tDisplay scenarios which will be executed." + printf "\n--show_steps\n\tDisplay scenarios and their steps which will be executed." + printf "\n--dry_run\n\tExecute a dry run of the tests, disable crds updates and display the scenarios which would be executed." + printf "\n--keep_namespace\n\tDo not delete namespace(s) after scenario run (WARNING: can be resources consuming ...)." + printf "\n--namespace_name\n\tSpecify name of the namespace which will be used for scenario execution (intended for development purposes)." + printf "\n--local_cluster\n\tSpecify whether you run test using a local cluster." + printf "\n--local_execution\n\tSpecify whether you run test in local using either a local or remote cluster." + printf "\n--enable_clean_cluster\n\tSet to true to cleanup the cluster before/after the tests." + printf "\n" +} + +function addParam(){ + if [ ! -z $2 ]; then + if [ "$2" = "true" ]; then + PARAMS="${PARAMS} ${1}" + return 0 + elif [ "$2" = "false" ]; then + return 0 + fi + fi + PARAMS="${PARAMS} ${1}" + return 1 +} + +function addParamKeyValueIfAccepted(){ + key=${1} + value=${2} + if isValueNotOption ${value}; then + if isValueNotEmpty ${value}; then + addParam "${key}=${value}" + fi + return 0 + fi + return 1 +} + +function isValueNotOption(){ + if [[ ! ${1} =~ ^-.* ]]; then + return 0 + fi + return 1 +} + +function isValueNotEmpty(){ + if [[ ! -z "${1}" ]]; then + return 0 + fi; + return 1 +} + +function clean_cluster() { + echo "-------- Clean Cluster operators" + ${SCRIPT_DIR}/clean-cluster-operators.sh + + echo "-------- Clean dependencies CRDs" + ${SCRIPT_DIR}/clean-crds.sh +} + +PARAMS="" +TAGS="" # tags are parsed independently as there could be whitespace to be handled correctly +FEATURE="" +TIMEOUT=240 +DEBUG=false +KEEP_NAMESPACE=false +LOAD_DEFAULT_CONFIG=false +TEST_MAIN_DIR=${SCRIPT_DIR}/../testbdd +ENABLE_CLEAN_CLUSTER=false + +while (( $# )) +do +case $1 in + # tests configuration + --test_main_dir) + shift + if isValueNotOption ${1}; then + if isValueNotEmpty ${1}; then + TEST_MAIN_DIR=${1} + fi + shift + fi + ;; + --feature) + shift + if isValueNotOption ${1}; then + if isValueNotEmpty ${1}; then + FEATURE=${1} + fi + shift + fi + ;; + --tags) + shift + if isValueNotOption ${1}; then + if isValueNotEmpty ${1}; then + TAGS="${1}" + fi + shift + fi + ;; + --concurrent) + shift + if addParamKeyValueIfAccepted "--godog.concurrency" ${1}; then shift; fi + ;; + --timeout) + shift + if isValueNotOption ${1}; then + if isValueNotEmpty ${1}; then + TIMEOUT=${1} + fi + shift + fi + ;; + --debug) + shift + if [ ! -z $1 ]; then + if [ "$1" = "true" ]; then + DEBUG=true + shift + elif [ "$1" = "false" ]; then + shift + fi + else + DEBUG=true + fi + ;; + --load_default_config) + shift + if [ ! -z $1 ]; then + if [ "$1" = "true" ]; then + LOAD_DEFAULT_CONFIG=true + shift + elif [ "$1" = "false" ]; then + shift + fi + else + LOAD_DEFAULT_CONFIG=true + fi + ;; + --format) + shift + if addParamKeyValueIfAccepted "--godog.format" ${1}; then shift; fi + ;; + + # dev options + --dry_run) + shift + if [ ! -z $1 ]; then + if [ "$1" = "true" ]; then + addParam "--tests.show_scenarios" + addParam "--tests.dry_run" + shift + elif [ "$1" = "false" ]; then + shift + fi + else + addParam "--tests.show_scenarios" + addParam "--tests.dry_run" + fi + ;; + --keep_namespace) + shift + if [ ! -z $1 ]; then + if [ "$1" = "true" ]; then + KEEP_NAMESPACE=true + addParam "--tests.keep_namespace" + shift + elif [ "$1" = "false" ]; then + shift + fi + else + KEEP_NAMESPACE=true + addParam "--tests.keep_namespace" + fi + ;; + --enable_clean_cluster) + shift + if [ ! -z $1 ]; then + if [ "$1" = "true" ]; then + ENABLE_CLEAN_CLUSTER=true + shift + elif [ "$1" = "false" ]; then + shift + fi + else + ENABLE_CLEAN_CLUSTER=true + fi + ;; + + # others + -h|--help) + usage + exit 0 + ;; + *) + option=$1 + value=${option#--} + shift + if arrayMatchElement ${value} "${BOOLEAN_TEST_PARAMS[*]}"; then + if addParam "--tests.${value}" ${1}; then shift; fi + elif arrayMatchElement ${value} "${STRING_TEST_PARAMS[*]}"; then + if addParamKeyValueIfAccepted "--tests.${value}" ${1}; then shift; fi + elif arrayMatchElement ${value} "${DEV_BOOLEAN_TEST_PARAMS[*]}"; then + if addParam "--tests.dev.${value}" ${1}; then shift; fi + elif arrayMatchElement ${value} "${DEV_STRING_TEST_PARAMS[*]}"; then + if addParamKeyValueIfAccepted "--tests.dev.${value}" ${1}; then shift; fi + else + echo "Unknown arguments: ${option}" + usage + exit 1 + fi + ;; +esac +done + +# load test default config options if not set already +if [ "${LOAD_DEFAULT_CONFIG}" = "true" ]; then + echo "Load default test config" + cat "${SCRIPT_DIR}/../testbdd/.default_config" + while IFS="=" read -r key value + do + if [[ $PARAMS != *"${key}"* ]]; then + addParam "--${key}=${value}" + fi + done < "${SCRIPT_DIR}/../testbdd/.default_config" +fi + +## Clean cluster before executing the tests +if [ "${ENABLE_CLEAN_CLUSTER}" = "true" ]; then + clean_cluster +fi + +echo "-------- Running BDD tests" +echo "DEBUG=${DEBUG} go test ${TEST_MAIN_DIR} -v -timeout \"${TIMEOUT}m\" --godog.tags=\"${TAGS}\" ${PARAMS} ${FEATURE}" +DEBUG=${DEBUG} go test ${TEST_MAIN_DIR} -v -timeout "${TIMEOUT}m" --godog.tags="${TAGS}" ${PARAMS} ${FEATURE} +exit_code=$? + +echo "${exit_code}" > /tmp/bdd-exit-code.txt + +echo "Tests finished with code ${exit_code}" + +if [ "${KEEP_NAMESPACE}" = "false" ]; then + echo "-------- Pruning namespaces" + cd ${SCRIPT_DIR}/../testbdd + go run scripts/prune_namespaces.go + echo "Pruning namespaces done." + cd - >/dev/null +fi + +echo "-------- Delete stuck namespaces" +${SCRIPT_DIR}/clean-stuck-namespaces.sh + +if [ "${KEEP_NAMESPACE}" = "false" ] && [ "${ENABLE_CLEAN_CLUSTER}" = "true" ]; then + clean_cluster +fi + +exit ${exit_code} diff --git a/packages/kogito-serverless-operator/hack/run-tests.sh.bats b/packages/kogito-serverless-operator/hack/run-tests.sh.bats new file mode 100644 index 00000000000..c3ad5abb553 --- /dev/null +++ b/packages/kogito-serverless-operator/hack/run-tests.sh.bats @@ -0,0 +1,1100 @@ +#!/usr/bin/env bats + +function go() { + echo '' +} + +function oc() { + echo '' +} + +export -f go +export -f oc + +@test "invoke run-tests with dry_run" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --dry_run + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.dry_run" ]] +} + +@test "invoke run-tests with dry_run true" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --dry_run true + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.dry_run" ]] +} + +@test "invoke run-tests with dry_run false" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --dry_run false + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.dry_run"* ]] +} + +@test "invoke run-tests unknown option" { + run ${BATS_TEST_DIRNAME}/run-tests.sh something + [ "$status" -eq 1 ] + [ "${lines[0]}" = "Unknown arguments: something" ] +} + +# tests configuration + +@test "invoke run-tests with test_main_dir" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --test_main_dir ${BATS_TEST_DIRNAME}/../test/scripts/examples + [ "$status" -eq 0 ] + [[ "${output}" =~ " ${BATS_TEST_DIRNAME}/../test/scripts/examples" ]] +} + +@test "invoke run-tests with test_main_dir missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --test_main_dir + [ "$status" -eq 0 ] + [[ "${output}" =~ " ${BATS_TEST_DIRNAME}/../test" ]] +} + +@test "invoke run-tests with test_main_dir empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --test_main_dir "" + [ "$status" -eq 0 ] + [[ "${output}" =~ " ${BATS_TEST_DIRNAME}/../test" ]] +} + +@test "invoke run-tests with feature" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --feature ${BATS_TEST_DIRNAME}/../test/features + [ "$status" -eq 0 ] + [[ "${output}" =~ " ${BATS_TEST_DIRNAME}/../test/features" ]] +} + +@test "invoke run-tests with feature missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --feature + [ "$status" -eq 0 ] + [[ "${output}" != *" features"* ]] +} + +@test "invoke run-tests with feature empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --feature "" + [ "$status" -eq 0 ] + [[ "${output}" != *" features"* ]] +} + +@test "invoke run-tests with tags" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --tags hello + [ "$status" -eq 0 ] + [[ "${output}" =~ "--godog.tags=\"hello\"" ]] +} + +@test "invoke run-tests with tags multiple values" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --tags "hello and bonjour" + [ "$status" -eq 0 ] + [[ "${output}" =~ "--godog.tags=\"hello and bonjour\"" ]] +} + +@test "invoke run-tests with tags missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --tags + [ "$status" -eq 0 ] + [[ "${output}" =~ "--godog.tags=\"\"" ]] +} + +@test "invoke run-tests with tags empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --tags "" + [ "$status" -eq 0 ] + [[ "${output}" =~ "--godog.tags=\"\"" ]] +} + +@test "invoke run-tests with concurrent" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --concurrent 3 + [ "$status" -eq 0 ] + [[ "${output}" =~ "--godog.concurrency=3" ]] +} + +@test "invoke run-tests with concurrent missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --concurrent + [ "$status" -eq 0 ] + [[ "${output}" != *"--godog.concurrency"* ]] +} + +@test "invoke run-tests with concurrent empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --concurrent "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--godog.concurrency"* ]] +} + +@test "invoke run-tests with timeout" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --timeout 120 + [ "$status" -eq 0 ] + [[ "${output}" =~ "-timeout \"120m\"" ]] +} + +@test "invoke run-tests with timeout missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --timeout + [ "$status" -eq 0 ] + [[ "${output}" =~ "-timeout \"240m\"" ]] +} + +@test "invoke run-tests with timeout empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --timeout "" + [ "$status" -eq 0 ] + [[ "${output}" =~ "-timeout \"240m\"" ]] +} + +@test "invoke run-tests with debug" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --debug + [ "$status" -eq 0 ] + [[ "${output}" =~ "DEBUG=true go test"* ]] +} + +@test "invoke run-tests with debug true" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --debug true + [ "$status" -eq 0 ] + [[ "${output}" =~ "DEBUG=true go test"* ]] +} + +@test "invoke run-tests with debug false" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --debug false + [ "$status" -eq 0 ] + [[ "${output}" =~ "DEBUG=false go test"* ]] +} + +@test "invoke run-tests without debug" { + run ${BATS_TEST_DIRNAME}/run-tests.sh + [ "$status" -eq 0 ] + [[ "${output}" =~ "DEBUG=false go test"* ]] +} + +@test "invoke run-tests with smoke" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --smoke + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.smoke" ]] +} + +@test "invoke run-tests with smoke true" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --smoke true + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.smoke" ]] +} + +@test "invoke run-tests with smoke false" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --smoke false + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.smoke"* ]] +} + +@test "invoke run-tests without smoke" { + run ${BATS_TEST_DIRNAME}/run-tests.sh + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.smoke"* ]] +} + +@test "invoke run-tests with performance" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --performance + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.performance" ]] +} + +@test "invoke run-tests with performance true" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --performance true + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.performance" ]] +} + +@test "invoke run-tests with performance false" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --performance false + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.performance"* ]] +} + +@test "invoke run-tests without performance" { + run ${BATS_TEST_DIRNAME}/run-tests.sh + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.performance"* ]] +} + +@test "invoke run-tests with load_factor" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --load_factor 3 + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.load_factor=3" ]] +} + +@test "invoke run-tests with load_factor missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --load_factor + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.load_factor"* ]] +} + +@test "invoke run-tests with load_factor empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --load_factor "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.load_factor"* ]] +} + +@test "invoke run-tests with local_execution" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --local_execution + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.local_execution" ]] +} + +@test "invoke run-tests without local_execution" { + run ${BATS_TEST_DIRNAME}/run-tests.sh + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.local_execution"* ]] +} + +@test "invoke run-tests with ci" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --ci jenkins + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.ci=jenkins" ]] +} + +@test "invoke run-tests with ci missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --ci + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.ci"* ]] +} + +@test "invoke run-tests with ci empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --ci "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.ci"* ]] +} + +@test "invoke run-tests with cr_deployment_only" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --cr_deployment_only + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.cr_deployment_only" ]] +} + +@test "invoke run-tests with cr_deployment_only true" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --cr_deployment_only true + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.cr_deployment_only" ]] +} + +@test "invoke run-tests with cr_deployment_only false" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --cr_deployment_only false + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.cr_deployment_only"* ]] +} + +@test "invoke run-tests without cr_deployment_only" { + run ${BATS_TEST_DIRNAME}/run-tests.sh + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.cr_deployment_only"* ]] +} + +@test "invoke run-tests with load_default_config" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --load_default_config + [ "$status" -eq 0 ] + [[ "${output}" =~ "Load default test config" ]] +} + +@test "invoke run-tests with load_default_config true" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --load_default_config true + [ "$status" -eq 0 ] + [[ "${output}" =~ "Load default test config" ]] +} + +@test "invoke run-tests with load_default_config false" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --load_default_config false + [ "$status" -eq 0 ] + [[ "${output}" != *"Load default test config"* ]] +} + +@test "invoke run-tests without load_default_config" { + run ${BATS_TEST_DIRNAME}/run-tests.sh + [ "$status" -eq 0 ] + [[ "${output}" != *"Load default test config"* ]] +} + +@test "invoke run-tests with container_engine" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --container_engine podman + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.container_engine=podman" ]] +} + +@test "invoke run-tests with container_engine missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --container_engine + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.container_engine"* ]] +} + +@test "invoke run-tests with container_engine empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --container_engine "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.container_engine"* ]] +} + +@test "invoke run-tests with domain_suffix" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --domain_suffix suffix + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.domain_suffix=suffix" ]] +} + +@test "invoke run-tests with domain_suffix missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --domain_suffix + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.domain_suffix"* ]] +} + +@test "invoke run-tests with domain_suffix empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --domain_suffix "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.domain_suffix"* ]] +} + +@test "invoke run-tests with image_cache_mode" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --image_cache_mode always + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.image_cache_mode=always" ]] +} + +@test "invoke run-tests with image_cache_mode missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --image_cache_mode + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.image_cache_mode"* ]] +} + +@test "invoke run-tests with image_cache_mode empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --image_cache_mode "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.image_cache_mode"* ]] +} + +@test "invoke run-tests with http_retry_nb" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --http_retry_nb 3 + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.http_retry_nb=3" ]] +} + +@test "invoke run-tests with http_retry_nb missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --http_retry_nb + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.http_retry_nb"* ]] +} + +@test "invoke run-tests with http_retry_nb empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --http_retry_nb "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.http_retry_nb"* ]] +} + +@test "invoke run-tests with olm_namespace" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --olm_namespace olm + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.olm_namespace=olm" ]] +} + +@test "invoke run-tests with olm_namespace missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --olm_namespace + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.olm_namespace"* ]] +} + +@test "invoke run-tests with olm_namespace empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --olm_namespace "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.olm_namespace"* ]] +} + +# operator information + +@test "invoke run-tests with operator_image_tag" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_image_tag image + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.operator_image_tag=image" ]] +} + +@test "invoke run-tests with operator_image_tag missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_image_tag + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_image_tag"* ]] +} + +@test "invoke run-tests with operator_image_tag empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_image_tag "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_image_tag"* ]] +} + +@test "invoke run-tests with operator_installation_source" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_installation_source olm + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.operator_installation_source=olm" ]] +} + +@test "invoke run-tests with operator_installation_source missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_installation_source + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_installation_source"* ]] +} + +@test "invoke run-tests with operator_installation_source empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_installation_source "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_installation_source"* ]] +} + +@test "invoke run-tests with operator_catalog_image" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_catalog_image catalog-image + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.operator_catalog_image=catalog-image" ]] +} + +@test "invoke run-tests with operator_catalog_image missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_catalog_image + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_catalog_image"* ]] +} + +@test "invoke run-tests with operator_catalog_image empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_catalog_image "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_catalog_image"* ]] +} + +@test "invoke run-tests with use_product_operator" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --use_product_operator --dry_run + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.use_product_operator" ]] +} + +@test "invoke run-tests without use_product_operator" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --dry_run + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.use_product_operator"* ]] +} + +# operator profiling + +@test "invoke run-tests with operator_profiling_enabled" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_profiling_enabled + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.operator_profiling_enabled" ]] +} + +@test "invoke run-tests with operator_profiling_enabled true" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_profiling_enabled true + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.operator_profiling_enabled" ]] +} + +@test "invoke run-tests with operator_profiling_enabled false" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_profiling_enabled false + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_profiling_enabled"* ]] +} + +@test "invoke run-tests without operator_profiling_enabled" { + run ${BATS_TEST_DIRNAME}/run-tests.sh + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_profiling_enabled"* ]] +} + +@test "invoke run-tests with operator_profiling_data_access_yaml_uri" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_profiling_data_access_yaml_uri uri + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.operator_profiling_data_access_yaml_uri=uri" ]] +} + +@test "invoke run-tests with operator_profiling_data_access_yaml_uri missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_profiling_data_access_yaml_uri + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_profiling_data_access_yaml_uri"* ]] +} + +@test "invoke run-tests with operator_profiling_data_access_yaml_uri empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_profiling_data_access_yaml_uri "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_profiling_data_access_yaml_uri"* ]] +} + +@test "invoke run-tests with operator_profiling_output_file_uri" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_profiling_output_file_uri uri + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.operator_profiling_output_file_uri=uri" ]] +} + +@test "invoke run-tests with operator_profiling_output_file_uri missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_profiling_output_file_uri + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_profiling_output_file_uri"* ]] +} + +@test "invoke run-tests with operator_profiling_output_file_uri empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_profiling_output_file_uri "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_profiling_output_file_uri"* ]] +} + +# files/binaries + +@test "invoke run-tests with operator_yaml_uri" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_yaml_uri file.yaml + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.operator_yaml_uri=file.yaml" ]] +} + +@test "invoke run-tests with operator_yaml_uri missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_yaml_uri + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_yaml_uri"* ]] +} + +@test "invoke run-tests with operator_yaml_uri empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --operator_yaml_uri "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.operator_yaml_uri"* ]] +} + +@test "invoke run-tests with cli_path" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --cli_path cli + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.cli_path=cli" ]] +} + +@test "invoke run-tests with cli_path missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --cli_path + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.cli_path"* ]] +} + +@test "invoke run-tests with cli_path empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --cli_path "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.cli_path"* ]] +} + +@test "invoke run-tests with rhpam_operator_yaml_uri" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --rhpam_operator_yaml_uri file.yaml --dry_run + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.rhpam_operator_yaml_uri=file.yaml" ]] +} + +@test "invoke run-tests with rhpam_operator_yaml_uri missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --rhpam_operator_yaml_uri --dry_run + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.rhpam_operator_yaml_uri"* ]] +} + +@test "invoke run-tests with rhpam_operator_yaml_uri empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --rhpam_operator_yaml_uri "" --dry_run + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.rhpam_operator_yaml_uri"* ]] +} + +# runtime + +@test "invoke run-tests with services_image_tag" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --services_image_tag registry + [ "$status" -eq 1 ] + [[ "${output}" != *"--tests.services_image_tag"* ]] +} + +@test "invoke run-tests with services_{}_image_tag" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --services_anything_image_tag registry + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.services_anything_image_tag=registry" ]] +} + +@test "invoke run-tests with services_{}_image_tag missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --services_anything_image_tag + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.services_anything_image_tag"* ]] +} + +@test "invoke run-tests with services_{}_image_tag empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --services_anything_image_tag "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.services_anything_image_tag"* ]] +} + +@test "invoke run-tests with services_image_registry" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --services_image_registry registry + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.services_image_registry=registry" ]] +} + +@test "invoke run-tests with services_image_registry missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --services_image_registry + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.services_image_registry"* ]] +} + +@test "invoke run-tests with services_image_registry empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --services_image_registry "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.services_image_registry"* ]] +} + +@test "invoke run-tests with services_image_name_suffix" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --services_image_name_suffix suffix + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.services_image_name_suffix=suffix" ]] +} + +@test "invoke run-tests with services_image_name_suffix missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --services_image_name_suffix + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.services_image_name_suffix"* ]] +} + +@test "invoke run-tests with services_image_name_suffix empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --services_image_name_suffix "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.services_image_name_suffix"* ]] +} + +@test "invoke run-tests with services_image_version" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --services_image_version version + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.services_image_version=version" ]] +} + +@test "invoke run-tests with services_image_version missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --services_image_version + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.services_image_version"* ]] +} + +@test "invoke run-tests with services_image_version empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --services_image_version "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.services_image_version"* ]] +} + +@test "invoke run-tests with runtime_application_image_registry" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --runtime_application_image_registry registry + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.runtime_application_image_registry=registry" ]] +} + +@test "invoke run-tests with runtime_application_image_registry missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --runtime_application_image_registry + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.runtime_application_image_registry"* ]] +} + +@test "invoke run-tests with runtime_application_image_registry empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --runtime_application_image_registry "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.runtime_application_image_registry"* ]] +} + +@test "invoke run-tests with runtime_application_image_name_prefix" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --runtime_application_image_name_prefix prefix + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.runtime_application_image_name_prefix=prefix" ]] +} + +@test "invoke run-tests with runtime_application_image_name_prefix missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --runtime_application_image_name_prefix + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.runtime_application_image_name_prefix"* ]] +} + +@test "invoke run-tests with runtime_application_image_name_prefix empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --runtime_application_image_name_prefix "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.runtime_application_image_name_prefix"* ]] +} + +@test "invoke run-tests with runtime_application_image_name_suffix" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --runtime_application_image_name_suffix suffix + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.runtime_application_image_name_suffix=suffix" ]] +} + +@test "invoke run-tests with runtime_application_image_name_suffix missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --runtime_application_image_name_suffix + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.runtime_application_image_name_suffix"* ]] +} + +@test "invoke run-tests with runtime_application_image_name_suffix empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --runtime_application_image_name_suffix "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.runtime_application_image_name_suffix"* ]] +} + +@test "invoke run-tests with runtime_application_image_version" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --runtime_application_image_version latest + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.runtime_application_image_version=latest" ]] +} + +@test "invoke run-tests with runtime_application_image_version missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --runtime_application_image_version + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.runtime_application_image_version"* ]] +} + +@test "invoke run-tests with runtime_application_image_version empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --runtime_application_image_version "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.runtime_application_image_version"* ]] +} + +# build + +@test "invoke run-tests with custom_maven_repo_url" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --custom_maven_repo_url repourl + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.custom_maven_repo_url=repourl" ]] +} + +@test "invoke run-tests with custom_maven_repo_url missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --custom_maven_repo_url + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.custom_maven_repo_url"* ]] +} + +@test "invoke run-tests with custom_maven_repo_url empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --custom_maven_repo_url "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.custom_maven_repo_url"* ]] +} + +@test "invoke run-tests with custom_maven_repo_replace_default" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --custom_maven_repo_replace_default + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.custom_maven_repo_replace_default" ]] +} + +@test "invoke run-tests without custom_maven_repo_replace_default" { + run ${BATS_TEST_DIRNAME}/run-tests.sh + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.custom_maven_repo_replace_default"* ]] +} + +@test "invoke run-tests with maven_mirror_url" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --maven_mirror_url maven + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.maven_mirror_url=maven" ]] +} + +@test "invoke run-tests with maven_mirror_url missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --maven_mirror_url + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.maven_mirror_url"* ]] +} + +@test "invoke run-tests with maven_mirror_url empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --maven_mirror_url "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.maven_mirror_url"* ]] +} + +@test "invoke run-tests with quarkus_platform_maven_mirror_url" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --quarkus_platform_maven_mirror_url maven --dry_run + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.quarkus_platform_maven_mirror_url=maven" ]] +} + +@test "invoke run-tests with quarkus_platform_maven_mirror_url missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --quarkus_platform_maven_mirror_url --dry_run + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.quarkus_platform_maven_mirror_url"* ]] +} + +@test "invoke run-tests with quarkus_platform_maven_mirror_url empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --quarkus_platform_maven_mirror_url "" --dry_run + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.quarkus_platform_maven_mirror_url"* ]] +} + +@test "invoke run-tests with maven_ignore_self_signed_certificate" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --maven_ignore_self_signed_certificate + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.maven_ignore_self_signed_certificate" ]] +} + +@test "invoke run-tests with maven_ignore_self_signed_certificate true" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --maven_ignore_self_signed_certificate true + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.maven_ignore_self_signed_certificate" ]] +} + +@test "invoke run-tests with maven_ignore_self_signed_certificate false" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --maven_ignore_self_signed_certificate false + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.maven_ignore_self_signed_certificate"* ]] +} + +@test "invoke run-tests without maven_ignore_self_signed_certificate" { + run ${BATS_TEST_DIRNAME}/run-tests.sh + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.maven_ignore_self_signed_certificate"* ]] +} + +@test "invoke run-tests with build_builder_image_tag" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --build_builder_image_tag tag + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.build_builder_image_tag=tag" ]] +} + +@test "invoke run-tests with build_builder_image_tag missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --build_builder_image_tag + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.build_builder_image_tag"* ]] +} + +@test "invoke run-tests with build_builder_image_tag empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --build_builder_image_tag "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.build_builder_image_tag"* ]] +} + +@test "invoke run-tests with build_runtime_jvm_image_tag" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --build_runtime_jvm_image_tag tag + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.build_runtime_jvm_image_tag=tag" ]] +} + +@test "invoke run-tests with build_runtime_jvm_image_tag missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --build_runtime_jvm_image_tag + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.build_runtime_jvm_image_tag"* ]] +} + +@test "invoke run-tests with build_runtime_jvm_image_tag empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --build_runtime_jvm_image_tag "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.build_runtime_jvm_image_tag"* ]] +} + +@test "invoke run-tests with build_runtime_native_image_tag" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --build_runtime_native_image_tag tag + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.build_runtime_native_image_tag=tag" ]] +} + +@test "invoke run-tests with build_runtime_native_image_tag missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --build_runtime_native_image_tag + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.build_runtime_native_image_tag"* ]] +} + +@test "invoke run-tests with build_runtime_native_image_tag empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --build_runtime_native_image_tag "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.build_runtime_native_image_tag"* ]] +} + +@test "invoke run-tests with disable_maven_native_build_container" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --disable_maven_native_build_container + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.disable_maven_native_build_container" ]] +} + +@test "invoke run-tests without disable_maven_native_build_container" { + run ${BATS_TEST_DIRNAME}/run-tests.sh + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.disable_maven_native_build_container"* ]] +} + +@test "invoke run-tests with native_builder_image" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --native_builder_image image + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.native_builder_image=image" ]] +} + +@test "invoke run-tests with native_builder_image missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --native_builder_image + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.native_builder_image"* ]] +} + +@test "invoke run-tests with native_builder_image empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --native_builder_image "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.native_builder_image"* ]] +} + +# examples repository + +@test "invoke run-tests with examples_uri" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --examples_uri uri + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.examples_uri=uri" ]] +} + +@test "invoke run-tests with examples_uri missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --examples_uri + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.examples_uri"* ]] +} + +@test "invoke run-tests with examples_uri empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --examples_uri "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.examples_uri"* ]] +} + +@test "invoke run-tests with examples_ref" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --examples_ref ref + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.examples_ref=ref" ]] +} + +@test "invoke run-tests with examples_ref missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --examples_ref + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.examples_ref"* ]] +} + +@test "invoke run-tests with examples_ref empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --examples_ref "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.examples_ref"* ]] +} + +# Infinispan + +@test "invoke run-tests with infinispan_installation_source" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --infinispan_installation_source yaml + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.infinispan_installation_source=yaml" ]] +} + +@test "invoke run-tests with infinispan_installation_source missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --infinispan_installation_source + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.infinispan_installation_source"* ]] +} + +@test "invoke run-tests with infinispan_installation_source empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --infinispan_installation_source "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.infinispan_installation_source"* ]] +} + +@test "invoke run-tests with infinispan_storage_class" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --infinispan_storage_class local + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.infinispan_storage_class=local" ]] +} + +@test "invoke run-tests with infinispan_storage_class missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --infinispan_storage_class + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.infinispan_storage_class"* ]] +} + +@test "invoke run-tests with infinispan_storage_class empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --infinispan_storage_class "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.infinispan_storage_class"* ]] +} + +# Hyperfoil + +@test "invoke run-tests with hyperfoil_output_directory" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --hyperfoil_output_directory /some/folder + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.hyperfoil_output_directory=/some/folder" ]] +} + +@test "invoke run-tests with hyperfoil_output_directory missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --hyperfoil_output_directory + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.hyperfoil_output_directory"* ]] +} + +@test "invoke run-tests with hyperfoil_output_directory empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --hyperfoil_output_directory "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.hyperfoil_output_directory"* ]] +} + +@test "invoke run-tests with hyperfoil_controller_image_version" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --hyperfoil_controller_image_version 0.1.0 + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.hyperfoil_controller_image_version=0.1.0" ]] +} + +@test "invoke run-tests with hyperfoil_controller_image_version missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --hyperfoil_controller_image_version + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.hyperfoil_controller_image_version"* ]] +} + +@test "invoke run-tests with hyperfoil_controller_image_version empty value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --hyperfoil_controller_image_version "" + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.hyperfoil_controller_image_version"* ]] +} + +# dev options + +@test "invoke run-tests with show_scenarios" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --show_scenarios + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.show_scenarios" ]] +} + +@test "invoke run-tests with show_scenarios true" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --show_scenarios true + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.show_scenarios" ]] +} + +@test "invoke run-tests with show_scenarios false" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --show_scenarios false + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.show_scenarios"* ]] +} + +@test "invoke run-tests with keep_namespace" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --keep_namespace + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.keep_namespace" ]] +} + +@test "invoke run-tests with keep_namespace true" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --keep_namespace true + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.keep_namespace" ]] +} + +@test "invoke run-tests with keep_namespace false" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --keep_namespace false + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.keep_namespace"* ]] +} + +@test "invoke run-tests without keep_namespace" { + run ${BATS_TEST_DIRNAME}/run-tests.sh + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.keep_namespace"* ]] +} + +@test "invoke run-tests with namespace_name" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --namespace_name test-namespace + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.dev.namespace_name=test-namespace" ]] +} + +@test "invoke run-tests with namespace_name missing value" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --namespace_name + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.dev.namespace_name"* ]] +} + +@test "invoke run-tests with local_cluster" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --local_cluster + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.dev.local_cluster" ]] +} + +@test "invoke run-tests with local_cluster true" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --local_cluster true + [ "$status" -eq 0 ] + [[ "${output}" =~ "--tests.dev.local_cluster" ]] +} + +@test "invoke run-tests with local_cluster false" { + run ${BATS_TEST_DIRNAME}/run-tests.sh --local_cluster false + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.dev.local_cluster"* ]] +} + +@test "invoke run-tests without local_cluster" { + run ${BATS_TEST_DIRNAME}/run-tests.sh + [ "$status" -eq 0 ] + [[ "${output}" != *"--tests.dev.local_cluster"* ]] +} \ No newline at end of file diff --git a/packages/kogito-serverless-operator/images/bundle.yaml b/packages/kogito-serverless-operator/images/bundle.yaml new file mode 100644 index 00000000000..fe797bc3fe2 --- /dev/null +++ b/packages/kogito-serverless-operator/images/bundle.yaml @@ -0,0 +1,47 @@ +schema_version: 1 +name: "sonataflow-operator-bundle" +description: "SonataFlow Operator Bundle" +version: 0.0.0 +from: "scratch" + +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: "alpha" + - name: operators.operatorframework.io.bundle.channel.default.v1 + value: alpha + - name: operators.operatorframework.io.metrics.mediatype.v1 + value: metrics+v1 + - name: operators.operatorframework.io.metrics.builder + value: operator-sdk-v1.25.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.10 + +modules: + repositories: + - path: modules + install: + - name: org.apache.kie.sonataflow.bundle diff --git a/packages/kogito-serverless-operator/images/manager.yaml b/packages/kogito-serverless-operator/images/manager.yaml new file mode 100644 index 00000000000..6dfdb2c19a2 --- /dev/null +++ b/packages/kogito-serverless-operator/images/manager.yaml @@ -0,0 +1,40 @@ +- name: operator-builder + version: 0.0.0 + from: "golang:1.21.6" + 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.3-9" + 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/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.bundle/module.yaml b/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.bundle/module.yaml new file mode 100644 index 00000000000..7348191deef --- /dev/null +++ b/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.bundle/module.yaml @@ -0,0 +1,14 @@ +name: org.apache.kie.sonataflow.bundle +version: "1.0" +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/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.goModDownload/install.sh b/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.goModDownload/install.sh new file mode 100755 index 00000000000..e2d36e4f6ef --- /dev/null +++ b/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.goModDownload/install.sh @@ -0,0 +1,20 @@ +#!/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/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.goModDownload/module.yaml b/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.goModDownload/module.yaml new file mode 100644 index 00000000000..befb19a313a --- /dev/null +++ b/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.goModDownload/module.yaml @@ -0,0 +1,31 @@ +name: org.apache.kie.sonataflow.goModDownload +version: "1.0" +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/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.operatorBuilder/install.sh b/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.operatorBuilder/install.sh new file mode 100644 index 00000000000..d4e18d13edb --- /dev/null +++ b/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.operatorBuilder/install.sh @@ -0,0 +1,21 @@ +#!/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 main.go; \ No newline at end of file diff --git a/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.operatorBuilder/module.yaml b/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.operatorBuilder/module.yaml new file mode 100644 index 00000000000..4b1c6ced92c --- /dev/null +++ b/packages/kogito-serverless-operator/images/modules/org.apache.kie.sonataflow.operatorBuilder/module.yaml @@ -0,0 +1,28 @@ +name: org.apache.kie.sonataflow.operatorBuilder +version: "1.0" +description: Builds the operator binary + +artifacts: + - name: main + path: "../../../../main.go" + target: "main.go" + dest: /workspace/ + + - name: controllers + path: "../../../../controllers" + dest: /workspace/controllers + + - name: version + path: "../../../../version" + dest: /workspace/version + + - name: utils + path: "../../../../utils" + dest: /workspace/utils + + - name: log + path: "../../../../log" + dest: /workspace/log + +execute: + - script: install.sh diff --git a/packages/kogito-serverless-operator/images/requirements.txt b/packages/kogito-serverless-operator/images/requirements.txt new file mode 100644 index 00000000000..87a0ef5117c --- /dev/null +++ b/packages/kogito-serverless-operator/images/requirements.txt @@ -0,0 +1,10 @@ +# Requirements for cekit 4.11.0 build +# see: https://pip.pypa.io/en/stable/reference/requirements-file-format/ +docker-squash +odcs +docker +python-docker +behave +lxml +krb5 +cekit == 4.11.0 diff --git a/packages/kogito-serverless-operator/log/log.go b/packages/kogito-serverless-operator/log/log.go new file mode 100644 index 00000000000..544fea7b7f5 --- /dev/null +++ b/packages/kogito-serverless-operator/log/log.go @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/main.go b/packages/kogito-serverless-operator/main.go new file mode 100644 index 00000000000..7f181140601 --- /dev/null +++ b/packages/kogito-serverless-operator/main.go @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "flag" + "os" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/cfg" + eventingv1 "knative.dev/eventing/pkg/apis/eventing/v1" + sourcesv1 "knative.dev/eventing/pkg/apis/sources/v1" + + "k8s.io/klog/v2/klogr" + + "k8s.io/klog/v2" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers" + ocputil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils/openshift" + + // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) + // to ensure that exec-entrypoint and run can make use of them. + _ "k8s.io/client-go/plugin/pkg/client/auth" + + "k8s.io/apimachinery/pkg/runtime" + 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/healthz" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + //+kubebuilder:scaffold:imports +) + +var ( + scheme = runtime.NewScheme() +) + +func init() { + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + utilruntime.Must(operatorapi.AddToScheme(scheme)) + utilruntime.Must(sourcesv1.AddToScheme(scheme)) + utilruntime.Must(eventingv1.AddToScheme(scheme)) + //+kubebuilder:scaffold:scheme +} + +func main() { + var metricsAddr string + var enableLeaderElection bool + var probeAddr string + var controllerCfgPath string + klog.InitFlags(nil) + flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") + 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.") + flag.StringVar(&controllerCfgPath, "controller-cfg-path", "", "The controller config file path.") + flag.Parse() + + ctrl.SetLogger(klogr.New().WithName(controllers.ComponentName)) + + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + Scheme: scheme, + MetricsBindAddress: metricsAddr, + Port: 9443, + HealthProbeBindAddress: probeAddr, + LeaderElection: enableLeaderElection, + LeaderElectionID: "1be5e57d.kie.org", + }) + if err != nil { + klog.V(log.E).ErrorS(err, "unable to start manager") + os.Exit(1) + } + + // Set global assessors + utils.SetIsOpenShift(mgr.GetConfig()) + utils.SetClient(mgr.GetClient()) + + // 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) + } + + if err = (&controllers.SonataFlowReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Config: mgr.GetConfig(), + Recorder: mgr.GetEventRecorderFor("workflow-controller"), + }).SetupWithManager(mgr); err != nil { + klog.V(log.E).ErrorS(err, "unable to create controller", "controller", "SonataFlow") + os.Exit(1) + } + if err = (&controllers.SonataFlowBuildReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Config: mgr.GetConfig(), + Recorder: mgr.GetEventRecorderFor("build-controller"), + }).SetupWithManager(mgr); err != nil { + klog.V(log.E).ErrorS(err, "unable to create controller", "controller", "SonataFlowBuild") + os.Exit(1) + } + + if err = (&controllers.SonataFlowPlatformReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Reader: mgr.GetAPIReader(), + Config: mgr.GetConfig(), + Recorder: mgr.GetEventRecorderFor("platform-controller"), + }).SetupWithManager(mgr); err != nil { + klog.V(log.E).ErrorS(err, "unable to create controller", "controller", "SonataFlowPlatform") + os.Exit(1) + } + if err = (&controllers.SonataFlowClusterPlatformReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Reader: mgr.GetAPIReader(), + Config: mgr.GetConfig(), + Recorder: mgr.GetEventRecorderFor("cluster-platform-controller"), + }).SetupWithManager(mgr); err != nil { + klog.V(log.E).ErrorS(err, "unable to create controller", "controller", "SonataFlowClusterPlatform") + os.Exit(1) + } + //+kubebuilder:scaffold:builder + + if utils.IsOpenShift() { + ocputil.MustAddToScheme(mgr.GetScheme()) + } + + if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { + klog.V(log.E).ErrorS(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") + os.Exit(1) + } + + klog.V(log.I).InfoS("starting manager") + if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { + klog.V(log.E).ErrorS(err, "problem running manager") + os.Exit(1) + } + +} diff --git a/packages/kogito-serverless-operator/operator.yaml b/packages/kogito-serverless-operator/operator.yaml new file mode 100644 index 00000000000..2dab6916278 --- /dev/null +++ b/packages/kogito-serverless-operator/operator.yaml @@ -0,0 +1,27130 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + control-plane: sonataflow-operator + name: sonataflow-operator-system +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.2 + creationTimestamp: null + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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.9.2 + creationTimestamp: null + 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.9.2 + creationTimestamp: null + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + 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. \n 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + 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. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + 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 + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be set + if type is "Localhost". + type: string + type: + description: "type indicates which kind of + seccomp profile will be applied. Valid options + are: \n 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. + This field is alpha-level and will only + be honored by components that enable the + WindowsHostProcessContainers feature flag. + Setting this field without the feature flag + will result in errors when validating the + Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind + of seccomp profile will be applied. Valid + options are: \n 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. This field is alpha-level and + will only be honored by components that + enable the WindowsHostProcessContainers + feature flag. Setting this field without + the feature flag will result in errors + when validating the Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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 + 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 + 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 + 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 + ip: + description: IP address of the host file entry. + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind + of seccomp profile will be applied. Valid + options are: \n 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. This field is alpha-level and + will only be honored by components that + enable the WindowsHostProcessContainers + feature flag. Setting this field without + the feature flag will result in errors + when validating the Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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. \n If the OS field is set to linux, the + following fields must be unset: -securityContext.windowsOptions + \n 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 + 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. \n This is an + alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable." + items: + description: PodResourceClaim references exactly one + ResourceClaim through a ClaimSource. 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 + source: + description: Source describes where to find the + ResourceClaim. + properties: + resourceClaimName: + description: ResourceClaimName is the name of + a ResourceClaim object in the same namespace + as this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the + name of a ResourceClaimTemplate object in + the same namespace as this pod. \n 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 name of the ResourceClaim + will be -, where + is the PodResourceClaim.Name. + Pod validation will reject the pod if the + concatenated name is not valid for a ResourceClaim + (e.g. too long). \n An existing ResourceClaim + with that name that is not owned by the pod + will not be used for the pod to avoid using + an unrelated resource by mistake. Scheduling + and pod startup are then blocked until the + unrelated ResourceClaim is removed. \n This + field is immutable and no changes will be + made to the corresponding ResourceClaim by + the control plane after creating the ResourceClaim." + type: string + type: object + 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. \n SchedulingGates can only be + set at pod creation time, and be removed only afterwards. + \n 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: + 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: \n 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---- \n + 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: + \n 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, the fsGroup (if specified), + and group memberships defined in the container image + for the uid of the container process. If unspecified, + no additional groups are added to any container. + Note that group memberships defined in the container + image for the uid of the container process are still + effective, even if they are not included in this + list. Note that this field cannot be set when spec.os.name + is windows. + items: + format: int64 + type: integer + type: array + 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 + 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. + This field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the + feature flag will result in errors when validating + the Pod. 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + 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. \n 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. \n 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. \n This is a beta + field and requires the MinDomainsInPodTopologySpread + feature gate to be enabled (enabled by default)." + 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. + \n 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. \n 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + name: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 and namespace 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 + 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. \n 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). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes + that persist for longer than the lifecycle of + an individual pod. \n 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. \n 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). + \n 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. \n This field is read-only + and no changes will be made by Kubernetes + to the PVC after it has been created. \n 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 + 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: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. + \n This is an alpha field and + requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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. TODO: how do we prevent errors + in the filesystem from compromising the machine' + 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 + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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 + --- TODO(jonesdl) We need to restrict who can + use host directory mounts and who can/can not + mount host directories as read/write." + 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 + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + items: + description: Projection that may be projected + along with other supported volume types + properties: + 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 + name: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 and namespace + 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 + 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 + name: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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 + pool: + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + x-kubernetes-map-type: atomic + user: + 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: + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable + SSL communication with Gateway, default false + type: boolean + storageMode: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + 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: 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + 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. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + 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 + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be set + if type is "Localhost". + type: string + type: + description: "type indicates which kind of + seccomp profile will be applied. Valid options + are: \n 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. + This field is alpha-level and will only + be honored by components that enable the + WindowsHostProcessContainers feature flag. + Setting this field without the feature flag + will result in errors when validating the + Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind + of seccomp profile will be applied. Valid + options are: \n 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. This field is alpha-level and + will only be honored by components that + enable the WindowsHostProcessContainers + feature flag. Setting this field without + the feature flag will result in errors + when validating the Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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 + 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 + 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 + 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 + ip: + description: IP address of the host file entry. + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. \n This is an alpha field + and requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX + capabilities type + type: string + type: array + 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 + is DefaultProcMount 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind + of seccomp profile will be applied. Valid + options are: \n 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. This field is alpha-level and + will only be honored by components that + enable the WindowsHostProcessContainers + feature flag. Setting this field without + the feature flag will result in errors + when validating the Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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. \n If the OS field is set to linux, the + following fields must be unset: -securityContext.windowsOptions + \n 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 + 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. \n This is an + alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable." + items: + description: PodResourceClaim references exactly one + ResourceClaim through a ClaimSource. 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 + source: + description: Source describes where to find the + ResourceClaim. + properties: + resourceClaimName: + description: ResourceClaimName is the name of + a ResourceClaim object in the same namespace + as this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the + name of a ResourceClaimTemplate object in + the same namespace as this pod. \n 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 name of the ResourceClaim + will be -, where + is the PodResourceClaim.Name. + Pod validation will reject the pod if the + concatenated name is not valid for a ResourceClaim + (e.g. too long). \n An existing ResourceClaim + with that name that is not owned by the pod + will not be used for the pod to avoid using + an unrelated resource by mistake. Scheduling + and pod startup are then blocked until the + unrelated ResourceClaim is removed. \n This + field is immutable and no changes will be + made to the corresponding ResourceClaim by + the control plane after creating the ResourceClaim." + type: string + type: object + 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. \n SchedulingGates can only be + set at pod creation time, and be removed only afterwards. + \n 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: + 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: \n 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---- \n + 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: + \n 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, the fsGroup (if specified), + and group memberships defined in the container image + for the uid of the container process. If unspecified, + no additional groups are added to any container. + Note that group memberships defined in the container + image for the uid of the container process are still + effective, even if they are not included in this + list. Note that this field cannot be set when spec.os.name + is windows. + items: + format: int64 + type: integer + type: array + 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 + 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. + This field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the + feature flag will result in errors when validating + the Pod. 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + 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. \n 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. \n 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. \n This is a beta + field and requires the MinDomainsInPodTopologySpread + feature gate to be enabled (enabled by default)." + 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. + \n 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. \n 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + name: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 and namespace 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 + 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. \n 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). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes + that persist for longer than the lifecycle of + an individual pod. \n 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. \n 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). + \n 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. \n This field is read-only + and no changes will be made by Kubernetes + to the PVC after it has been created. \n 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 + 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: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. + \n This is an alpha field and + requires enabling the DynamicResourceAllocation + feature gate. \n 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 + 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 + 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + 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 + 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. TODO: how do we prevent errors + in the filesystem from compromising the machine' + 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 + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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 + --- TODO(jonesdl) We need to restrict who can + use host directory mounts and who can/can not + mount host directories as read/write." + 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 + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + items: + description: Projection that may be projected + along with other supported volume types + properties: + 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 + name: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 and namespace + 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 + 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 + name: + description: "Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + TODO: how do we prevent errors in the filesystem + from compromising the machine' + 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: + 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 + pool: + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + x-kubernetes-map-type: atomic + user: + 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: + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable + SSL communication with Gateway, default false + type: boolean + storageMode: + 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 + 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: + description: "Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + type: object + 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 + 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 build + type: object + observedGeneration: + description: The generation observed by the deployment controller. + format: int64 + type: integer + 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.9.2 + creationTimestamp: null + 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: + type: string + 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: + 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: + additionalProperties: + type: object + description: Metadata information + type: object + 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: + additionalProperties: + type: object + description: Metadata information + type: object + 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) + TODO: make iso8601duration compatible this type" + 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: + additionalProperties: + type: object + description: Add additional extension context + attributes to the produced event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to be passed + to the referenced function TODO: validate + it as required if function type is graphql" + type: object + 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. TODO: validate it as required if function + type is graphql" + 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: + additionalProperties: + type: object + description: Add additional extension + context attributes to the produced + event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function + definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to + be passed to the referenced function + TODO: validate it as required if function + type is graphql" + type: object + 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. TODO: validate + it as required if function type is + graphql" + 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: + additionalProperties: + type: object + description: Add additional extension context + attributes to the produced event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to be passed + to the referenced function TODO: validate + it as required if function type is graphql" + type: object + 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. TODO: validate it as required if function + type is graphql" + 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: + additionalProperties: + type: object + description: JSON object which can be set as state's + data input and can be manipulated via filter + minProperties: 1 + type: object + 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: + additionalProperties: + type: object + description: Metadata information. + type: object + 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: + additionalProperties: + type: object + description: Add additional extension context + attributes to the produced event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to be passed + to the referenced function TODO: validate + it as required if function type is graphql" + type: object + 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. TODO: validate it as required if function + type is graphql" + 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: + additionalProperties: + type: object + description: Add additional extension + context attributes to the produced + event. + type: object + 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. + type: object + 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: + - resultEventRef + - triggerEventRef + type: object + functionRef: + description: References a reusable function + definition. + properties: + arguments: + additionalProperties: + type: object + description: "Arguments (inputs) to + be passed to the referenced function + TODO: validate it as required if function + type is graphql" + type: object + 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. TODO: validate + it as required if function type is + graphql" + 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. + TODO: change this field to unmarshal result as int" + 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: TODO End or Transition needs to be + exclusive tag, one or another should be set. + 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 + type: object + 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. + type: object + 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: + additionalProperties: + type: object + description: Metadata information. + type: object + 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. + type: object + 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: If 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: TODO End or Transition needs to be + exclusive tag, one or another should be set. + 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: 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + 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 + 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 + required: + - key + - operator + type: object + type: array + 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 + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + 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 + 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 + 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. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + 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 + 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 + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + 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 is DefaultProcMount + 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 only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n 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. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + 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 is DefaultProcMount + 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n + 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. This + field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the + Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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 + 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 + 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 + 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 + ip: + description: IP address of the host file entry. + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + type: object + 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 + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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: + 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). + \n 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 + 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 + 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: + 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). + \n 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 + 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. + \n This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. \n 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 + 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 + 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 + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + 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 is DefaultProcMount + 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n + 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. This + field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the + Pod. 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 + 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: + 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). + \n 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 + 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. + 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 + 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 + 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. \n If + the OS field is set to linux, the following fields must be unset: + -securityContext.windowsOptions \n 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 + 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. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. \n This + field is immutable." + items: + description: PodResourceClaim references exactly one ResourceClaim + through a ClaimSource. 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 + source: + description: Source describes where to find the ResourceClaim. + properties: + resourceClaimName: + description: ResourceClaimName is the name of a ResourceClaim + object in the same namespace as this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the name + of a ResourceClaimTemplate object in the same namespace + as this pod. \n 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 name of the ResourceClaim will be + -, where + is the PodResourceClaim.Name. Pod validation will + reject the pod if the concatenated name is not valid + for a ResourceClaim (e.g. too long). \n An existing + ResourceClaim with that name that is not owned by + the pod will not be used for the pod to avoid using + an unrelated resource by mistake. Scheduling and pod + startup are then blocked until the unrelated ResourceClaim + is removed. \n This field is immutable and no changes + will be made to the corresponding ResourceClaim by + the control plane after creating the ResourceClaim." + type: string + type: object + 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. \n SchedulingGates + can only be set at pod creation time, and be removed only afterwards. + \n 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: + 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: \n 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---- + \n 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 only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n 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, the fsGroup (if specified), and group memberships defined + in the container image for the uid of the container process. + If unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image + for the uid of the container process are still effective, + even if they are not included in this list. Note that this + field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + 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 + 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. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + 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. \n 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. \n 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. \n This is a beta field and requires + the MinDomainsInPodTopologySpread feature gate to be enabled + (enabled by default)." + 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. \n 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. \n 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 + TODO: how do we prevent errors in the filesystem from + compromising the machine' + 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: + 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: + 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 + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + name: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 and namespace + 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 + 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. \n + 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). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes that persist + for longer than the lifecycle of an individual pod. \n + 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. \n 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). \n 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. + \n This field is read-only and no changes will be + made by Kubernetes to the PVC after it has been created. + \n 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 + 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: + claims: + description: "Claims lists the names of + resources, defined in spec.resourceClaims, + that are used by this container. \n This + is an alpha field and requires enabling + the DynamicResourceAllocation feature + gate. \n 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 + 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 + 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 + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + 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 + 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. TODO: how do we prevent + errors in the filesystem from compromising the machine' + 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 + 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 + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + TODO: how do we prevent errors in the filesystem from + compromising the machine' + 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 + --- TODO(jonesdl) We need to restrict who can use host + directory mounts and who can/can not mount host directories + as read/write." + 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 + 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 + TODO: how do we prevent errors in the filesystem from + compromising the machine' + 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: + 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 + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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 + items: + description: Projection that may be projected along + with other supported volume types + properties: + 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 + name: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 and namespace 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 + 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 + name: + description: "Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?" + type: string + 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 + 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 + TODO: how do we prevent errors in the filesystem from + compromising the machine' + 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: + 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 + pool: + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + x-kubernetes-map-type: atomic + user: + 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: + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + 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 + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?" + type: string + type: object + 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: + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?" + type: string + type: object + 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 + 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 + 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 + 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 + lastTimeRecoverAttempt: + format: date-time + type: string + observedGeneration: + description: The generation observed by the deployment controller. + format: int64 + type: integer + recoverFailureAttempts: + description: keeps track of how many failure recovers a given workflow + had so far + type: integer + 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 + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: sonataflow-operator-controller-manager + namespace: sonataflow-operator-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + 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: + 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 + - 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 +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + 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: + creationTimestamp: null + name: sonataflow-operator-manager-role +rules: + - apiGroups: + - sonataflow.org + resources: + - sonataflowbuilds + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflowbuilds/finalizers + verbs: + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowbuilds/status + verbs: + - get + - patch + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowclusterplatforms + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflowclusterplatforms/finalizers + verbs: + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowclusterplatforms/status + verbs: + - get + - patch + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowplatforms + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflowplatforms/finalizers + verbs: + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflowplatforms/status + verbs: + - get + - patch + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflows + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflows/finalizers + verbs: + - update + - apiGroups: + - sonataflow.org + resources: + - sonataflows/status + verbs: + - get + - patch + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: sonataflow-operator-metrics-reader +rules: + - nonResourceURLs: + - /metrics + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + 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: + 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: + 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: + 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: + 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: + 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: + 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: + 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: + 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: + 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: "FROM quay.io/kiegroup/kogito-swf-builder-nightly:latest 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: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: + name: sonataflow-operator-builder-config + namespace: sonataflow-operator-system +--- +apiVersion: v1 +data: + controllers_cfg.yaml: | + # 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: "" + dataIndexEphemeralTag: "" + # 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 se 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" +kind: ConfigMap +metadata: + name: sonataflow-operator-controllers-config + namespace: sonataflow-operator-system +--- +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: sonataflow-operator + name: sonataflow-operator-controller-manager-metrics-service + namespace: sonataflow-operator-system +spec: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: https + selector: + control-plane: sonataflow-operator +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + control-plane: sonataflow-operator + name: sonataflow-operator-controller-manager + namespace: sonataflow-operator-system +spec: + replicas: 1 + selector: + matchLabels: + control-plane: sonataflow-operator + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: manager + labels: + control-plane: sonataflow-operator + spec: + containers: + - args: + - --health-probe-bind-address=:8081 + - --metrics-bind-address=127.0.0.1:8080 + - --leader-elect + - --v=0 + command: + - /usr/local/bin/manager + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: quay.io/kiegroup/kogito-serverless-operator-nightly:latest + 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: 128Mi + requests: + cpu: 10m + memory: 64Mi + 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 + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0 + 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/packages/kogito-serverless-operator/package.json b/packages/kogito-serverless-operator/package.json new file mode 100644 index 00000000000..37d48b846f1 --- /dev/null +++ b/packages/kogito-serverless-operator/package.json @@ -0,0 +1,54 @@ +{ + "private": true, + "name": "@kie-tools/kogito-serverless-operator", + "version": "0.0.0", + "description": "", + "license": "Apache-2.0", + "homepage": "https://github.com/apache/incubator-kie-tools", + "repository": { + "type": "git", + "url": "https://github.com/apache/incubator-kie-tools.git" + }, + "bugs": { + "url": "https://github.com/apache/incubator-kie-tools/issues" + }, + "scripts": { + "build:dev": "run-script-os", + "build:dev:darwin:linux": ". ./node_modules/@kie-tools/python-venv/venv/bin/activate && make build && pnpm image:build && pnpm format", + "build:dev:win32": ".\\node_modules\\@kie-tools\\python-venv\\venv\\Scripts\\Activate.bat && make build && pnpm image:build && pnpm format", + "build:prod": "run-script-os", + "build:prod:darwin:linux": ". ./node_modules/@kie-tools/python-venv/venv/bin/activate && make build && pnpm image:build && pnpm test && pnpm test-e2e && pnpm format", + "build:prod:win32": "echo 'Build not supported on Windows'", + "bump-version": "run-script-os", + "bump-version:darwin:linux": "./hack/bump-version.sh $(pnpm build-env kogitoServerlessOperator.version)", + "bump-version:win32": "echo 'Bumping version not supported on Windows'", + "format": "prettier --write .", + "image:build": "run-script-os", + "image:build:darwin:win32": "echo 'Image build not supported on Windows and macOS'", + "image:build:linux": ". ./node_modules/@kie-tools/python-venv/venv/bin/activate && run-script-if --bool \"$(build-env containerImages.build)\" --then \"make container-build\"", + "install": "rimraf bin && go mod tidy && pnpm bump-version && pnpm format", + "test": "run-script-os", + "test-e2e": "run-script-os", + "test-e2e:darwin:win32": "echo 'E2E tests not supported on Windows and macOS'", + "test-e2e:linux": ". ./node_modules/@kie-tools/python-venv/venv/bin/activate && run-script-if --ignore-errors \"$(build-env tests.ignoreFailures)\" --bool \"$(build-env endToEndTests.run)\" --then \"make full-test-e2e\"", + "test:darwin:linux": ". ./node_modules/@kie-tools/python-venv/venv/bin/activate && run-script-if --ignore-errors \"$(build-env tests.ignoreFailures)\" --bool \"$(build-env tests.run)\" --then \"make test\"", + "test:win32": ".\\node_modules\\@kie-tools\\python-venv\\venv\\Scripts\\Activate.bat && run-script-if --ignore-errors \"$(build-env tests.ignoreFailures)\" --bool \"$(build-env tests.run)\" --then \"make test\"" + }, + "dependencies": {}, + "devDependencies": { + "@kie-tools/kogito-swf-builder": "workspace:*", + "@kie-tools/kogito-swf-devmode": "workspace:*", + "@kie-tools/python-venv": "workspace:*", + "@kie-tools/root-env": "workspace:*", + "replace-in-file": "^7.1.0", + "rimraf": "^3.0.2", + "run-script-os": "^1.1.6" + }, + "kieTools": { + "requiredPreinstalledCliCommands": [ + "go", + "make", + "python3" + ] + } +} \ No newline at end of file diff --git a/packages/kogito-serverless-operator/tekton/pipeline/kogito_serverless_operator_pipeline.yaml b/packages/kogito-serverless-operator/tekton/pipeline/kogito_serverless_operator_pipeline.yaml new file mode 100644 index 00000000000..3e05f9c6177 --- /dev/null +++ b/packages/kogito-serverless-operator/tekton/pipeline/kogito_serverless_operator_pipeline.yaml @@ -0,0 +1,63 @@ +apiVersion: tekton.dev/v1beta1 +kind: Pipeline +metadata: + name: kogito-serverless-operator-pipeline + namespace: sonataflow-operator-system +spec: + params: + - description: name of the deployment to be patched + name: deployment-name + type: string + - description: url of the git repo for the code of deployment + name: git-url + type: string + - default: pipelines-1.9 + description: revision to be used from repo of the code for deployment + name: git-revision + type: string + - description: image to be built from the code + name: IMAGE + type: string + tasks: + - name: fetch-repository + params: + - name: url + value: $(params.git-url) + - name: subdirectory + value: "" + - name: deleteExisting + value: "true" + - name: revision + value: $(params.git-revision) + taskRef: + kind: ClusterTask + name: git-clone + workspaces: + - name: output + workspace: shared-workspace + - name: build-image + params: + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: "false" + runAfter: + - fetch-repository + taskRef: + kind: ClusterTask + name: buildah + workspaces: + - name: source + workspace: shared-workspace + - name: deploy-image + params: + - name: script + value: > + curl https://raw.githubusercontent.com/apache/incubator-kie-kogito-serverless-operator/main/operator.yaml | sed -E 's|image: quay.io/kiegroup/.*|image: image-registry.openshift-image-registry.svc:5000/sonataflow-operator-system/kogito-serverless-operator:latest|g' | kubectl apply -f - + runAfter: + - build-image + taskRef: + kind: Task + name: kubernetes-actions + workspaces: + - name: shared-workspace diff --git a/packages/kogito-serverless-operator/tekton/pipeline/kogito_serverless_operator_pipeline_run.yaml b/packages/kogito-serverless-operator/tekton/pipeline/kogito_serverless_operator_pipeline_run.yaml new file mode 100644 index 00000000000..b09d1d876af --- /dev/null +++ b/packages/kogito-serverless-operator/tekton/pipeline/kogito_serverless_operator_pipeline_run.yaml @@ -0,0 +1,26 @@ +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + namespace: sonataflow-operator-system + generateName: kogito-serverless-operator-pipeline-run +spec: + workspaces: + - name: shared-workspace + volumeClaimTemplate: + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 500Mi + params: + - name: deployment-name + value: kogito-serverless-operator + - name: git-url + value: https://github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator.git + - name: git-revision + value: "main" + - name: IMAGE + value: "image-registry.openshift-image-registry.svc:5000/sonataflow-operator-system/kogito-serverless-operator:latest" + pipelineRef: + name: kogito-serverless-operator-pipeline diff --git a/packages/kogito-serverless-operator/tekton/role/cluster_role.yaml b/packages/kogito-serverless-operator/tekton/role/cluster_role.yaml new file mode 100644 index 00000000000..2b0d2ec9eab --- /dev/null +++ b/packages/kogito-serverless-operator/tekton/role/cluster_role.yaml @@ -0,0 +1,152 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: tekton-clustermanger-role +rules: + - apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + - clusterrolebindings + - roles + - rolebindings + - customresourcedefinitions + - configmaps + - deployments + - events + - namespaces + - nodes + - persistentvolumeclaims + - pods + - pods/exec + - secrets + - serviceaccounts + - services + - services/finalizers + - pods + - subjectaccessreviews + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: + - apiextensions.k8s.io + resources: + - clusterroles + - clusterrolebindings + - roles + - rolebindings + - customresourcedefinitions + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: + - sonataflow.org + resources: + - sonataflowbuilds + - sonataflowbuilds/status + - sonataflowplatforms + - sonataflowplatforms/finalizers + - sonataflowplatforms/status + - sonataflows + - sonataflows/finalizers + - sonataflows/status + - pods + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - configmaps + - deployments + - events + - namespaces + - nodes + - persistentvolumeclaims + - pods + - pods/exec + - secrets + - serviceaccounts + - services + - services/finalizers + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: + - "*" + resources: + - configmaps + - deployments + - events + - namespaces + - nodes + - persistentvolumeclaims + - pods + - pods/exec + - secrets + - serviceaccounts + - services + - services/finalizers + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - tokenreviews + - subjectaccessreviews + verbs: + - create + - nonResourceURLs: + - /metrics + verbs: + - get diff --git a/packages/kogito-serverless-operator/tekton/role/cluster_role_binding.yaml b/packages/kogito-serverless-operator/tekton/role/cluster_role_binding.yaml new file mode 100644 index 00000000000..ce887fda840 --- /dev/null +++ b/packages/kogito-serverless-operator/tekton/role/cluster_role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: tekton-clustermanger-role-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: tekton-clustermanger-role +subjects: + - kind: ServiceAccount + name: pipeline + namespace: sonataflow-operator-system diff --git a/packages/kogito-serverless-operator/tekton/task/show_workspace_content.yaml b/packages/kogito-serverless-operator/tekton/task/show_workspace_content.yaml new file mode 100644 index 00000000000..40d07b807e4 --- /dev/null +++ b/packages/kogito-serverless-operator/tekton/task/show_workspace_content.yaml @@ -0,0 +1,23 @@ +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: show-workspace +spec: + params: + - default: /workspace/source + description: The directory in source that contains yaml manifests + name: source + type: string + steps: + - args: + - "-c" + - | + set -ex + find /workspace + command: + - /bin/sh + image: alpine + name: dump-directory + resources: {} + workspaces: + - name: source diff --git a/packages/kogito-serverless-operator/tekton/trigger/trigger_binding.yaml b/packages/kogito-serverless-operator/tekton/trigger/trigger_binding.yaml new file mode 100644 index 00000000000..643cb4c44d7 --- /dev/null +++ b/packages/kogito-serverless-operator/tekton/trigger/trigger_binding.yaml @@ -0,0 +1,13 @@ +apiVersion: triggers.tekton.dev/v1beta1 +kind: TriggerBinding +metadata: + name: kogito-serverless-operator-trigger-binding + namespace: sonataflow-operator-system +spec: + params: + - name: git-repo-url + value: $(body.repository.url) + - name: git-repo-name + value: $(body.repository.name) + - name: git-revision + value: $(body.head_commit.id) diff --git a/packages/kogito-serverless-operator/tekton/trigger/trigger_event_listener.yaml b/packages/kogito-serverless-operator/tekton/trigger/trigger_event_listener.yaml new file mode 100644 index 00000000000..383860a129f --- /dev/null +++ b/packages/kogito-serverless-operator/tekton/trigger/trigger_event_listener.yaml @@ -0,0 +1,13 @@ +apiVersion: triggers.tekton.dev/v1alpha1 +kind: EventListener +metadata: + name: kogito-serverless-operator-webhook + namespace: sonataflow-operator-system +spec: + serviceAccountName: pipeline + triggers: + - name: kogito-serverless-operator-trigger-webhook + bindings: + - ref: kogito-serverless-operator-trigger-binding + template: + ref: kogito-serverless-operator-trigger-template diff --git a/packages/kogito-serverless-operator/tekton/trigger/trigger_resource.yaml b/packages/kogito-serverless-operator/tekton/trigger/trigger_resource.yaml new file mode 100644 index 00000000000..7ea8b39a2d0 --- /dev/null +++ b/packages/kogito-serverless-operator/tekton/trigger/trigger_resource.yaml @@ -0,0 +1,11 @@ +apiVersion: triggers.tekton.dev/v1beta1 +kind: Trigger +metadata: + name: kogito-serverless-operator-trigger + namespace: sonataflow-operator-system +spec: + serviceAccountName: pipeline + bindings: + - ref: kogito-serverless-operator-trigger-binding + template: + ref: kogito-serverless-operator-trigger-template diff --git a/packages/kogito-serverless-operator/tekton/trigger/trigger_template.yaml b/packages/kogito-serverless-operator/tekton/trigger/trigger_template.yaml new file mode 100644 index 00000000000..a7e55ac162a --- /dev/null +++ b/packages/kogito-serverless-operator/tekton/trigger/trigger_template.yaml @@ -0,0 +1,42 @@ +apiVersion: triggers.tekton.dev/v1beta1 +kind: TriggerTemplate +metadata: + name: kogito-serverless-operator-trigger-template + namespace: sonataflow-operator-system +spec: + params: + - name: git-repo-url + description: The git repository url + - name: git-revision + description: The git revision + default: pipelines-1.9 + - name: git-repo-name + description: The name of the deployment to be created / patched + + resourcetemplates: + - apiVersion: tekton.dev/v1beta1 + kind: PipelineRun + metadata: + generateName: build-deploy-$(tt.params.git-repo-name)- + spec: + serviceAccountName: pipeline + pipelineRef: + name: build-and-deploy + params: + - name: deployment-name + value: $(tt.params.git-repo-name) + - name: git-url + value: $(tt.params.git-repo-url) + - name: git-revision + value: $(tt.params.git-revision) + - name: IMAGE + value: image-registry.openshift-image-registry.svc:5000/sonataflow-operator-system/$(tt.params.git-repo-name) + workspaces: + - name: shared-workspace + volumeClaimTemplate: + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 500Mi diff --git a/packages/kogito-serverless-operator/tekton/trigger/webhook_event_listener_route.yaml b/packages/kogito-serverless-operator/tekton/trigger/webhook_event_listener_route.yaml new file mode 100644 index 00000000000..16bfe88e851 --- /dev/null +++ b/packages/kogito-serverless-operator/tekton/trigger/webhook_event_listener_route.yaml @@ -0,0 +1,14 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: kogito-serverless-operator-webhook-event-listener-route + namespace: sonataflow-operator-system +spec: + host: "" + port: + targetPort: 8080 + to: + kind: Service + name: el-kogito-serverless-operator-webhook + weight: 100 + wildcardPolicy: None diff --git a/packages/kogito-serverless-operator/tekton/volume/persistent_volume.yaml b/packages/kogito-serverless-operator/tekton/volume/persistent_volume.yaml new file mode 100644 index 00000000000..ecaad9142e2 --- /dev/null +++ b/packages/kogito-serverless-operator/tekton/volume/persistent_volume.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: source-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 500Mi diff --git a/packages/kogito-serverless-operator/test/builder/Dockerfile b/packages/kogito-serverless-operator/test/builder/Dockerfile new file mode 100644 index 00000000000..fac640c2fe4 --- /dev/null +++ b/packages/kogito-serverless-operator/test/builder/Dockerfile @@ -0,0 +1,49 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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 quay.io/kiegroup/kogito-swf-builder-nightly: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 . ./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/packages/kogito-serverless-operator/test/builder/greetings.sw.json b/packages/kogito-serverless-operator/test/builder/greetings.sw.json new file mode 100644 index 00000000000..a619b3b8bc7 --- /dev/null +++ b/packages/kogito-serverless-operator/test/builder/greetings.sw.json @@ -0,0 +1,67 @@ +{ + "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/packages/kogito-serverless-operator/test/e2e/clusterplatform_test.go b/packages/kogito-serverless-operator/test/e2e/clusterplatform_test.go new file mode 100644 index 00000000000..3df9a2b9b1c --- /dev/null +++ b/packages/kogito-serverless-operator/test/e2e/clusterplatform_test.go @@ -0,0 +1,294 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/platform/services" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/profiles/common/constants" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test/utils" + + //nolint:golint + //nolint:revive + . "github.com/onsi/ginkgo/v2" + + //nolint:golint + //nolint:revive + . "github.com/onsi/gomega" +) + +var _ = Describe("Validate a clusterplatform", Ordered, func() { + + var ( + projectDir string + targetNamespace string + targetNamespace2 string + ) + + BeforeEach(func() { + targetNamespace = fmt.Sprintf("test-%d", rand.Intn(1024)+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 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()) + } + } + }) + 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", filepath.Join(projectDir, + test.GetSonataFlowE2EPlatformServicesDirectory(), 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()) + + if withServices { + By("Deploy SonatatFlowPlatform 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("''"))) + + dataIndexServiceUrl := services.GenerateServiceURL(constants.KogitoServiceURLProtocol, targetNamespace2, "sonataflow-platform-"+constants.DataIndexServiceName) + jobServiceUrl := services.GenerateServiceURL(constants.KogitoServiceURLProtocol, targetNamespace2, "sonataflow-platform-"+constants.JobServiceName) + EventuallyWithOffset(1, func() []byte { + cmd = exec.Command("kubectl", "get", "sf", "-n", targetNamespace2, "callbackstatetimeouts", "-o", "jsonpath='{.status.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", "sf", "-n", targetNamespace2, "callbackstatetimeouts", "-o", "jsonpath='{.status.services.jobServiceRef.url}'") + returnedValue, _ := utils.Run(cmd) + return returnedValue + }, 20*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.KogitoServiceURLProtocol, targetNamespace, "sonataflow-platform-"+constants.DataIndexServiceName) + jobServiceUrl := services.GenerateServiceURL(constants.KogitoServiceURLProtocol, 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 + "'"))) + EventuallyWithOffset(1, func() []byte { + cmd = exec.Command("kubectl", "get", "sf", "-n", targetNamespace2, "callbackstatetimeouts", "-o", "jsonpath='{.status.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", "sf", "-n", targetNamespace2, "callbackstatetimeouts", "-o", "jsonpath='{.status.services.jobServiceRef.url}'") + returnedValue, _ := utils.Run(cmd) + return returnedValue + }, 20*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.GetSonataFlowE2EPlatformNoServicesDirectory(), metadata.PreviewProfile.String(), ephemeral, false), + Entry("with services configured", test.GetSonataFlowE2EPlatformServicesDirectory(), metadata.PreviewProfile.String(), "ephemeral-with-workflow", 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", filepath.Join(projectDir, + test.GetSonataFlowE2EPlatformServicesDirectory(), 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.GetSonataFlowE2EPlatformServicesDirectory(), metadata.PreviewProfile.String(), ephemeralDataIndex), + Entry("with only Job Service configured", test.GetSonataFlowE2EPlatformServicesDirectory(), metadata.PreviewProfile.String(), ephemeralJobService), + ) + }) +}) diff --git a/packages/kogito-serverless-operator/test/e2e/e2e_suite_test.go b/packages/kogito-serverless-operator/test/e2e/e2e_suite_test.go new file mode 100644 index 00000000000..25113c8fb4a --- /dev/null +++ b/packages/kogito-serverless-operator/test/e2e/e2e_suite_test.go @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "fmt" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +// Run e2e tests using the Ginkgo runner. +func TestE2E(t *testing.T) { + RegisterFailHandler(Fail) + fmt.Fprintf(GinkgoWriter, "Starting SonataFlow Operator suite\n") + RunSpecs(t, "SonataFlow e2e suite") +} diff --git a/packages/kogito-serverless-operator/test/e2e/helpers.go b/packages/kogito-serverless-operator/test/e2e/helpers.go new file mode 100644 index 00000000000..18b6e42996e --- /dev/null +++ b/packages/kogito-serverless-operator/test/e2e/helpers.go @@ -0,0 +1,159 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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" + "net/url" + "os/exec" + "strconv" + "strings" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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"` +} + +var ( + upStatus string = "UP" +) + +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] + } + fmt.Printf("Parsed following JSON object from health Endpoint response: %v\n", stringOutput) + err = json.Unmarshal([]byte(stringOutput), &h) + if err != nil { + return nil, fmt.Errorf("failed to execute curl command against health endpoint in container %s:%v with output %s", containerName, err, output) + } + GinkgoWriter.Println(fmt.Sprintf("Health status:\n%s", string(output))) + return &h, nil +} +func verifyWorkflowIsInRunningStateInNamespace(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 greeting workflow is running: %v", err)) + return false + } + GinkgoWriter.Println(fmt.Sprintf("Got response %s", response)) + + if len(strings.TrimSpace(string(response))) == 0 { + GinkgoWriter.Println(fmt.Errorf("empty response %v", err)) + return false + } + status, err := strconv.ParseBool(string(response)) + if err != nil { + GinkgoWriter.Println(fmt.Errorf("failed to parse result %v", err)) + return false + } + return status +} + +func verifyWorkflowIsInRunningState(workflowName string, targetNamespace string) bool { + return verifyWorkflowIsInRunningStateInNamespace(workflowName, targetNamespace) +} + +func verifyWorkflowIsAddressable(workflowName string, targetNamespace string) bool { + cmd := exec.Command("kubectl", "get", "workflow", workflowName, "-n", targetNamespace, "-o", "jsonpath={.status.address.url}") + if response, err := utils.Run(cmd); err != nil { + GinkgoWriter.Println(fmt.Errorf("failed to check if greeting workflow is running: %v", err)) + return false + } else { + GinkgoWriter.Println(fmt.Sprintf("Got response %s", response)) + if len(strings.TrimSpace(string(response))) > 0 { + _, err := url.ParseRequestURI(string(response)) + if err != nil { + GinkgoWriter.Println(fmt.Errorf("failed to parse result %v", err)) + return false + } + // The response is a valid URL so the test is passed + return true + } + return false + } +} diff --git a/packages/kogito-serverless-operator/test/e2e/platform_test.go b/packages/kogito-serverless-operator/test/e2e/platform_test.go new file mode 100644 index 00000000000..9f7210f7e30 --- /dev/null +++ b/packages/kogito-serverless-operator/test/e2e/platform_test.go @@ -0,0 +1,159 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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" + "path/filepath" + "strings" + "time" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test/utils" + + //nolint:golint + //nolint:revive + . "github.com/onsi/ginkgo/v2" + + //nolint:golint + //nolint:revive + . "github.com/onsi/gomega" +) + +const ( + ephemeral = "ephemeral" + postgreSQL = "postgreSQL" + clusterWideEphemeral = "cluster-wide-ephemeral" + ephemeralDataIndex = "ephemeral-data-index" + ephemeralJobService = "ephemeral-job-service" +) + +var _ = Describe("Validate the persistence", Ordered, func() { + + var ( + projectDir string + targetNamespace string + ) + + BeforeEach(func() { + targetNamespace = fmt.Sprintf("test-%d", rand.Intn(1024)+1) + cmd := exec.Command("kubectl", "create", "namespace", targetNamespace) + _, err := utils.Run(cmd) + Expect(err).NotTo(HaveOccurred()) + }) + AfterEach(func() { + // Remove resources in test namespace with no failure + if !CurrentSpecReport().Failed() && len(targetNamespace) > 0 { + cmd := exec.Command("kubectl", "delete", "namespace", targetNamespace, "--wait") + _, err := utils.Run(cmd) + Expect(err).NotTo(HaveOccurred()) + } + }) + var _ = Context("with platform services", func() { + + DescribeTable("when creating a simple workflow", 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", 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", 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() error { + cmd = exec.Command("kubectl", "wait", "pod", "-n", targetNamespace, "-l", "app=sonataflow-platform", "--for", "condition=Ready", "--timeout=5s") + _, err = utils.Run(cmd) + return err + }, 20*time.Minute, 5).Should(Succeed()) + By("Evaluate status of service's health endpoint") + cmd = exec.Command("kubectl", "get", "pod", "-l", "app=sonataflow-platform", "-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, 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), " ") + + By("Evaluate status of SonataFlow CR") + for _, sf := range strings.Split(string(sfNames), " ") { + Expect(sf).NotTo(BeEmpty(), "sonataflow name is empty") + EventuallyWithOffset(1, func() bool { + return verifyWorkflowIsInRunningStateInNamespace(sf, targetNamespace) + }, 10*time.Minute, 5).Should(BeTrue()) + } + }, + Entry("with both Job Service and Data Index and ephemeral persistence and the workflow in a dev profile", test.GetSonataFlowE2EPlatformServicesDirectory(), metadata.DevProfile.String(), ephemeral), + Entry("with both Job Service and Data Index and ephemeral persistence and the workflow in a preview profile", test.GetSonataFlowE2EPlatformServicesDirectory(), metadata.PreviewProfile.String(), ephemeral), + Entry("with both Job Service and Data Index and postgreSQL persistence and the workflow in a dev profile", test.GetSonataFlowE2EPlatformServicesDirectory(), metadata.DevProfile.String(), postgreSQL), + Entry("with both Job Service and Data Index and postgreSQL persistence and the workflow in a preview profile", test.GetSonataFlowE2EPlatformServicesDirectory(), metadata.PreviewProfile.String(), 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=sonataflow-platform", "--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=sonataflow-platform", "-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.GetSonataFlowE2EPlatformPersistenceSampleDataDirectory("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.GetSonataFlowE2EPlatformPersistenceSampleDataDirectory("overwritten_by_services")), + ) + +}) diff --git a/packages/kogito-serverless-operator/test/e2e/workflow_test.go b/packages/kogito-serverless-operator/test/e2e/workflow_test.go new file mode 100644 index 00000000000..a5908dfb245 --- /dev/null +++ b/packages/kogito-serverless-operator/test/e2e/workflow_test.go @@ -0,0 +1,227 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + "path/filepath" + "strings" + "time" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test/utils" + + //nolint:golint + //nolint:revive + . "github.com/onsi/ginkgo/v2" + + //nolint:golint + //nolint:revive + . "github.com/onsi/gomega" +) + +var _ = Describe("SonataFlow Operator", Ordered, func() { + + var targetNamespace string + BeforeEach(func() { + targetNamespace = fmt.Sprintf("test-%d", rand.Intn(1024)+1) + cmd := exec.Command("kubectl", "create", "namespace", targetNamespace) + _, err := utils.Run(cmd) + Expect(err).NotTo(HaveOccurred()) + }) + AfterEach(func() { + // Remove resources in test namespace + if !CurrentSpecReport().Failed() && len(targetNamespace) > 0 { + cmd := exec.Command("kubectl", "delete", "namespace", targetNamespace, "--wait") + _, err := utils.Run(cmd) + Expect(err).NotTo(HaveOccurred()) + } + }) + + Describe("ensure that Operator and Operand(s) can run in restricted namespaces", func() { + projectDir, _ := utils.GetProjectDir() + + It("should successfully deploy the Simple Workflow in GitOps mode and verify if it's running", func() { + By("creating an instance of the SonataFlow Operand(CR)") + EventuallyWithOffset(1, func() error { + cmd := exec.Command("kubectl", "apply", "-f", filepath.Join(projectDir, + "test/testdata/"+test.SonataFlowSimpleOpsYamlCR), "-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("simple", targetNamespace) }, 15*time.Minute, 30*time.Second).Should(BeTrue()) + + EventuallyWithOffset(1, func() error { + cmd := exec.Command("kubectl", "delete", "-f", filepath.Join(projectDir, + "test/testdata/"+test.SonataFlowSimpleOpsYamlCR), "-n", targetNamespace) + _, err := utils.Run(cmd) + return err + }, 3*time.Minute, time.Second).Should(Succeed()) + }) + + It("should successfully deploy the Greeting Workflow in preview mode and verify if it's running", func() { + By("creating external resources DataInputSchema configMap") + EventuallyWithOffset(1, func() error { + cmd := exec.Command("kubectl", "apply", "-f", filepath.Join(projectDir, + "test/testdata/"+test.SonataFlowGreetingsDataInputSchemaConfig), "-n", targetNamespace) + _, err := utils.Run(cmd) + return err + }, 3*time.Minute, time.Second).Should(Succeed()) + + By("creating an instance of the SonataFlow Operand(CR)") + EventuallyWithOffset(1, func() error { + cmd := exec.Command("kubectl", "apply", "-f", filepath.Join(projectDir, + "test/testdata/"+test.SonataFlowGreetingsWithDataInputSchemaCR), "-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", filepath.Join(projectDir, + "test/testdata/"+test.SonataFlowGreetingsWithDataInputSchemaCR), "-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() { + + By("creating an instance of the SonataFlow Workflow in DevMode") + EventuallyWithOffset(1, func() error { + cmd := exec.Command("kubectl", "apply", "-f", filepath.Join(projectDir, + test.GetSonataFlowE2eOrderProcessingFolder()), "-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", filepath.Join(projectDir, + test.GetSonataFlowE2eOrderProcessingFolder()), "-n", targetNamespace) + _, err := utils.Run(cmd) + return err + }, 3*time.Minute, time.Second).Should(Succeed()) + }) + + }) + +}) + +var _ = Describe("Validate the persistence ", Ordered, func() { + + const ( + dbConnectionName = "Database connections health check" + defaultDataCheck = "" + ) + var ( + ns string + ) + + BeforeEach(func() { + ns = fmt.Sprintf("test-%d", rand.Intn(1024)+1) + cmd := exec.Command("kubectl", "create", "namespace", ns) + _, err := utils.Run(cmd) + Expect(err).NotTo(HaveOccurred()) + }) + AfterEach(func() { + // Remove platform CR if it exists + if len(ns) > 0 { + 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) { + 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("Wait for SonatatFlow CR to complete deployment") + // wait for service deployments to be ready + EventuallyWithOffset(1, func() error { + cmd = exec.Command("kubectl", "wait", "pod", "-n", ns, "-l", "sonataflow.org/workflow-app", "--for", "condition=Ready", "--timeout=5s") + out, err := utils.Run(cmd) + GinkgoWriter.Printf("%s\n", string(out)) + return err + }, 12*time.Minute, 5).Should(Succeed()) + + By("Evaluate status of the workflow's pod database connection health endpoint") + cmd = exec.Command("kubectl", "get", "pod", "-l", "sonataflow.org/workflow-app", "-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") + for _, c := range h.Checks { + if c.Name == dbConnectionName { + Expect(c.Status).To(Equal(upStatus), "Pod's database connection is not UP") + if withPersistence { + Expect(c.Data[defaultDataCheck]).To(Equal(upStatus), "Pod's 'default' database data is not UP") + return true + } else { + Expect(defaultDataCheck).NotTo(BeElementOf(c.Data), "Pod's 'default' database data check exists in health manifest") + return true + } + } + } + } + return false + }, 1*time.Minute).Should(BeTrue()) + }, + Entry("defined in the workflow from an existing kubernetes service as a reference", test.GetSonataFlowE2EWorkflowPersistenceSampleDataDirectory("by_service"), true), + Entry("defined in the workflow and from the sonataflow platform", test.GetSonataFlowE2EWorkflowPersistenceSampleDataDirectory("from_platform_overwritten_by_service"), true), + Entry("defined from the sonataflow platform as reference and with DI and JS", test.GetSonataFlowE2EWorkflowPersistenceSampleDataDirectory("from_platform_with_di_and_js_services"), true), + Entry("defined from the sonataflow platform as reference and without DI and JS", test.GetSonataFlowE2EWorkflowPersistenceSampleDataDirectory("from_platform_without_di_and_js_services"), true), + Entry("defined from the sonataflow platform as reference but not required by the workflow", test.GetSonataFlowE2EWorkflowPersistenceSampleDataDirectory("from_platform_with_no_persistence_required"), false), + ) + +}) diff --git a/packages/kogito-serverless-operator/test/kubernetes_cli.go b/packages/kogito-serverless-operator/test/kubernetes_cli.go new file mode 100644 index 00000000000..fd2ebd6561a --- /dev/null +++ b/packages/kogito-serverless-operator/test/kubernetes_cli.go @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + 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/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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" +) + +func NewFakeRecorder() record.EventRecorder { + return record.NewFakeRecorder(10) +} + +// NewSonataFlowClientBuilder creates a new fake.ClientBuilder with the right scheme references +func NewSonataFlowClientBuilder() *fake.ClientBuilder { + s := scheme.Scheme + utilruntime.Must(operatorapi.AddToScheme(s)) + return fake.NewClientBuilder().WithScheme(s) +} + +// NewKogitoClientBuilderWithOpenShift creates a new fake client with OpenShift schemas. +// If your object is not present, just add in the list below. +func NewKogitoClientBuilderWithOpenShift() *fake.ClientBuilder { + s := scheme.Scheme + utilruntime.Must(routev1.Install(s)) + utilruntime.Must(buildv1.Install(s)) + utilruntime.Must(imgv1.Install(s)) + utilruntime.Must(operatorapi.AddToScheme(s)) + return fake.NewClientBuilder().WithScheme(s) +} + +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/packages/kogito-serverless-operator/test/mock_service.go b/packages/kogito-serverless-operator/test/mock_service.go new file mode 100644 index 00000000000..2003c5d6c21 --- /dev/null +++ b/packages/kogito-serverless-operator/test/mock_service.go @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/test/testdata/order-processing/01_v1_configmap_subflows.yaml b/packages/kogito-serverless-operator/test/testdata/order-processing/01_v1_configmap_subflows.yaml new file mode 100644 index 00000000000..fe896c10bfd --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/order-processing/01_v1_configmap_subflows.yaml @@ -0,0 +1,85 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/test/testdata/order-processing/02_appsv1_deployment_eventlistener.yaml b/packages/kogito-serverless-operator/test/testdata/order-processing/02_appsv1_deployment_eventlistener.yaml new file mode 100644 index 00000000000..b9b810b355c --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/order-processing/02_appsv1_deployment_eventlistener.yaml @@ -0,0 +1,60 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/test/testdata/order-processing/03_discovery_role.yaml b/packages/kogito-serverless-operator/test/testdata/order-processing/03_discovery_role.yaml new file mode 100644 index 00000000000..5c35ab6a8e9 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/order-processing/03_discovery_role.yaml @@ -0,0 +1,78 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/test/testdata/order-processing/04_v1_configmap_properties.yaml b/packages/kogito-serverless-operator/test/testdata/order-processing/04_v1_configmap_properties.yaml new file mode 100644 index 00000000000..5392bd27277 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/order-processing/04_v1_configmap_properties.yaml @@ -0,0 +1,25 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/test/testdata/order-processing/05_sonataflow.org_v1alpha08_sonataflow_devmode_orderprocessing.yaml b/packages/kogito-serverless-operator/test/testdata/order-processing/05_sonataflow.org_v1alpha08_sonataflow_devmode_orderprocessing.yaml new file mode 100644 index 00000000000..b8cae65cf0a --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/order-processing/05_sonataflow.org_v1alpha08_sonataflow_devmode_orderprocessing.yaml @@ -0,0 +1,56 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/test/testdata/order-processing/README.md b/packages/kogito-serverless-operator/test/testdata/order-processing/README.md new file mode 100644 index 00000000000..450761ded10 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/order-processing/README.md @@ -0,0 +1,3 @@ +# Order Processing Example + +See: https://github.com/kiegroup/kogito-examples/tree/main/serverless-workflow-examples/serverless-workflow-order-processing diff --git a/packages/kogito-serverless-operator/test/testdata/platform/noservices/preview/ephemeral/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/platform/noservices/preview/ephemeral/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..87d5297b40d --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/noservices/preview/ephemeral/02-sonataflow_platform.yaml @@ -0,0 +1,27 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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:999-SNAPSHOT + config: + strategyOptions: + KanikoBuildCacheEnabled: "true" diff --git a/packages/kogito-serverless-operator/test/testdata/platform/noservices/preview/ephemeral/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/platform/noservices/preview/ephemeral/kustomization.yaml new file mode 100644 index 00000000000..c078452270e --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/noservices/preview/ephemeral/kustomization.yaml @@ -0,0 +1,20 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 + - sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml + +sortOptions: + order: fifo diff --git a/packages/kogito-serverless-operator/test/testdata/platform/noservices/preview/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/packages/kogito-serverless-operator/test/testdata/platform/noservices/preview/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml new file mode 100644 index 00000000000..0709fbe9bc8 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/noservices/preview/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml @@ -0,0 +1,81 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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: prod +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/packages/kogito-serverless-operator/test/testdata/platform/persistence/generic_from_platform_cr/01-postgres.yaml b/packages/kogito-serverless-operator/test/testdata/platform/persistence/generic_from_platform_cr/01-postgres.yaml new file mode 100644 index 00000000000..be063351636 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/persistence/generic_from_platform_cr/01-postgres.yaml @@ -0,0 +1,86 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/persistence/generic_from_platform_cr/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/platform/persistence/generic_from_platform_cr/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..6d7dae7ff98 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/persistence/generic_from_platform_cr/02-sonataflow_platform.yaml @@ -0,0 +1,56 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 + 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 + 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/packages/kogito-serverless-operator/test/testdata/platform/persistence/generic_from_platform_cr/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/platform/persistence/generic_from_platform_cr/kustomization.yaml new file mode 100644 index 00000000000..fb6f456cee8 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/persistence/generic_from_platform_cr/kustomization.yaml @@ -0,0 +1,31 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/persistence/overwritten_by_services/01-postgres.yaml b/packages/kogito-serverless-operator/test/testdata/platform/persistence/overwritten_by_services/01-postgres.yaml new file mode 100644 index 00000000000..be063351636 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/persistence/overwritten_by_services/01-postgres.yaml @@ -0,0 +1,86 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/persistence/overwritten_by_services/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/platform/persistence/overwritten_by_services/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..8a9323fb9b6 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/persistence/overwritten_by_services/02-sonataflow_platform.yaml @@ -0,0 +1,74 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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: + 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: + 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/packages/kogito-serverless-operator/test/testdata/platform/persistence/overwritten_by_services/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/platform/persistence/overwritten_by_services/kustomization.yaml new file mode 100644 index 00000000000..fb6f456cee8 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/persistence/overwritten_by_services/kustomization.yaml @@ -0,0 +1,31 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/services/dev/ephemeral/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/ephemeral/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..a1fb788af32 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/ephemeral/02-sonataflow_platform.yaml @@ -0,0 +1,32 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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:999-SNAPSHOT + config: + strategyOptions: + KanikoBuildCacheEnabled: "true" + services: + dataIndex: + enabled: false + jobService: + enabled: false diff --git a/packages/kogito-serverless-operator/test/testdata/platform/services/dev/ephemeral/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/ephemeral/kustomization.yaml new file mode 100644 index 00000000000..81eb1865fff --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/ephemeral/kustomization.yaml @@ -0,0 +1,19 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/services/dev/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml new file mode 100644 index 00000000000..ec571780a0d --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml @@ -0,0 +1,81 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/services/dev/postgreSQL/01-postgres.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/postgreSQL/01-postgres.yaml new file mode 100644 index 00000000000..be063351636 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/postgreSQL/01-postgres.yaml @@ -0,0 +1,86 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/services/dev/postgreSQL/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/postgreSQL/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..6eea798bca6 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/postgreSQL/02-sonataflow_platform.yaml @@ -0,0 +1,65 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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:999-SNAPSHOT + services: + dataIndex: + enabled: false + persistence: + 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: + 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/packages/kogito-serverless-operator/test/testdata/platform/services/dev/postgreSQL/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/postgreSQL/kustomization.yaml new file mode 100644 index 00000000000..fb6f456cee8 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/postgreSQL/kustomization.yaml @@ -0,0 +1,31 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/services/dev/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml new file mode 100644 index 00000000000..ec571780a0d --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/dev/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml @@ -0,0 +1,81 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/services/preview/cluster-wide-ephemeral/01-sonataflow_clusterplatform.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/cluster-wide-ephemeral/01-sonataflow_clusterplatform.yaml new file mode 100644 index 00000000000..57e9735dbea --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/cluster-wide-ephemeral/01-sonataflow_clusterplatform.yaml @@ -0,0 +1,25 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/services/preview/cluster-wide-ephemeral/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/cluster-wide-ephemeral/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..6cdf1d697b8 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/cluster-wide-ephemeral/02-sonataflow_platform.yaml @@ -0,0 +1,32 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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:999-SNAPSHOT + config: + strategyOptions: + KanikoBuildCacheEnabled: "true" + services: + dataIndex: + enabled: true + jobService: + enabled: true diff --git a/packages/kogito-serverless-operator/test/testdata/platform/services/preview/cluster-wide-ephemeral/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/cluster-wide-ephemeral/kustomization.yaml new file mode 100644 index 00000000000..da530c5f4ea --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/cluster-wide-ephemeral/kustomization.yaml @@ -0,0 +1,17 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-data-index/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-data-index/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..6377a731e63 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-data-index/02-sonataflow_platform.yaml @@ -0,0 +1,30 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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:999-SNAPSHOT + config: + strategyOptions: + KanikoBuildCacheEnabled: "true" + services: + dataIndex: + enabled: false diff --git a/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-data-index/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-data-index/kustomization.yaml new file mode 100644 index 00000000000..c078452270e --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-data-index/kustomization.yaml @@ -0,0 +1,20 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 + - sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml + +sortOptions: + order: fifo diff --git a/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-data-index/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-data-index/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml new file mode 100644 index 00000000000..0709fbe9bc8 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-data-index/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml @@ -0,0 +1,81 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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: prod +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/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-job-service/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-job-service/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..a61ac76dd72 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-job-service/02-sonataflow_platform.yaml @@ -0,0 +1,30 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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:999-SNAPSHOT + config: + strategyOptions: + KanikoBuildCacheEnabled: "true" + services: + jobService: + enabled: false diff --git a/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-job-service/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-job-service/kustomization.yaml new file mode 100644 index 00000000000..c078452270e --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-job-service/kustomization.yaml @@ -0,0 +1,20 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 + - sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml + +sortOptions: + order: fifo diff --git a/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-job-service/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-job-service/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml new file mode 100644 index 00000000000..0709fbe9bc8 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-job-service/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml @@ -0,0 +1,81 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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: prod +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/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-with-workflow/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-with-workflow/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..52b7d11f715 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-with-workflow/02-sonataflow_platform.yaml @@ -0,0 +1,28 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-with-workflow/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-with-workflow/kustomization.yaml new file mode 100644 index 00000000000..c078452270e --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-with-workflow/kustomization.yaml @@ -0,0 +1,20 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 + - sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml + +sortOptions: + order: fifo diff --git a/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-with-workflow/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-with-workflow/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml new file mode 100644 index 00000000000..0709fbe9bc8 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral-with-workflow/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml @@ -0,0 +1,81 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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: prod +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/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..52b7d11f715 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral/02-sonataflow_platform.yaml @@ -0,0 +1,28 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral/kustomization.yaml new file mode 100644 index 00000000000..81eb1865fff --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral/kustomization.yaml @@ -0,0 +1,19 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml new file mode 100644 index 00000000000..ff075a4a329 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/ephemeral/sonataflow/03-sonataflow_callbackstatetimeouts.sw.yaml @@ -0,0 +1,81 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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: + 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/packages/kogito-serverless-operator/test/testdata/platform/services/preview/postgreSQL/01-postgres.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/postgreSQL/01-postgres.yaml new file mode 100644 index 00000000000..be063351636 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/postgreSQL/01-postgres.yaml @@ -0,0 +1,86 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/services/preview/postgreSQL/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/postgreSQL/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..a6e02588c58 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/postgreSQL/02-sonataflow_platform.yaml @@ -0,0 +1,64 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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: + 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: + 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/packages/kogito-serverless-operator/test/testdata/platform/services/preview/postgreSQL/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/postgreSQL/kustomization.yaml new file mode 100644 index 00000000000..fb6f456cee8 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/postgreSQL/kustomization.yaml @@ -0,0 +1,31 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/platform/services/preview/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml new file mode 100644 index 00000000000..ff075a4a329 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/platform/services/preview/postgreSQL/sonataflow/04-sonataflow_callbackstatetimeouts.sw.yaml @@ -0,0 +1,81 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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: + 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/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow-metainf.yaml b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow-metainf.yaml new file mode 100644 index 00000000000..c77ed6b3bb1 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow-metainf.yaml @@ -0,0 +1,62 @@ +# Copyright 2023 Red Hat, Inc. and/or its affiliates +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow-simpleops.yaml b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow-simpleops.yaml new file mode 100644 index 00000000000..d55f427f168 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow-simpleops.yaml @@ -0,0 +1,36 @@ +# Copyright 2023 Red Hat, Inc. and/or its affiliates +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 + app: not-simple +spec: + podTemplate: + container: + image: quay.io/kiegroup/sonataflow-minimal-example:latest + flow: + start: HelloWorld + states: + - name: HelloWorld + type: inject + data: + message: Hello World + end: true diff --git a/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow.yaml b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow.yaml new file mode 100644 index 00000000000..57c3387fe57 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow.yaml @@ -0,0 +1,61 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode.yaml b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode.yaml new file mode 100644 index 00000000000..591163fed57 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode.yaml @@ -0,0 +1,60 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode_events_http.yaml b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode_events_http.yaml new file mode 100644 index 00000000000..0813a0a1115 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow_devmode_events_http.yaml @@ -0,0 +1,65 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow_greetings_datainput.yaml b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow_greetings_datainput.yaml new file mode 100644 index 00000000000..7bc4c925f8a --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow_greetings_datainput.yaml @@ -0,0 +1,66 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow_vet_event.yaml b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow_vet_event.yaml new file mode 100644 index 00000000000..05e3a5b422b --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflow_vet_event.yaml @@ -0,0 +1,72 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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 + 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/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowbuild.yaml b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowbuild.yaml new file mode 100644 index 00000000000..9b018ec72a1 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowbuild.yaml @@ -0,0 +1,50 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: 10.100.163.129/greeting:0.0.1 + 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/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml new file mode 100644 index 00000000000..57e9735dbea --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml @@ -0,0 +1,25 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform.yaml b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform.yaml new file mode 100644 index 00000000000..39c5f1c1448 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform.yaml @@ -0,0 +1,31 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: + registry: + address: quay.io/kiegroup + secret: regcred diff --git a/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_openshift.yaml b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_openshift.yaml new file mode 100644 index 00000000000..d0add9fb045 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_openshift.yaml @@ -0,0 +1,25 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_withCache_minikube.yaml b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_withCache_minikube.yaml new file mode 100644 index 00000000000..76a1e026b2a --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/sonataflow.org_v1alpha08_sonataflowplatform_withCache_minikube.yaml @@ -0,0 +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. + +apiVersion: sonataflow.org/v1alpha08 +kind: SonataFlowPlatform +metadata: + name: sonataflow-platform +spec: + build: + config: + baseImage: quay.io/kiegroup/kogito-swf-builder-nightly:latest + strategyOptions: + KanikoBuildCacheEnabled: "true" diff --git a/packages/kogito-serverless-operator/test/testdata/v1_configmap_greetings_datainput.yaml b/packages/kogito-serverless-operator/test/testdata/v1_configmap_greetings_datainput.yaml new file mode 100644 index 00000000000..b11f0c4f2b0 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/v1_configmap_greetings_datainput.yaml @@ -0,0 +1,39 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/test/testdata/v1_configmap_greetings_staticfiles.yaml b/packages/kogito-serverless-operator/test/testdata/v1_configmap_greetings_staticfiles.yaml new file mode 100644 index 00000000000..418ef87af9b --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/v1_configmap_greetings_staticfiles.yaml @@ -0,0 +1,24 @@ +# Copyright 2023 Red Hat, Inc. and/or its affiliates +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/by_service/01-postgres.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/by_service/01-postgres.yaml new file mode 100644 index 00000000000..be063351636 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/by_service/01-postgres.yaml @@ -0,0 +1,86 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/by_service/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/by_service/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..84a94217910 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/by_service/02-sonataflow_platform.yaml @@ -0,0 +1,27 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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:kie-addons-quarkus-persistence-jdbc:999-SNAPSHOT,io.quarkus:quarkus-jdbc-postgresql:3.2.9.Final,io.quarkus:quarkus-agroal:3.2.9.Final + config: + strategyOptions: + KanikoBuildCacheEnabled: "true" diff --git a/packages/kogito-serverless-operator/test/testdata/workflow/persistence/by_service/03-sonataflow_callbackstatetimeouts.sw.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/by_service/03-sonataflow_callbackstatetimeouts.sw.yaml new file mode 100644 index 00000000000..157e4bd84d6 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/by_service/03-sonataflow_callbackstatetimeouts.sw.yaml @@ -0,0 +1,106 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 +spec: + persistence: + postgresql: + secretRef: + name: postgres-secrets + userKey: POSTGRES_USER + passwordKey: POSTGRES_PASSWORD + serviceRef: + name: postgres + port: 5432 + databaseName: sonataflow + databaseSchema: callbackstatetimeouts + podTemplate: + 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/by_service/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/by_service/kustomization.yaml new file mode 100644 index 00000000000..0a5a33a92b7 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/by_service/kustomization.yaml @@ -0,0 +1,32 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_overwritten_by_service/01-postgres.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_overwritten_by_service/01-postgres.yaml new file mode 100644 index 00000000000..be063351636 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_overwritten_by_service/01-postgres.yaml @@ -0,0 +1,86 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_overwritten_by_service/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_overwritten_by_service/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..5e692ea2447 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_overwritten_by_service/02-sonataflow_platform.yaml @@ -0,0 +1,37 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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: + template: + buildArgs: + - name: QUARKUS_EXTENSIONS + value: org.kie:kie-addons-quarkus-persistence-jdbc:999-SNAPSHOT,io.quarkus:quarkus-jdbc-postgresql:3.2.9.Final,io.quarkus:quarkus-agroal:3.2.9.Final + config: + strategyOptions: + KanikoBuildCacheEnabled: "true" diff --git a/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_overwritten_by_service/03-sonataflow_callbackstatetimeouts.sw.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_overwritten_by_service/03-sonataflow_callbackstatetimeouts.sw.yaml new file mode 100644 index 00000000000..157e4bd84d6 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_overwritten_by_service/03-sonataflow_callbackstatetimeouts.sw.yaml @@ -0,0 +1,106 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 +spec: + persistence: + postgresql: + secretRef: + name: postgres-secrets + userKey: POSTGRES_USER + passwordKey: POSTGRES_PASSWORD + serviceRef: + name: postgres + port: 5432 + databaseName: sonataflow + databaseSchema: callbackstatetimeouts + podTemplate: + 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_overwritten_by_service/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_overwritten_by_service/kustomization.yaml new file mode 100644 index 00000000000..0a5a33a92b7 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_overwritten_by_service/kustomization.yaml @@ -0,0 +1,32 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_di_and_js_services/01-postgres.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_di_and_js_services/01-postgres.yaml new file mode 100644 index 00000000000..be063351636 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_di_and_js_services/01-postgres.yaml @@ -0,0 +1,86 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_di_and_js_services/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_di_and_js_services/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..7d57abc851f --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_di_and_js_services/02-sonataflow_platform.yaml @@ -0,0 +1,64 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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: + template: + buildArgs: + - name: QUARKUS_EXTENSIONS + value: org.kie:kie-addons-quarkus-persistence-jdbc:999-SNAPSHOT,io.quarkus:quarkus-jdbc-postgresql:3.2.9.Final,io.quarkus:quarkus-agroal:3.2.9.Final + config: + strategyOptions: + KanikoBuildCacheEnabled: "true" + services: + dataIndex: + enabled: true + 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 + 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_di_and_js_services/03-sonataflow_callbackstatetimeouts.sw.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_di_and_js_services/03-sonataflow_callbackstatetimeouts.sw.yaml new file mode 100644 index 00000000000..2f9c7d51768 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_di_and_js_services/03-sonataflow_callbackstatetimeouts.sw.yaml @@ -0,0 +1,85 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 +spec: + podTemplate: + 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_di_and_js_services/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_di_and_js_services/kustomization.yaml new file mode 100644 index 00000000000..0a5a33a92b7 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_di_and_js_services/kustomization.yaml @@ -0,0 +1,32 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_no_persistence_required/01-postgres.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_no_persistence_required/01-postgres.yaml new file mode 100644 index 00000000000..be063351636 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_no_persistence_required/01-postgres.yaml @@ -0,0 +1,86 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_no_persistence_required/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_no_persistence_required/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..78dd85dc3d7 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_no_persistence_required/02-sonataflow_platform.yaml @@ -0,0 +1,37 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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: + template: + buildArgs: + - name: QUARKUS_EXTENSIONS + value: org.kie:kie-addons-quarkus-persistence-jdbc:999-SNAPSHOT,io.quarkus:quarkus-jdbc-postgresql:3.2.9.Final,io.quarkus:quarkus-agroal:3.2.9.Final + config: + strategyOptions: + KanikoBuildCacheEnabled: "true" diff --git a/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_no_persistence_required/03-sonataflow_callbackstatetimeouts-no-persistence.sw.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_no_persistence_required/03-sonataflow_callbackstatetimeouts-no-persistence.sw.yaml new file mode 100644 index 00000000000..f690120733b --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_no_persistence_required/03-sonataflow_callbackstatetimeouts-no-persistence.sw.yaml @@ -0,0 +1,86 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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-no-persistence + annotations: + sonataflow.org/description: Callback State Timeouts Example k8s + sonataflow.org/version: 0.0.1 +spec: + persistence: {} + podTemplate: + 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_no_persistence_required/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_no_persistence_required/kustomization.yaml new file mode 100644 index 00000000000..91d6cec06a5 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_with_no_persistence_required/kustomization.yaml @@ -0,0 +1,32 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_without_di_and_js_services/01-postgres.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_without_di_and_js_services/01-postgres.yaml new file mode 100644 index 00000000000..be063351636 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_without_di_and_js_services/01-postgres.yaml @@ -0,0 +1,86 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_without_di_and_js_services/02-sonataflow_platform.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_without_di_and_js_services/02-sonataflow_platform.yaml new file mode 100644 index 00000000000..78dd85dc3d7 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_without_di_and_js_services/02-sonataflow_platform.yaml @@ -0,0 +1,37 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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: + template: + buildArgs: + - name: QUARKUS_EXTENSIONS + value: org.kie:kie-addons-quarkus-persistence-jdbc:999-SNAPSHOT,io.quarkus:quarkus-jdbc-postgresql:3.2.9.Final,io.quarkus:quarkus-agroal:3.2.9.Final + config: + strategyOptions: + KanikoBuildCacheEnabled: "true" diff --git a/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_without_di_and_js_services/03-sonataflow_callbackstatetimeouts.sw.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_without_di_and_js_services/03-sonataflow_callbackstatetimeouts.sw.yaml new file mode 100644 index 00000000000..2f9c7d51768 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_without_di_and_js_services/03-sonataflow_callbackstatetimeouts.sw.yaml @@ -0,0 +1,85 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 +spec: + podTemplate: + 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/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_without_di_and_js_services/kustomization.yaml b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_without_di_and_js_services/kustomization.yaml new file mode 100644 index 00000000000..0a5a33a92b7 --- /dev/null +++ b/packages/kogito-serverless-operator/test/testdata/workflow/persistence/from_platform_without_di_and_js_services/kustomization.yaml @@ -0,0 +1,32 @@ +# Copyright 2024 Apache Software Foundation (ASF) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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/packages/kogito-serverless-operator/test/utils/utils.go b/packages/kogito-serverless-operator/test/utils/utils.go new file mode 100644 index 00000000000..25a58df0d1a --- /dev/null +++ b/packages/kogito-serverless-operator/test/utils/utils.go @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + "fmt" + "os" + "os/exec" + "strconv" + "strings" + + . "github.com/onsi/ginkgo/v2" //nolint:golint,revive +) + +func warnError(err error) { + fmt.Fprintf(GinkgoWriter, "warning: %v\n", err) +} + +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 +} + +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 +} + +// Run executes the provided command within this context +func Run(cmd *exec.Cmd) ([]byte, error) { + dir, _ := GetProjectDir() + cmd.Dir = dir + fmt.Fprintf(GinkgoWriter, "running dir: %s\n", cmd.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 { + fmt.Fprintf(GinkgoWriter, "chdir dir: %s\n", err) + } + + cmd.Env = append(os.Environ(), "GO111MODULE=on") + command := strings.Join(cmd.Args, " ") + fmt.Fprintf(GinkgoWriter, "running: %s\n", command) + output, err := cmd.CombinedOutput() + if err != nil { + return output, fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) + } + + return output, nil +} + +// GetNonEmptyLines converts given command output string into individual objects +// according to line breakers, and ignores the empty elements in it. +func GetNonEmptyLines(output string) []string { + var res []string + elements := strings.Split(output, "\n") + for _, element := range elements { + if element != "" { + res = append(res, element) + } + } + + return res +} + +// GetProjectDir will return the directory where the project is +func GetProjectDir() (string, error) { + wd, err := os.Getwd() + if err != nil { + return wd, err + } + wd = strings.Replace(wd, "/test/e2e", "", -1) + 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()) + } + err = scanner.Err() + return +} + +// 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") + } +} + +// IsDebugEnabled ... +func IsDebugEnabled() bool { + if v, ok := os.LookupEnv("DEBUG"); ok { + if debug, err := strconv.ParseBool(v); err == nil { + return debug + } + } + return false +} diff --git a/packages/kogito-serverless-operator/test/yaml.go b/packages/kogito-serverless-operator/test/yaml.go new file mode 100644 index 00000000000..97c74ca8872 --- /dev/null +++ b/packages/kogito-serverless-operator/test/yaml.go @@ -0,0 +1,311 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "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/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + sonataFlowOrderProcessingFolder = "order-processing" + 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" + sonataFlowPlatformWithCacheMinikubeYamlCR = "sonataflow.org_v1alpha08_sonataflowplatform_withCache_minikube.yaml" + sonataFlowPlatformForOpenshift = "sonataflow.org_v1alpha08_sonataflowplatform_openshift.yaml" + sonataFlowClusterPlatformYamlCR = "sonataflow.org_v1alpha08_sonataflowclusterplatform.yaml" + sonataFlowBuilderConfig = "sonataflow-operator-builder-config_v1_configmap.yaml" + sonataFlowBuildSucceed = "sonataflow.org_v1alpha08_sonataflowbuild.yaml" + + e2eSamples = "test/testdata/" + manifestsPath = "bundle/manifests/" +) + +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 + 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 { + cm := &corev1.ConfigMap{} + yamlFile, err := os.ReadFile(path.Join(getBundleDir(), sonataFlowBuilderConfig)) + if err != nil { + klog.V(log.E).ErrorS(err, "yamlFile.Get") + panic(err) + } + err = yaml.NewYAMLOrJSONDecoder(bytes.NewReader(yamlFile), 100).Decode(cm) + if err != nil { + klog.V(log.E).ErrorS(err, "Unmarshal") + panic(err) + } + cm.Namespace = namespace + 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 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) +} + +// GetBaseSonataFlowWithProdOpsProfile gets a base workflow that has a pre-built image set in podTemplate. +func GetBaseSonataFlowWithProdOpsProfile(namespace string) *operatorapi.SonataFlow { + return NewSonataFlow(SonataFlowSimpleOpsYamlCR, namespace) +} + +func GetBaseClusterPlatformInReadyPhase(namespace string) *operatorapi.SonataFlowClusterPlatform { + return GetSonataFlowClusterPlatformInReadyPhase(sonataFlowClusterPlatformYamlCR, namespace) +} + +func GetBasePlatformInReadyPhase(namespace string) *operatorapi.SonataFlowPlatform { + return GetSonataFlowPlatformInReadyPhase(sonataFlowPlatformYamlCR, namespace) +} + +func GetBasePlatformWithBaseImageInReadyPhase(namespace string) *operatorapi.SonataFlowPlatform { + platform := GetBasePlatform() + platform.Namespace = namespace + platform.Status.Manager().MarkTrue(api.SucceedConditionType) + platform.Spec.Build.Config.BaseImage = "quay.io/customx/custom-swf-builder:24.8.17" + return platform +} + +func GetBasePlatformWithDevBaseImageInReadyPhase(namespace string) *operatorapi.SonataFlowPlatform { + platform := GetBasePlatform() + platform.Namespace = namespace + platform.Status.Manager().MarkTrue(api.SucceedConditionType) + platform.Spec.DevMode.BaseImage = "quay.io/customgroup/custom-swf-builder-nightly:42.43.7" + return platform +} + +func GetBasePlatform() *operatorapi.SonataFlowPlatform { + return getSonataFlowPlatform(sonataFlowPlatformYamlCR) +} + +func GetPlatformMinikubeE2eTest() string { + return e2eSamples + sonataFlowPlatformWithCacheMinikubeYamlCR +} + +func GetPlatformOpenshiftE2eTest() string { + return e2eSamples + sonataFlowPlatformForOpenshift +} + +func GetSonataFlowE2eOrderProcessingFolder() string { + return e2eSamples + sonataFlowOrderProcessingFolder +} + +func GetSonataFlowE2EPlatformServicesDirectory() string { + return filepath.Join(getTestDataDir(), "platform", "services") +} + +func GetSonataFlowE2EPlatformNoServicesDirectory() string { + return filepath.Join(getTestDataDir(), "platform", "noservices") +} + +func GetSonataFlowE2EPlatformPersistenceSampleDataDirectory(subdir string) string { + return filepath.Join(getTestDataDir(), "platform", "persistence", subdir) +} + +func GetSonataFlowE2EWorkflowPersistenceSampleDataDirectory(subdir string) string { + return filepath.Join(getTestDataDir(), "workflow", "persistence", subdir) +} + +// 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 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 +} diff --git a/packages/kogito-serverless-operator/testbdd/Makefile b/packages/kogito-serverless-operator/testbdd/Makefile new file mode 100644 index 00000000000..32e549e1622 --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/Makefile @@ -0,0 +1,26 @@ +TEST_PARAMS=$(foreach V,$(.VARIABLES),$(if $(filter command line, $(origin $V)),--$(V) "$($(V))")) + +.PHONY: fmt +fmt: ## Run go fmt against code. + go mod tidy + go fmt ./... + +.PHONY: vet +vet: ## Run go vet against code. + go vet ./... + +.PHONY: update-modules +update-modules: fmt vet + +.PHONY: run-tests +run-tests: update-modules + ../hack/run-tests.sh $(TEST_PARAMS) + +.PHONY: run-smoke-tests +run-smoke-tests: update-modules + $(MAKE) run-tests smoke=true + +.PHONY: clean-logs +clean-logs: + rm -rf logs/ + diff --git a/packages/kogito-serverless-operator/testbdd/README.md b/packages/kogito-serverless-operator/testbdd/README.md new file mode 100644 index 00000000000..956fa94123e --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/README.md @@ -0,0 +1,129 @@ +# BDD tests + +Tests in this module are a rewrite and enhancement of the end-to-end tests available in the `/test` directory. +They use [Godog](https://github.com/cucumber/godog) framework which is the official [Cucumber](https://cucumber.io/) BDD framework for Go and use [Gherkin](https://cucumber.io/docs/gherkin/) for writing test scenarios. + +Tests also make use of the [BDD Framework](https://github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/tree/main/bddframework) for Kubernetes which simplifies communication with a Kubernetes cluster. This framework is an extract of the original framework available at [github.com/kiegroup/kogito-operator](https://github.com/kiegroup/kogito-operator/tree/main/test). + +## Run tests + +**Prerequisites:** + +- `oc` installed +- Minikube or OpenShift running +- `~/.kube/config` targeting the cluster + +Command to run tests has the following format: + +```bash +$ make run-tests [key=value]* +``` + +You can set these optional keys: + + + +- `feature` is a specific feature you want to run. + If you define a relative path, this has to be based on the "test" folder as the run is happening there. + _Default are all enabled features from 'test/features' folder_ + Example: feature=features/operator/deploy_quarkus_service.feature +- `tags` to run only specific scenarios. It is using tags filtering. + _Scenarios with '@disabled' tag are always ignored._ + Expression can be: + + - "@wip": run all scenarios with wip tag + - "~@wip": exclude all scenarios with wip tag + - "@wip && ~@new": run wip scenarios, but exclude new + - "@wip,@undone": run wip or undone scenarios + + Complete list of supported tags and descriptions can be found in [List of test tags](#list-of-test-tags) + +- `concurrent` is the number of concurrent tests to be run. + _Default is 1._ +- `timeout` sets the timeout in minutes for the overall run. + _Default is 240 minutes._ +- `debug` to be set to true to activate debug mode. + _Default is false._ +- `load_factor` sets the tests load factor. Useful for the tests to take into account that the cluster can be overloaded, for example for the calculation of timeouts. + _Default is 1._ +- `ci` to be set if running tests with CI. Give CI name. +- `cr_deployment_only` to be set if you don't have a CLI built. Default will deploy applications via the CLI. +- `load_default_config` sets to true if you want to directly use the default test config (from test/.default_config) +- `format` sets the Godog output format, possible values are 'pretty' or 'junit'. _Default is junit._ +- `container_engine` engine used to interact with images and local containers. + _Default is docker._ +- `domain_suffix` domain suffix used for exposed services. Ignored when running tests on Openshift. +- `http_retry_nb` sets the retry number for all HTTP calls in case it fails (and response code != 500). + _Default is 3._ +- `olm_namespace` Set the namespace which is used for cluster scope operators. Default is 'openshift-operators'. + +- `operator_image_tag` is the Operator image full name. +- `operator_installation_source` Defines what source is used to install the SonataFlow operator. Available options are `olm` and `yaml`. + _Default is yaml_. +- `operator_catalog_image` Specifies catalog image containing SonataFlow operator bundle. Needs to be specified when `operator_installation_source` is set to `olm`. +- `use_product_operator` Set true if you want to run tests using product operator. + +- `operator_yaml_uri` Url or Path to operator.yaml file. +_Default is ../operator.yaml_. + +- `show_scenarios` sets to true to display scenarios which will be executed. + _Default is false._ +- `show_steps` sets to true to display scenarios and their steps which will be executed. + _Default is false._ +- `dry_run` sets to true to execute a dry run of the tests, disable crds updates and display the scenarios which will be executed. + _Default is false._ +- `keep_namespace` sets to true to not delete namespace(s) after scenario run (WARNING: can be resources consuming ...). + _Default is false._ +- `namespace_name` to specify name of the namespace which will be used for scenario execution (intended for development purposes). +- `local_cluster` to be set to true if running tests using a local cluster. + _Default is false._ +- `local_execution` to be set to true if running tests in local using either a local or remote cluster. + _Default is false._ + +Logs will be shown on the Terminal. + +To save the test output in a local file for future reference, run the following command: + +```bash +make run-tests 2>&1 | tee log.out +``` + +#### Running BDD tests with the current branch + +``` +$ make +$ make container-build +$ podman tag quay.io/kiegroup/kogito-serverless-operator-nightly:latest quay.io/{USERNAME}/kogito-serverless-operator-nightly:latest +$ podman push quay.io/{USERNAME}/kogito-serverless-operator-nightly:latest +$ make run-tests cr_deployment_only=true local_cluster=true operator_image_tag=quay.io/{USERNAME}/kogito-serverless-operator-nightly:latest +``` + +**NOTE:** Replace {USERNAME} with the username/group you want to push to. Podman needs to be logged in to quay.io and be able to push to your username/group. If you want to use docker, just append `BUILDER=docker` to the `make container-build` command. + +#### Running smoke tests + +The BDD tests do provide some smoke tests for a quick feedback on basic functionality: + +```bash +$ make run-smoke-tests [key=value]* +``` + +It will run only tests tagged with `@smoke`. +All options from BDD tests do also apply here. + +#### Running devMode tests + +```bash +make run-tests cr_deployment_only=true local_cluster=true show_scenarios=true tags=devMode namespace_name=my-namespace operator_image_tag=quay.io/kiegroup/kogito-serverless-operator-nightly:latest +``` + +If you want to have a more readable format, you can specify the `format=pretty` parameter. You can also specify your own operator image. Namespace is always created automatically, however, you can provide its name as in the command above, otherwise it will be automatically generated. + +#### List of test tags + +| Tag name | Tag meaning | +| --------- | --------------------------------------------------------- | +| @smoke | Smoke tests verifying basic functionality | +| @disabled | Disabled tests, usually with comment describing reasons | +| | | +| @devMode | Tests verifying dev mode profile of the deployed workflow | diff --git a/packages/kogito-serverless-operator/testbdd/executor/bdd_executor.go b/packages/kogito-serverless-operator/testbdd/executor/bdd_executor.go new file mode 100644 index 00000000000..f36c9b5b254 --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/executor/bdd_executor.go @@ -0,0 +1,379 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package executor + +import ( + "context" + "fmt" + "io" + "os" + "strings" + "time" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/testbdd/installers" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/testbdd/steps" + + "github.com/cucumber/godog" + "github.com/cucumber/godog/colors" + "github.com/cucumber/messages-go/v16" + imgv1 "github.com/openshift/api/image/v1" + olmapiv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1" + flag "github.com/spf13/pflag" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/gherkin" + frameworkInstallers "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/installers" + kogitoSteps "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/steps" +) + +const ( + disabledTag = "@disabled" + cliTag = "@cli" + smokeTag = "@smoke" + performanceTag = "@performance" +) + +var ( + godogOpts = godog.Options{ + Output: colors.Colored(os.Stdout), + Format: "junit", + Randomize: time.Now().UTC().UnixNano(), + Tags: disabledTag, + } + + // PreRegisterStepsHook appends hooks to be executed before default steps are registered + PreRegisterStepsHook func(ctx *godog.ScenarioContext, d *steps.Data) + // AfterScenarioHook appends hooks to be executed before default AfterScenario phase + AfterScenarioHook func(scenario *godog.Scenario, d *steps.Data) error +) + +func init() { + config.BindFlags(flag.CommandLine) + godog.BindCommandLineFlags("godog.", &godogOpts) +} + +// ExecuteBDDTests executes BDD tests +func ExecuteBDDTests(beforeTestsExecution func(godogOpts *godog.Options) error) { + flag.Parse() + godogOpts.Paths = flag.Args() + + configureTags() + configureTestOutput() + + if beforeTestsExecution != nil { + if err := beforeTestsExecution(&godogOpts); err != nil { + panic(err) + } + } + + features, err := gherkin.ParseFeatures(godogOpts.Tags, godogOpts.Paths) + if err != nil { + panic(fmt.Errorf("Error parsing features: %v", err)) + } + if config.IsShowScenarios() || config.IsShowSteps() { + showScenarios(features, config.IsShowSteps()) + } + + if !config.IsDryRun() { + if !config.IsCrDeploymentOnly() || gherkin.MatchingFeatureWithTags(cliTag, features) { + // Check CLI binary is existing if needed + if exits, err := framework.CheckCliBinaryExist(); err != nil { + panic(fmt.Errorf("Error trying to get CLI binary %v", err)) + } else if !exits { + panic("CLI Binary does not exist on specified path") + } + } + + status := godog.TestSuite{ + Name: "godogs", + TestSuiteInitializer: initializeTestSuite, + ScenarioInitializer: initializeScenario, + Options: &godogOpts, + }.Run() + + os.Exit(status) + } + os.Exit(0) +} + +func configureTags() { + if config.IsSmokeTests() { + // Filter with smoke tag + appendTag(smokeTag) + } else if !strings.Contains(godogOpts.Tags, performanceTag) { + if config.IsPerformanceTests() { + // Turn on performance tests + appendTag(performanceTag) + } else { + // Turn off performance tests + appendTag("~" + performanceTag) + } + } + + if !strings.Contains(godogOpts.Tags, disabledTag) { + // Ignore disabled tag + appendTag("~" + disabledTag) + } +} + +func appendTag(tag string) { + if len(godogOpts.Tags) > 0 { + godogOpts.Tags += " && " + } + godogOpts.Tags += tag +} + +func configureTestOutput() { + logFolder := framework.GetLogFolder() + if err := framework.CreateFolder(logFolder); err != nil { + panic(fmt.Errorf("Error while creating log folder %s: %v", logFolder, err)) + } + + mainLogFile, err := os.Create(fmt.Sprintf("%s/%s", logFolder, "junit.xml")) + if err != nil { + panic(fmt.Errorf("Error creating junit file: %v", err)) + } + + godogOpts.Output = io.MultiWriter(godogOpts.Output, mainLogFile) +} + +func initializeTestSuite(ctx *godog.TestSuiteContext) { + // Verify Setup + if err := framework.CheckSetup(); err != nil { + panic(err) + } + + // Initialization of cluster wide resources + ctx.BeforeSuite(func() { + if config.IsOperatorProfiling() { + framework.GetMainLogger().Info("Running testing with profiling") + } + + monitorOlmNamespace() + + if config.IsOperatorInstalledByOlm() { + if err := installKogitoOperatorCatalogSource(); err != nil { + panic(err) + } + } + }) + + // Final cleanup once test suite finishes + ctx.AfterSuite(func() { + if !config.IsKeepNamespace() { + if config.IsOperatorProfiling() { + retrieveProfilingData() + } + + // Delete all operators created by test suite + if success := frameworkInstallers.UninstallServicesFromCluster(); !success { + framework.GetMainLogger().Warn("Some services weren't uninstalled propertly from cluster, see error logs above") + } + } + + if config.IsOperatorInstalledByOlm() { + deleteKogitoOperatorCatalogSource() + } + + stopOlmNamespaceMonitoring() + }) +} + +func initializeScenario(ctx *godog.ScenarioContext) { + // Register Steps + kogitoData := &kogitoSteps.Data{} + data := &steps.Data{Data: kogitoData} + + if PreRegisterStepsHook != nil { + PreRegisterStepsHook(ctx, data) + } + + data.RegisterAllSteps(ctx) + kogitoData.RegisterAllSteps(ctx) + + // Unused for now + // Log objects + //if config.UseProductOperator() { + // data.RegisterLogsKubernetesObjects(&v1.KogitoRuntimeList{}, &v1.KogitoBuildList{}) + //} else { + // data.RegisterLogsKubernetesObjects(&v1beta1.KogitoRuntimeList{}, &v1beta1.KogitoBuildList{}, &v1beta1.KogitoSupportingServiceList{}, &v1beta1.KogitoInfraList{}) + //} + + if config.IsOperatorInstalledByOlm() { // framework.IsOlmInstalled() may be included in the framework to properly resolve this + data.RegisterLogsKubernetesObjects(&olmapiv1alpha1.ClusterServiceVersionList{}) + } + + if framework.IsOpenshift() { + data.RegisterLogsKubernetesObjects(&imgv1.ImageStreamList{}) + } + + // Scenario handlers + ctx.Before(func(ctx context.Context, scenario *messages.Pickle) (context.Context, error) { + if err := data.BeforeScenario(scenario); err != nil { + framework.GetLogger(data.Namespace).Error(err, "Error in configuring data for before scenario") + } + return ctx, nil + }) + ctx.After(func(ctx context.Context, scenario *godog.Scenario, err error) (context.Context, error) { + + if AfterScenarioHook != nil { + if err := AfterScenarioHook(scenario, data); err != nil { + framework.GetLogger(data.Namespace).Error(err, "Error in executing AfterScenarioHook") + } + } + + if err := data.AfterScenario(scenario, err); err != nil { + framework.GetLogger(data.Namespace).Error(err, "Error in configuring data for After scenario") + } + + // Namespace should be deleted after all other operations have been done + if !config.IsKeepNamespace() { + if success := frameworkInstallers.UninstallServicesFromNamespace(data.Namespace); !success { + framework.GetMainLogger().Warn("Some services weren't uninstalled propertly from namespace, see error logs above", "namespace", data.Namespace) + } + + deleteNamespaceIfExists(data.Namespace) + } + + return ctx, nil + }) + + // Step handlers + ctx.StepContext().Before(func(ctx context.Context, s *godog.Step) (context.Context, error) { + framework.GetLogger(data.Namespace).Info("Step", "stepText", s.Text) + return ctx, nil + }) + ctx.StepContext().After(func(ctx context.Context, s *godog.Step, status godog.StepResultStatus, err error) (context.Context, error) { + if err != nil { + framework.GetLogger(data.Namespace).Error(err, "Error in step", "step", s.Text) + } + return ctx, nil + }) +} + +func deleteNamespaceIfExists(namespace string) { + err := framework.OperateOnNamespaceIfExists(namespace, func(namespace string) error { + framework.GetLogger(namespace).Info("Delete created namespace", "namespace", namespace) + if e := framework.DeleteNamespace(namespace); e != nil { + return fmt.Errorf("Error while deleting the namespace: %v", e) + } + return nil + }) + if err != nil { + framework.GetLogger(namespace).Error(err, "Error while doing operator on namespace") + } +} + +func showScenarios(features []*gherkin.Feature, showSteps bool) { + mainLogger := framework.GetMainLogger() + mainLogger.Info("------------------ SHOW SCENARIOS ------------------") + for _, ft := range features { + // Placeholders in names are now replaced directly into names for each scenario + if len(ft.Pickles) > 0 { + mainLogger.Info(fmt.Sprintf("Feature: %s", ft.Document.Feature.Name)) + for _, scenario := range ft.Pickles { + mainLogger.Info(fmt.Sprintf(" Scenario: %s", scenario.Name)) + if showSteps { + for _, step := range scenario.Steps { + mainLogger.Info(fmt.Sprintf(" Step: %s", step.Text)) + } + } + } + } + } + mainLogger.Info("------------------ END SHOW SCENARIOS ------------------") +} + +func monitorOlmNamespace() { + monitorNamespace(framework.GetClusterOperatorNamespace()) +} + +func monitorNamespace(namespace string) { + go func() { + err := framework.StartPodLogCollector(namespace) + if err != nil { + framework.GetLogger(namespace).Error(err, "Error starting log collector", "namespace", namespace) + } + }() +} + +func stopOlmNamespaceMonitoring() { + stopNamespaceMonitoring(framework.GetClusterOperatorNamespace()) +} + +func stopNamespaceMonitoring(namespace string) { + if err := framework.StopPodLogCollector(namespace); err != nil { + framework.GetMainLogger().Error(err, "Error stopping log collector", "namespace", namespace) + } + // Framework uses deprecated v1beta1 events which are deprecated as of v1.25, see https://kubernetes.io/docs/reference/using-api/deprecation-guide/#v1-25 + //if err := framework.BumpEvents(namespace); err != nil { + // framework.GetMainLogger().Error(err, "Error bumping events", "namespace", namespace) + //} +} + +// Install cluster wide Kogito operator from OLM +func installKogitoOperatorCatalogSource() error { + // Create CatalogSource + if _, err := framework.CreateKogitoOperatorCatalogSource(); err != nil { + return fmt.Errorf("Error installing custer wide Kogito operator using OLM: %v", err) + } + + // Wait for the CatalogSource + if err := framework.WaitForKogitoOperatorCatalogSourceReady(); err != nil { + return fmt.Errorf("Error while waiting for Kogito operator CatalogSource initialization: %v", err) + } + + return nil +} + +func deleteKogitoOperatorCatalogSource() { + if err := framework.DeleteKogitoOperatorCatalogSource(); err != nil { + framework.GetMainLogger().Error(err, "Error deleting Kogito operator CatalogSource") + } +} + +func retrieveProfilingData() { + framework.GetMainLogger().Info("Retrieve Profiling Data") + + if err := framework.RemoveKogitoOperatorDeployment(installers.SonataFlowNamespace); err != nil { + framework.GetMainLogger().Error(err, "Unable to delete Kogito Operator Deployment") + return + } + + // Apply dataaccess + if _, err := framework.CreateCommand("oc", "apply", "-f", config.GetOperatorProfilingDataAccessYamlURI()).Execute(); err != nil { + framework.GetMainLogger().Error(err, "Error while installing Kogito operator from YAML file") + return + } + + // Wait for dataaccess pod + if err := framework.WaitForPodsWithLabel(installers.SonataFlowNamespace, "name", "profiling-data-access", 1, 2); err != nil { + framework.GetMainLogger().Error(err, "Error while waiting for profiling data access pod") + return + } + + // Copy coverage data + dataFileInContainer := fmt.Sprintf("%s:/data/cover.out", "kogito-operator-profiling-data-access") + if _, err := framework.CreateCommand("oc", "cp", dataFileInContainer, config.GetOperatorProfilingOutputFileURI(), "-n", installers.SonataFlowNamespace).Execute(); err != nil { + framework.GetMainLogger().Error(err, "Error while installing Kogito operator from YAML file") + return + } +} diff --git a/packages/kogito-serverless-operator/testbdd/features/e2e.feature b/packages/kogito-serverless-operator/testbdd/features/e2e.feature new file mode 100644 index 00000000000..0cc03c301b7 --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/features/e2e.feature @@ -0,0 +1,24 @@ +Feature: Deploy SonataFlow Operator + + @devMode + Scenario: order-processing DevMode E2E test + Given Namespace is created + When SonataFlow Operator is deployed + When SonataFlowPlatform is deployed + When SonataFlow orderprocessing example is deployed + Then SonataFlow "orderprocessing" has the condition "Running" set to "True" within 5 minutes + Then SonataFlow "orderprocessing" is addressable within 1 minute + Then HTTP POST request as Cloud Event on SonataFlow "orderprocessing" is successful within 1 minute with path "", headers "content-type= application/json,ce-specversion= 1.0,ce-source= /from/localhost,ce-type= orderEvent,ce-id= f0643c68-609c-48aa-a820-5df423fa4fe0" and body: + """json + {"id":"f0643c68-609c-48aa-a820-5df423fa4fe0", + "country":"Czech Republic", + "total":10000, + "description":"iPhone 12" + } + """ + + Then Deployment "event-listener" pods log contains text 'source: /process/shippinghandling' within 1 minutes + Then Deployment "event-listener" pods log contains text 'source: /process/fraudhandling' within 1 minutes + Then Deployment "event-listener" pods log contains text '"id":"f0643c68-609c-48aa-a820-5df423fa4fe0","country":"Czech Republic","total":10000,"description":"iPhone 12"' within 1 minutes + Then Deployment "event-listener" pods log contains text '"fraudEvaluation":true' within 1 minutes + Then Deployment "event-listener" pods log contains text '"shipping":"international"' within 1 minutes diff --git a/packages/kogito-serverless-operator/testbdd/framework/operator.go b/packages/kogito-serverless-operator/testbdd/framework/operator.go new file mode 100644 index 00000000000..2c1ec73236e --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/framework/operator.go @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package framework + +import ( + "fmt" + + v1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/types" + + framework "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/operator" +) + +const ( + sonataFlowOperatorTimeoutInMin = 5 + + sonataFlowOperatorName = "sonataflow-operator" + sonataFlowOperatorDeploymentName = sonataFlowOperatorName + "-controller-manager" + sonataFlowOperatorPullImageSecretPrefix = sonataFlowOperatorName + "-dockercfg" +) + +// WaitForSonataFlowOperatorRunning waits for Kogito operator running +func WaitForSonataFlowOperatorRunning(namespace string) error { + return framework.WaitForOnOpenshift(namespace, "SonataFlow operator running", sonataFlowOperatorTimeoutInMin, + func() (bool, error) { + running, err := IsSonataFlowOperatorRunning(namespace) + if err != nil { + return false, err + } + + // If not running, make sure the image pull secret is present in pod + // If not present, delete the pod to allow its reconstruction with correct pull secret + // Note that this is specific to Openshift + if !running && framework.IsOpenshift() { + podList, err := framework.GetPodsWithLabels(namespace, map[string]string{"name": sonataFlowOperatorName}) + if err != nil { + framework.GetLogger(namespace).Error(err, "Error while trying to retrieve Kogito Operator pods") + return false, nil + } + for _, pod := range podList.Items { + if !framework.CheckPodHasImagePullSecretWithPrefix(&pod, sonataFlowOperatorPullImageSecretPrefix) { + // Delete pod as it has been misconfigured (missing pull secret) + framework.GetLogger(namespace).Info("Kogito Operator pod does not have the image pull secret needed. Deleting it to renew it.") + err := framework.DeleteObject(&pod) + if err != nil { + framework.GetLogger(namespace).Error(err, "Error while trying to delete Kogito Operator pod") + return false, nil + } + } + } + } + return running, nil + }) +} + +// IsSonataFlowOperatorRunning returns whether SonataFlow operator is running +func IsSonataFlowOperatorRunning(namespace string) (bool, error) { + exists, err := SonataFlowOperatorExists(namespace) + if err != nil { + if exists { + return false, nil + } + return false, err + } + + return exists, nil +} + +// SonataFlowOperatorExists returns whether SonataFlow operator exists and is running. If it is existing but not running, it returns true and an error +func SonataFlowOperatorExists(namespace string) (bool, error) { + framework.GetLogger(namespace).Debug("Checking Operator", "Deployment", sonataFlowOperatorDeploymentName, "Namespace", namespace) + + operatorDeployment := &v1.Deployment{} + namespacedName := types.NamespacedName{Namespace: namespace, Name: sonataFlowOperatorDeploymentName} // done to reuse the framework function + if exists, err := framework.GetObjectWithKey(namespacedName, operatorDeployment); err != nil { + return false, fmt.Errorf("Error while trying to look for Deploment %s: %v ", sonataFlowOperatorDeploymentName, err) + } else if !exists { + return false, nil + } + + if operatorDeployment.Status.AvailableReplicas == 0 { + return true, fmt.Errorf("%s Operator seems to be created in the namespace '%s', but there's no available pods replicas deployed ", operator.Name, namespace) + } + + if operatorDeployment.Status.AvailableReplicas != 1 { + return false, fmt.Errorf("Unexpected number of pods for %s Operator. Expected %d but got %d ", operator.Name, 1, operatorDeployment.Status.AvailableReplicas) + } + + return true, nil +} diff --git a/packages/kogito-serverless-operator/testbdd/go.mod b/packages/kogito-serverless-operator/testbdd/go.mod new file mode 100644 index 00000000000..d441c21b060 --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/go.mod @@ -0,0 +1,144 @@ +module github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/testbdd + +go 1.21 + +toolchain go1.21.6 + +replace ( + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator => ../ + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api => ../api + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework => ../bddframework + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder => ../container-builder + github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring => github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.50.0 +) + +require ( + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator v0.0.0 + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api v0.0.0 + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework v0.0.0 + github.com/cucumber/godog v0.12.5 + github.com/cucumber/messages-go/v16 v16.0.1 + github.com/openshift/api v0.0.0-20230522130544-0eef84f63102 + github.com/operator-framework/operator-lifecycle-manager v0.0.0-20200321030439-57b580e57e88 + github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.55.1 + github.com/spf13/pflag v1.0.5 + k8s.io/api v0.27.6 + k8s.io/apiextensions-apiserver v0.27.6 + k8s.io/apimachinery v0.27.6 + k8s.io/client-go v0.27.6 + knative.dev/eventing v0.26.0 + sigs.k8s.io/controller-runtime v0.15.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/RHsyseng/operator-utils v1.4.13 // indirect + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder v0.0.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/blang/semver v3.5.1+incompatible // indirect + github.com/blendle/zapdriver v1.3.1 // indirect + github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cloudevents/sdk-go/v2 v2.15.2 // indirect + github.com/cucumber/gherkin-go/v19 v19.0.3 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.10.2 // indirect + github.com/emirpasic/gods v1.12.0 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.7.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/ghodss/yaml v1.0.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/zapr v1.2.4 // 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.0 // indirect + github.com/go-playground/universal-translator v0.18.0 // indirect + github.com/go-playground/validator/v10 v10.11.1 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/gofrs/uuid v4.0.0+incompatible // 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.3 // indirect + github.com/google/gnostic v0.6.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 // indirect + github.com/google/uuid v1.3.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-memdb v1.3.0 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/imdario/mergo v0.3.16 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kelseyhightower/envconfig v1.4.0 // indirect + github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect + github.com/leodido/go-urn v1.2.1 // indirect + github.com/machinebox/graphql v0.2.2 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/go-homedir v1.1.0 // 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/v2 v2.13.0 // indirect + github.com/openshift/client-go v0.0.0-20230503144108-75015d2347cb // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/statsd_exporter v0.22.7 // indirect + github.com/relvacode/iso8601 v1.3.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/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 // indirect + github.com/sergi/go-diff v1.1.0 // indirect + github.com/serverlessworkflow/sdk-go/v2 v2.2.5 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect + github.com/src-d/gcfg v1.4.0 // indirect + github.com/stretchr/testify v1.8.4 // indirect + github.com/xanzy/ssh-agent v0.2.1 // indirect + go.opencensus.io v0.24.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.26.0 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/sync v0.4.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.14.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + google.golang.org/api v0.147.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect + google.golang.org/grpc v1.58.3 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect + gopkg.in/src-d/go-git.v4 v4.13.1 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/component-base v0.27.6 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 // indirect + k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // 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.3.0 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/packages/kogito-serverless-operator/testbdd/go.sum b/packages/kogito-serverless-operator/testbdd/go.sum new file mode 100644 index 00000000000..43572f7c878 --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/go.sum @@ -0,0 +1,1606 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg= +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.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= +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 v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +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.0/go.mod h1:o7cosnyfuPVK0tB8q0QmaQNhGnptITnPQB+z1+qeFB0= +contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= +contrib.go.opencensus.io/exporter/zipkin v0.1.2/go.mod h1:mP5xM3rrgOjpn79MM8fZbj3gsxcuytSqtH0dxSWW1RE= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +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/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig/v3 v3.0.2/go.mod h1:oesJ8kPONMONaZgtiHNzUShJbksypC5kWczhZAf6+aU= +github.com/Masterminds/vcs v1.13.1/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/RHsyseng/operator-utils v1.4.13 h1:kCsvBXm1Y3AEfzjioUvk/RmOigM/+czd/U5YQ3SZXx8= +github.com/RHsyseng/operator-utils v1.4.13/go.mod h1:f+GrcLNALoHBPonk3P6KCwPK5kYyHhkqj4vuCP2Eijc= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/ahmetb/gen-crd-api-reference-docs v0.3.1-0.20210420163308-c1402a70e2f1/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= +github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= +github.com/alecthomas/jsonschema v0.0.0-20180308105923-f2c93856175a/go.mod h1:qpebaTNSsyUn5rPSJMsfqEtDw71TTggXM6stUDI16HA= +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/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +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/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +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/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/c2h5oh/datasize v0.0.0-20171227191756-4eba002a5eae/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/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 v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= +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/conformance v0.2.0/go.mod h1:rHKDwylBH89Rns6U3wL9ww8bg9/4GbwRCDNuyoC6bcc= +github.com/cloudevents/sdk-go/observability/opencensus/v2 v2.4.1/go.mod h1:lhEpxMrIUkeu9rVRgoAbyqZ8GR8Hd3DUy+thHUxAHoI= +github.com/cloudevents/sdk-go/v2 v2.4.1/go.mod h1:MZiMwmAh5tGj+fPFvtHv9hKurKqXtdB9haJYMJ/7GJY= +github.com/cloudevents/sdk-go/v2 v2.15.2 h1:54+I5xQEnI73RBhWHxbI1XJcqOFOVJN85vb41+8mHUc= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200107194136-26c1120b8d41/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cucumber/gherkin-go/v19 v19.0.3 h1:mMSKu1077ffLbTJULUfM5HPokgeBcIGboyeNUof1MdE= +github.com/cucumber/gherkin-go/v19 v19.0.3/go.mod h1:jY/NP6jUtRSArQQJ5h1FXOUgk5fZK24qtE7vKi776Vw= +github.com/cucumber/godog v0.12.5 h1:FZIy6VCfMbmGHts9qd6UjBMT9abctws/pQYO/ZcwOVs= +github.com/cucumber/godog v0.12.5/go.mod h1:u6SD7IXC49dLpPN35kal0oYEjsXZWee4pW6Tm9t5pIc= +github.com/cucumber/messages-go/v16 v16.0.0/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK30BGjtYotDKpwQ0v6g= +github.com/cucumber/messages-go/v16 v16.0.1 h1:fvkpwsLgnIm0qugftrw2YwNlio+ABe2Iu94Ap8GMYIY= +github.com/cucumber/messages-go/v16 v16.0.1/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK30BGjtYotDKpwQ0v6g= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= +github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg= +github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= +github.com/cznic/internal v0.0.0-20180608152220-f44710a21d00/go.mod h1:olo7eAdKwJdXxb55TKGLiJ6xt1H0/tiiRCWKVLmtjY4= +github.com/cznic/lldb v1.1.0/go.mod h1:FIZVUmYUVhPwRiPzL8nD/mpFcJ/G7SSXjjXYG4uRI3A= +github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= +github.com/cznic/ql v1.2.0/go.mod h1:FbpzhyZrqr0PVlK6ury+PoW3T0ODUV22OeWIxcaOrSE= +github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ= +github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= +github.com/cznic/zappy v0.0.0-20160723133515-2533cb5b45cc/go.mod h1:Y1SNZ4dRUOKXshKUbwUapqNncRrho4mkjQebgEHZLj8= +github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= +github.com/deislabs/oras v0.8.1/go.mod h1:Mx0rMSbBNaNfY9hjpccEnxkOqJL6KGjtxNHPLC4G4As= +github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-gk v0.0.0-20140819190930-201884a44051/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E= +github.com/dgryski/go-gk v0.0.0-20200319235926-a69029f61654/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E= +github.com/dgryski/go-lttb v0.0.0-20180810165845-318fcdf10a77/go.mod h1:Va5MyIzkU0rAM92tn3hb3Anb7oz7KcnixF49+2wOMe4= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= +github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v0.7.3-0.20190103212154-2b7e084dc98b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v0.7.3-0.20190817195342-4760db040282/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE= +github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +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.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= +github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= +github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +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.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= +github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +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-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +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.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-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.4.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.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= +github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= +github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +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/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= +github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= +github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= +github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= +github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= +github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +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/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= +github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= +github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +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/gobuffalo/flect v0.1.5/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= +github.com/gobuffalo/flect v0.2.3/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcrg45ZL7LDBMW3WGJL0= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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 v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +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/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= +github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8= +github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= +github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= +github.com/gonum/diff v0.0.0-20181124234638-500114f11e71/go.mod h1:22dM4PLscQl+Nzf64qNBurVJvfyvZELT0iRW2l/NN70= +github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= +github.com/gonum/integrate v0.0.0-20181209220457-a422b5c0fdf2/go.mod h1:pDgmNM6seYpwvPos3q+zxlXMsbve6mOIPucUnUOrI7Y= +github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks= +github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A= +github.com/gonum/mathext v0.0.0-20181121095525-8a4bf007ea55/go.mod h1:fmo8aiSEWkJeiGXUJf+sPvuDgEFgqIoZSs843ePKrGg= +github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= +github.com/gonum/stat v0.0.0-20181125101827-41a0da705a5b/go.mod h1:Z4GIJBJO3Wa4gD4vbwQxXXZ+WHmW6E9ixmNrwvs0iZs= +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 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.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.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-github/v27 v27.0.6/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.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/mako v0.0.0-20190821191249-122f8dcef9e3/go.mod h1:YzLcVlL+NqWnmUEPuhS1LxDDwGO9WNbVlEXaF4IH35g= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/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-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 h1:n6vlPhxsA+BW/XsS5+uqi7GyzaLa5MH7qlSLBZtRdiA= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= +github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-health-probe v0.2.1-0.20181220223928-2bf0a5b182db/go.mod h1:uBKkC2RbarFsvS5jMJHpVhTLvGlGQj9JJwkaePE3FWI= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-memdb v1.3.0 h1:xdXq34gBOMEloa9rlGStLxmfX/dyIK8htOv36dQUwHU= +github.com/hashicorp/go-memdb v1.3.0/go.mod h1:Mluclgwib3R93Hk5fxEfiRhB+6Dar64wWh71LpNSe3g= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +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 v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= +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.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a/go.mod h1:9GkyshztGufsdPQWjH+ifgnIr3xNUL5syI70g2dzU1o= +github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= +github.com/influxdata/tdigest v0.0.0-20191024211133-5d87a7585faa/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y= +github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= +github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +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/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +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/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/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +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/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= +github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= +github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +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.2/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.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +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/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/lightstep/tracecontext.go v0.0.0-20181129014701-1757c391b1ac/go.mod h1:Frd2bnT3w5FB5q49ENTfVlztJES+1k/7lyWX2+9gq/M= +github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/machinebox/graphql v0.2.2 h1:dWKpJligYKhYKO5A2gvNhkJdQMNZeChZYyBbrZkBZfo= +github.com/machinebox/graphql v0.2.2/go.mod h1:F+kbVMHuwrQ5tYgU9JXlnskM8nOaFxCAEolaQybkjWA= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-shellwords v1.0.9/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +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/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/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/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.17/go.mod h1:WgzbA6oji13JREwiNsRDNfl7jYdPnmz+VEuLrA+/48M= +github.com/mikefarah/yaml/v2 v2.4.0/go.mod h1:ahVqZF4n1W4NqwvVnZzC4es67xsW9uR/RRf2RRxieJU= +github.com/mikefarah/yq/v2 v2.4.1/go.mod h1:i8SYf1XdgUvY2OFwSqGAtWOOgimD2McJ6iutoxRm4k0= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +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/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= +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-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +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/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +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/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +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.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/openshift/api v0.0.0-20200205133042-34f0ec8dab87/go.mod h1:fT6U/JfG8uZzemTRwZA2kBDJP5nWz7v05UHnty/D+pk= +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/client-go v0.0.0-20190923180330-3b6373338c9b/go.mod h1:6rzn+JTr7+WYS2E1TExP4gByoABxMznR6y2SnUIkmxk= +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/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= +github.com/operator-framework/api v0.1.1/go.mod h1:yzNYR7qyJqRGOOp+bT6Z/iYSbSPNxeh3Si93Gx/3OBY= +github.com/operator-framework/operator-lifecycle-manager v0.0.0-20200321030439-57b580e57e88 h1:ByKBik0i2aTEr7iKdSCmUGULydHwr6hA0h4INv9LkSA= +github.com/operator-framework/operator-lifecycle-manager v0.0.0-20200321030439-57b580e57e88/go.mod h1:7Ut8p9jJ8C6RZyyhZfZypmlibCIJwK5Wcc+WZDgLkOA= +github.com/operator-framework/operator-registry v1.5.3/go.mod h1:agrQlkWOo1q8U1SAaLSS2WQ+Z9vswNT2M2HFib9iuLY= +github.com/operator-framework/operator-registry v1.6.1/go.mod h1:sx4wWMiZtYhlUiaKscg3QQUPPM/c1bkrAs4n4KipDb4= +github.com/otiai10/copy v1.0.1/go.mod h1:8bMCJrAqOtN/d9oyh5HR7HhLQMvcGMpGdwRDYsfOCHc= +github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776/go.mod h1:3HNVkVOU7vZeFXocWuvtcS0XSFLcf2XUSDHkq9t1jU4= +github.com/otiai10/mint v1.2.3/go.mod h1:YnfyPNhBvnY8bW4SGQHCs/aAFhkgySlMZbrF5U0bOVw= +github.com/otiai10/mint v1.2.4/go.mod h1:d+b7n/0R3tdyUYYylALXpWQ/kTN+QobSq/4SRGBkR3M= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml/v2 v2.0.0-beta.2/go.mod h1:+X+aW6gUj6Hda43TeYHVCIvYNG/jqY/8ZFXAeXXHl+Q= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.50.0 h1:eIYVhtUPLDah0nhcHaWItFM595UAGVFKECaWoW02FUA= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.50.0/go.mod h1:3WYi4xqXxGGXWDdQIITnLNmuDzO5n6wYva9spVhR4fg= +github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= +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.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/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.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +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.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= +github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/relvacode/iso8601 v1.3.0 h1:HguUjsGpIMh/zsTczGN3DVJFxTU/GX+MMmzcKoMO7ko= +github.com/relvacode/iso8601 v1.3.0/go.mod h1:FlNp+jz+TXpyRqgmM7tnzHHzBnz776kmAH2h3sZCn0I= +github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +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 v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +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.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 h1:Dz0HrI1AtNSGCE8LXLLqoZU4iuOJXPWndenCsZfstA8= +github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46/go.mod h1:is8FVkzSi7PYLWEXT5MgWhglFsyyiW8ffxAoJqfuFZo= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +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.2.5 h1:/TFqBBni0hDpTA0bKadGTWbyBRiQ0o2ppz2ScY6DdTM= +github.com/serverlessworkflow/sdk-go/v2 v2.2.5/go.mod h1:uIy7EgNRGUzuTsihdto7fN+xsz/HDHq0MP1aPIG7wHU= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +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/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +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/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +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/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/sqs/goreturns v0.0.0-20181028201513-538ac6014518/go.mod h1:CKI4AZ4XmGV240rTHfO0hfE83S6/a3/Q1siZJ/vXf7A= +github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= +github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU= +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.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +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 v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/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.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tsenart/go-tsz v0.0.0-20180814232043-cdeb9e1e981e/go.mod h1:SWZznP1z5Ki7hDT2ioqiFKEse8K9tU2OUvaRI0NeGQo= +github.com/tsenart/vegeta/v12 v12.8.4/go.mod h1:ZiJtwLn/9M4fTPdMY7bdbIeyNeFVE8/AHbWFqCsUuho= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +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/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/wavesoftware/go-ensure v1.0.0/go.mod h1:K2UAFSwMTvpiRGay/M3aEYYuurcR8S4A6HkQlJPV8k4= +github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= +github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= +github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/otel v0.16.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/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-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +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-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/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.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +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/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/lint v0.0.0-20201208152925-83fdc39ff7b5/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.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +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-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181108082009-03003ca0c849/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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/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-20190619014844-b5b0513f8c1b/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-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/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-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/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-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/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-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +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-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/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-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/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-20190321052220-f7bb7a8bee54/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-20190426135247-a129542de9ae/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-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/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-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/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-20191210023423-ac6580df4449/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-20200519105757-fe76b779f299/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-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/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-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-20210806184541-e5e7981a1069/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-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +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.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/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-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/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-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190617190820-da514acc4774/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-20190624222133-a101b041ded4/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-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/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-20190920225731-5eefd052ad72/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-20191030203535-5e247c9ad0a0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/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-20200115044656-831fdb1e1868/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-20200505023115-26f46d2f7ef8/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-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +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.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= +gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +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.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.147.0 h1:Can3FaQo9LlVqxJCodNmeZW/ib3/qKAY3rFeXiHo5gc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= +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-20190404172233-64821d5d2107/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 v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210416161957-9910b6c460de/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c h1:jHkCUWkseRf+W+edG5hMzr/Uh1xkDREY4caybAq4dpY= +google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +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.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +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.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/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-20200227125254-8fa46927fb4f/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/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/imdario/mergo.v0 v0.3.7/go.mod h1:9qPP6AGrlC1G2PTNXko614FwGZvorN7MiBU0Eppok+U= +gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= +gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= +gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= +gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= +gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= +gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +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-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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 v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +helm.sh/helm/v3 v3.1.2/go.mod h1:WYsFJuMASa/4XUqLyv54s0U/f3mlAaRErGmyy4z921g= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +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.0.0-20190918155943-95b840bb6a1f/go.mod h1:uWuOHnjmNrtQomJrvEBg0c0HRNyQ+8KTEERVsK0PW48= +k8s.io/api v0.16.7/go.mod h1:oUAiGRgo4t+5yqcxjOu5LoHT3wJ8JSbgczkaFYS5L7I= +k8s.io/api v0.17.1/go.mod h1:zxiAc5y8Ngn4fmhWUtSxuUlkfz1ixT7j9wESokELzOg= +k8s.io/api v0.17.2/go.mod h1:BS9fjjLc4CMuqfSO8vgbHPKMt5+SF0ET6u/RVDihTo4= +k8s.io/api v0.17.3/go.mod h1:YZ0OTkuw7ipbe305fMpIdf3GLXZKRigjtZaV5gzC2J0= +k8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA= +k8s.io/api v0.21.4/go.mod h1:fTVGP+M4D8+00FN2cMnJqk/eb/GH53bvmNs2SVTmpFk= +k8s.io/api v0.27.6 h1:PBWu/lywJe2qQcshMjubzcBg7+XDZOo7O8JJAWuYtUo= +k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783/go.mod h1:xvae1SZB3E17UpV59AWc271W/Ph25N+bjPyR63X6tPY= +k8s.io/apiextensions-apiserver v0.16.7/go.mod h1:6xYRp4trGp6eT5WZ6tPi/TB2nfWQCzwUvBlpg8iswe0= +k8s.io/apiextensions-apiserver v0.17.2/go.mod h1:4KdMpjkEjjDI2pPfBA15OscyNldHWdBCfsWMDWAmSTs= +k8s.io/apiextensions-apiserver v0.17.3/go.mod h1:CJbCyMfkKftAd/X/V6OTHYhVn7zXnDdnkUjS1h0GTeY= +k8s.io/apiextensions-apiserver v0.18.3/go.mod h1:TMsNGs7DYpMXd+8MOCX8KzPOCx8fnZMoIGB24m03+JE= +k8s.io/apiextensions-apiserver v0.21.4/go.mod h1:OoC8LhI9LnV+wKjZkXIBbLUwtnOGJiTRE33qctH5CIk= +k8s.io/apiextensions-apiserver v0.27.6 h1:mOwSBJtThZhpJr+8gEkc3wFDIjq87E3JspR5mtZxIg8= +k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655/go.mod h1:nL6pwRT8NgfF8TT68DBI8uEePRt89cSvoXUVqbkWHq4= +k8s.io/apimachinery v0.16.7/go.mod h1:Xk2vD2TRRpuWYLQNM6lT9R7DSFZUYG03SarNkbGrnKE= +k8s.io/apimachinery v0.17.1/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= +k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= +k8s.io/apimachinery v0.17.3/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g= +k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= +k8s.io/apimachinery v0.19.7/go.mod h1:6sRbGRAVY5DOCuZwB5XkqguBqpqLU6q/kOaOdk29z6Q= +k8s.io/apimachinery v0.21.4/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI= +k8s.io/apimachinery v0.27.6 h1:mGU8jmBq5o8mWBov+mLjdTBcU+etTE19waies4AQ6NE= +k8s.io/apiserver v0.0.0-20190918160949-bfa5e2e684ad/go.mod h1:XPCXEwhjaFN29a8NldXA901ElnKeKLrLtREO9ZhFyhg= +k8s.io/apiserver v0.16.7/go.mod h1:/5zSatF30/L9zYfMTl55jzzOnx7r/gGv5a5wtRp8yAw= +k8s.io/apiserver v0.17.2/go.mod h1:lBmw/TtQdtxvrTk0e2cgtOxHizXI+d0mmGQURIHQZlo= +k8s.io/apiserver v0.17.3/go.mod h1:iJtsPpu1ZpEnHaNawpSV0nYTGBhhX2dUlnn7/QS7QiY= +k8s.io/apiserver v0.18.3/go.mod h1:tHQRmthRPLUtwqsOnJJMoI8SW3lnoReZeE861lH8vUw= +k8s.io/apiserver v0.21.4/go.mod h1:SErUuFBBPZUcD2nsUU8hItxoYheqyYr2o/pCINEPW8g= +k8s.io/cli-runtime v0.17.2/go.mod h1:aa8t9ziyQdbkuizkNLAw3qe3srSyWh9zlSB7zTqRNPI= +k8s.io/cli-runtime v0.17.3/go.mod h1:X7idckYphH4SZflgNpOOViSxetiMj6xI0viMAjM81TA= +k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53q3Uz5OSfgsv4uxpScmmyYOOlk= +k8s.io/client-go v0.16.7/go.mod h1:9kEMEeuy2LdsHHXoU2Skqh+SDso+Yhkxd/0tltvswDE= +k8s.io/client-go v0.17.2/go.mod h1:QAzRgsa0C2xl4/eVpeVAZMvikCn8Nm81yqVx3Kk9XYI= +k8s.io/client-go v0.17.3/go.mod h1:cLXlTMtWHkuK4tD360KpWz2gG2KtdWEr/OT02i3emRQ= +k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw= +k8s.io/client-go v0.21.4/go.mod h1:t0/eMKyUAq/DoQ7vW8NVVA00/nomlwC+eInsS8PxSew= +k8s.io/client-go v0.27.6 h1:vzI8804gpUtpMCNaFjIFyJrifH7u//LJCJPy8fQuYQg= +k8s.io/code-generator v0.0.0-20190912054826-cd179ad6a269/go.mod h1:V5BD6M4CyaN5m+VthcclXWsVcT1Hu+glwa1bi3MIsyE= +k8s.io/code-generator v0.16.7/go.mod h1:wFdrXdVi/UC+xIfLi+4l9elsTT/uEF61IfcN2wOLULQ= +k8s.io/code-generator v0.17.1/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= +k8s.io/code-generator v0.17.2/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= +k8s.io/code-generator v0.17.3/go.mod h1:l8BLVwASXQZTo2xamW5mQNFCe1XPiAesVq7Y1t7PiQQ= +k8s.io/code-generator v0.18.3/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= +k8s.io/code-generator v0.21.4/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo= +k8s.io/component-base v0.0.0-20190918160511-547f6c5d7090/go.mod h1:933PBGtQFJky3TEwYx4aEPZ4IxqhWh3R6DCmzqIn1hA= +k8s.io/component-base v0.16.7/go.mod h1:ikdyfezOFMu5O0qJjy/Y9eXwj+fV3pVwdmt0ulVcIR0= +k8s.io/component-base v0.17.2/go.mod h1:zMPW3g5aH7cHJpKYQ/ZsGMcgbsA/VyhEugF3QT1awLs= +k8s.io/component-base v0.17.3/go.mod h1:GeQf4BrgelWm64PXkIXiPh/XS0hnO42d9gx9BtbZRp8= +k8s.io/component-base v0.18.3/go.mod h1:bp5GzGR0aGkYEfTj+eTY0AN/vXTgkJdQXjNTTVUaa3k= +k8s.io/component-base v0.21.4/go.mod h1:ZKG0eHVX+tUDcaoIGpU3Vtk4TIjMddN9uhEWDmW6Nyg= +k8s.io/component-base v0.27.6 h1:hF5WxX7Tpi9/dXAbLjPVkIA6CA6Pi6r9JOHyo0uCDYI= +k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20210203185629-de9496dff47b/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-aggregator v0.17.3/go.mod h1:1dMwMFQbmH76RKF0614L7dNenMl3dwnUJuOOyZ3GMXA= +k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= +k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= +k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= +k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= +k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 h1:OmK1d0WrkD3IPfkskvroRykOulHVHf0s0ZIFRjyt+UI= +k8s.io/kubectl v0.17.2/go.mod h1:y4rfLV0n6aPmvbRCqZQjvOp3ezxsFgpqL+zF5jH/lxk= +k8s.io/kubectl v0.17.3/go.mod h1:NUn4IBY7f7yCMwSop2HCXlw/MVYP4HJBiUmOR3n9w28= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +k8s.io/metrics v0.17.2/go.mod h1:3TkNHET4ROd+NfzNxkjoVfQ0Ob4iZnaHmSEA4vYpwLw= +k8s.io/metrics v0.17.3/go.mod h1:HEJGy1fhHOjHggW9rMDBJBD3YuGroH3Y1pnIRw9FFaI= +k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc= +knative.dev/eventing v0.26.0 h1:osDUdav7S0FuChN0onfwL5cEcsdb54Kee2hjAPMpY7o= +knative.dev/eventing v0.26.0/go.mod h1:6tTam0lsPtBSJHJ63/195obj2VAHlTZZB7TLiBSeqk0= +knative.dev/hack v0.0.0-20210806075220-815cd312d65c/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= +knative.dev/hack/schema v0.0.0-20210806075220-815cd312d65c/go.mod h1:ffjwmdcrH5vN3mPhO8RrF2KfNnbHeCE2C60A+2cv3U0= +knative.dev/pkg v0.0.0-20210914164111-4857ab6939e3/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8= +knative.dev/pkg v0.0.0-20210919202233-5ae482141474/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8= +knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c h1:xyPoEToTWeBdn6tinhLxXfnhJhTNQt5WzHiTNiFphRw= +knative.dev/reconciler-test v0.0.0-20210915181908-49fac7555086/go.mod h1:6yDmb26SINSmgw6wVy9qQwgRMewiW8ddkkwGLR0ZvOY= +modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= +modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= +modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= +modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= +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/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= +sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +sigs.k8s.io/controller-tools v0.2.4/go.mod h1:m/ztfQNocGYBgTTCmFdnK94uVvgxeZeE3LtJvd/jIzA= +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/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= +sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= +sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= +sigs.k8s.io/structured-merge-diff v1.0.2/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= +sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI= diff --git a/packages/kogito-serverless-operator/testbdd/installers/sonataflow_installer.go b/packages/kogito-serverless-operator/testbdd/installers/sonataflow_installer.go new file mode 100644 index 00000000000..5d184c8a533 --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/installers/sonataflow_installer.go @@ -0,0 +1,199 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package installers + +import ( + "errors" + "fmt" + "regexp" + + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/installers" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/controllers/workflowdef" + srvframework "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/testbdd/framework" +) + +const defaultOperatorImage = "quay.io/kiegroup/kogito-serverless-operator" + +var ( + // sonataFlowYamlClusterInstaller installs SonataFlow operator cluster wide using YAMLs + sonataFlowYamlClusterInstaller = installers.YamlClusterWideServiceInstaller{ + InstallClusterYaml: installSonataFlowUsingYaml, + InstallationNamespace: SonataFlowNamespace, + WaitForClusterYamlServiceRunning: waitForSonataFlowOperatorUsingYamlRunning, + GetAllClusterYamlCrsInNamespace: getSonataFlowCrsInNamespace, + UninstallClusterYaml: uninstallSonataFlowUsingYaml, + ClusterYamlServiceName: sonataFlowServiceName, + CleanupClusterYamlCrsInNamespace: cleanupSonataFlowCrsInNamespace, + } + + // sonataFlowCustomOlmClusterWideInstaller installs SonataFlow cluster wide using OLM with custom catalog + sonataFlowCustomOlmClusterWideInstaller = installers.OlmClusterWideServiceInstaller{ + SubscriptionName: sonataFlowOperatorSubscriptionName, + Channel: sonataFlowOperatorSubscriptionChannel, + Catalog: framework.GetCustomKogitoOperatorCatalog, + InstallationTimeoutInMinutes: 5, + GetAllClusterWideOlmCrsInNamespace: getSonataFlowCrsInNamespace, + CleanupClusterWideOlmCrsInNamespace: cleanupSonataFlowCrsInNamespace, + } + + // sonataFlowOlmClusterWideInstaller installs SonataFlow cluster wide using OLM with community catalog + sonataFlowOlmClusterWideInstaller = installers.OlmClusterWideServiceInstaller{ + SubscriptionName: sonataFlowOperatorSubscriptionName, + Channel: sonataFlowOperatorSubscriptionChannel, + Catalog: framework.GetCommunityCatalog, + InstallationTimeoutInMinutes: 5, + GetAllClusterWideOlmCrsInNamespace: getSonataFlowCrsInNamespace, + CleanupClusterWideOlmCrsInNamespace: cleanupSonataFlowCrsInNamespace, + } + + // SonataFlowNamespace is the SonataFlow namespace for yaml cluster-wide deployment + SonataFlowNamespace = "sonataflow-operator-system" + sonataFlowServiceName = "SonataFlow operator" + + sonataFlowOperatorSubscriptionName = "sonataflow-operator" + sonataFlowOperatorSubscriptionChannel = "alpha" +) + +// GetSonataFlowInstaller returns SonataFlow installer +func GetSonataFlowInstaller() (installers.ServiceInstaller, error) { + // If user doesn't pass SonataFlow operator image then use community OLM catalog to install operator + if len(config.GetOperatorImageTag()) == 0 { + framework.GetMainLogger().Info("Installing SonataFlow operator using community catalog.") + return &sonataFlowOlmClusterWideInstaller, nil + } + + if config.IsOperatorInstalledByYaml() || config.IsOperatorProfiling() { + return &sonataFlowYamlClusterInstaller, nil + } + + if config.IsOperatorInstalledByOlm() { + return &sonataFlowCustomOlmClusterWideInstaller, nil + } + + return nil, errors.New("no SonataFlow operator installer available for provided configuration") +} + +func installSonataFlowUsingYaml() error { + framework.GetMainLogger().Info("Installing SonataFlow operator") + + yamlContent, err := framework.ReadFromURI(config.GetOperatorYamlURI()) + if err != nil { + framework.GetMainLogger().Error(err, "Error while reading the operator YAML file") + return err + } + + regexp, err := regexp.Compile(getDefaultOperatorImageTag()) + if err != nil { + return err + } + yamlContent = regexp.ReplaceAllString(yamlContent, config.GetOperatorImageTag()) + + tempFilePath, err := framework.CreateTemporaryFile("kogito-serverless-operator*.yaml", yamlContent) + if err != nil { + framework.GetMainLogger().Error(err, "Error while storing adjusted YAML content to temporary file") + return err + } + + _, err = framework.CreateCommand("oc", "create", "-f", tempFilePath).Execute() + if err != nil { + framework.GetMainLogger().Error(err, "Error while installing SonataFlow operator from YAML file") + return err + } + + return nil +} + +func waitForSonataFlowOperatorUsingYamlRunning() error { + return srvframework.WaitForSonataFlowOperatorRunning(SonataFlowNamespace) +} + +func uninstallSonataFlowUsingYaml() error { + framework.GetMainLogger().Info("Uninstalling SonataFlow operator") + + output, err := framework.CreateCommand("oc", "delete", "-f", config.GetOperatorYamlURI(), "--timeout=30s", "--ignore-not-found=true").Execute() + if err != nil { + framework.GetMainLogger().Error(err, fmt.Sprintf("Deleting SonataFlow operator failed, output: %s", output)) + return err + } + + return nil +} + +func getSonataFlowCrsInNamespace(namespace string) ([]client.Object, error) { + var crs []client.Object + + //kogitoRuntimes := &v1beta1.KogitoRuntimeList{} + //if err := framework.GetObjectsInNamespace(namespace, kogitoRuntimes); err != nil { + // return nil, err + //} + //for i := range kogitoRuntimes.Items { + // crs = append(crs, &kogitoRuntimes.Items[i]) + //} + // + //kogitoBuilds := &v1beta1.KogitoBuildList{} + //if err := framework.GetObjectsInNamespace(namespace, kogitoBuilds); err != nil { + // return nil, err + //} + //for i := range kogitoBuilds.Items { + // crs = append(crs, &kogitoBuilds.Items[i]) + //} + // + //kogitoSupportingServices := &v1beta1.KogitoSupportingServiceList{} + //if err := framework.GetObjectsInNamespace(namespace, kogitoSupportingServices); err != nil { + // return nil, err + //} + //for i := range kogitoSupportingServices.Items { + // crs = append(crs, &kogitoSupportingServices.Items[i]) + //} + // + //kogitoInfras := &v1beta1.KogitoInfraList{} + //if err := framework.GetObjectsInNamespace(namespace, kogitoInfras); err != nil { + // return nil, err + //} + //for i := range kogitoInfras.Items { + // crs = append(crs, &kogitoInfras.Items[i]) + //} + + return crs, nil +} + +func cleanupSonataFlowCrsInNamespace(namespace string) bool { + crs, err := getSonataFlowCrsInNamespace(namespace) + if err != nil { + framework.GetLogger(namespace).Error(err, "Error getting SonataFlow CRs.") + return false + } + + for _, cr := range crs { + if err := framework.DeleteObject(cr); err != nil { + framework.GetLogger(namespace).Error(err, "Error deleting SonataFlow CR.", "CR name", cr.GetName()) + return false + } + } + return true +} + +func getDefaultOperatorImageTag() string { + return workflowdef.GetDefaultImageTag(defaultOperatorImage) +} diff --git a/packages/kogito-serverless-operator/testbdd/main_test.go b/packages/kogito-serverless-operator/testbdd/main_test.go new file mode 100644 index 00000000000..8efbf60350c --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/main_test.go @@ -0,0 +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. + */ + +package main + +import ( + "testing" + + framework "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/testbdd/executor" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/testbdd/meta" +) + +func TestMain(m *testing.M) { + // Create kube client + if err := framework.InitKubeClient(meta.GetRegisteredSchema()); err != nil { + panic(err) + } + + executor.ExecuteBDDTests(nil) +} diff --git a/packages/kogito-serverless-operator/testbdd/meta/meta.go b/packages/kogito-serverless-operator/testbdd/meta/meta.go new file mode 100644 index 00000000000..ad92231a90d --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/meta/meta.go @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package meta + +import ( + appsv1 "github.com/openshift/api/apps/v1" + buildv1 "github.com/openshift/api/build/v1" + imgv1 "github.com/openshift/api/image/v1" + routev1 "github.com/openshift/api/route/v1" + coreappsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + rbac "k8s.io/api/rbac/v1" + eventing "knative.dev/eventing/pkg/apis/eventing/v1" + sources "knative.dev/eventing/pkg/apis/sources/v1" + + sonata "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + hyperfoil "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/api/hyperfoil/v1alpha2" + grafana "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/grafana/v1alpha1" + infinispan "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/infinispan/v1" + kafka "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/kafka/v1beta2" + keycloak "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/keycloak/v1alpha1" + mongodb "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework/infrastructure/mongodb/v1" + + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + + olmapiv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1" + olmapiv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1" + olmv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/apis/operators/v1" + prometheus "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" +) + +// GetRegisteredSchema gets all schema and types registered for use with CLI, unit tests, custom clients and so on +func GetRegisteredSchema() *runtime.Scheme { + s := runtime.NewScheme() + schemes := getRegisteredSchemeBuilder() + err := schemes.AddToScheme(s) + if err != nil { + panic(err) + } + + // After upgrading to Operator SDK 0.11.0 we need to add CreateOptions to our own schema. See: https://issues.jboss.org/browse/KOGITO-493 + // https://issues.jboss.org/browse/KOGITO-617 + metav1.AddToGroupVersion(s, apiextensionsv1.SchemeGroupVersion) + metav1.AddToGroupVersion(s, appsv1.GroupVersion) + metav1.AddToGroupVersion(s, prometheus.SchemeGroupVersion) + metav1.AddToGroupVersion(s, routev1.GroupVersion) + metav1.AddToGroupVersion(s, infinispan.SchemeGroupVersion) + metav1.AddToGroupVersion(s, mongodb.SchemeBuilder.GroupVersion) + metav1.AddToGroupVersion(s, kafka.SchemeGroupVersion) + metav1.AddToGroupVersion(s, grafana.GroupVersion) + metav1.AddToGroupVersion(s, eventing.SchemeGroupVersion) + metav1.AddToGroupVersion(s, sources.SchemeGroupVersion) + metav1.AddToGroupVersion(s, hyperfoil.GroupVersion) + metav1.AddToGroupVersion(s, olmapiv1.SchemeGroupVersion) + metav1.AddToGroupVersion(s, olmapiv1alpha1.SchemeGroupVersion) + metav1.AddToGroupVersion(s, olmv1.SchemeGroupVersion) + return s +} + +// getRegisteredSchemeBuilder gets the SchemeBuilder with all the desired APIs registered +func getRegisteredSchemeBuilder() runtime.SchemeBuilder { + return runtime.NewSchemeBuilder( + sonata.AddToScheme, + clientgoscheme.AddToScheme, + corev1.AddToScheme, + coreappsv1.AddToScheme, + buildv1.Install, + rbac.AddToScheme, + appsv1.Install, + coreappsv1.AddToScheme, + routev1.Install, + imgv1.Install, + apiextensionsv1.AddToScheme, + kafka.SchemeBuilder.AddToScheme, + mongodb.SchemeBuilder.AddToScheme, + infinispan.AddToScheme, + keycloak.SchemeBuilder.AddToScheme, + prometheus.SchemeBuilder.AddToScheme, + eventing.AddToScheme, sources.AddToScheme, + grafana.AddToScheme, + hyperfoil.AddToScheme, + olmapiv1alpha1.AddToScheme, + olmapiv1.AddToScheme, + olmv1.AddToScheme, + // Required for MogoDB, can be removed once we start using newer MongoDB operator version + apiextensionsv1beta1.AddToScheme) +} diff --git a/packages/kogito-serverless-operator/testbdd/scripts/prune_namespaces.go b/packages/kogito-serverless-operator/testbdd/scripts/prune_namespaces.go new file mode 100644 index 00000000000..8308d034ad3 --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/scripts/prune_namespaces.go @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +func main() { + if err := framework.PruneNamespaces(); err != nil { + panic(err) + } +} diff --git a/packages/kogito-serverless-operator/testbdd/steps/data.go b/packages/kogito-serverless-operator/testbdd/steps/data.go new file mode 100644 index 00000000000..dd049d85dc5 --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/steps/data.go @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "strconv" + "time" + + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + kogitoSteps "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/steps" +) + +// Data contains all data needed by Gherkin steps to run +type Data struct { + *kogitoSteps.Data +} + +// RegisterAllSteps register all steps available to the test suite +func (data *Data) RegisterAllSteps(ctx *godog.ScenarioContext) { + registerOperatorSteps(ctx, data) + registerPlatformSteps(ctx, data) + registerSonataFlowSteps(ctx, data) + registerKubernetesSteps(ctx, data) + + // Used for debugging + ctx.Step(`^Wait (\d+) seconds?$`, data.waitSeconds) +} + +func (data *Data) waitSeconds(seconds int) error { + framework.GetMainLogger().Info("Waiting for " + strconv.Itoa(seconds) + " s") + _ = <-time.After(time.Duration(seconds) * time.Second) + return nil +} diff --git a/packages/kogito-serverless-operator/testbdd/steps/kubernetes.go b/packages/kogito-serverless-operator/testbdd/steps/kubernetes.go new file mode 100644 index 00000000000..29721b430b0 --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/steps/kubernetes.go @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" +) + +func registerKubernetesSteps(ctx *godog.ScenarioContext, data *Data) { + // Added step to the one from the Kogito framework to be able to use quotes inside the text + ctx.Step(`^Deployment "([^"]*)" pods log contains text '([^']*)' within (\d+) minutes$`, data.deploymentPodsLogContainsTextWithinMinutes) +} + +func (data *Data) deploymentPodsLogContainsTextWithinMinutes(dName, logText string, timeoutInMin int) error { + return framework.WaitForAllPodsByDeploymentToContainTextInLog(data.Namespace, dName, logText, timeoutInMin) +} diff --git a/packages/kogito-serverless-operator/testbdd/steps/operator.go b/packages/kogito-serverless-operator/testbdd/steps/operator.go new file mode 100644 index 00000000000..c83eb4e578c --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/steps/operator.go @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "fmt" + + "github.com/cucumber/godog" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/testbdd/installers" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/config" + kogitoInstallers "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/installers" +) + +func registerOperatorSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^SonataFlow Operator is deployed$`, data.sonataFlowOperatorIsDeployed) + // Unused currently + //ctx.Step(`^SonataFlow Operator has (\d+) (?:pod|pods) running"$`, data.sonataFlowOperatorHasPodsRunning) + // Not migrated yet + //ctx.Step(`^Kogito operator should be installed$`, data.kogitoOperatorShouldBeInstalled) + //ctx.Step(`^CLI install Kogito operator$`, data.cliInstallKogitoOperator) +} + +func (data *Data) sonataFlowOperatorIsDeployed() (err error) { + var installer kogitoInstallers.ServiceInstaller + if config.UseProductOperator() { + installer, err = &kogitoInstallers.YamlClusterWideServiceInstaller{}, fmt.Errorf("OLM is not supported by the steps yet") + } else { + installer, err = installers.GetSonataFlowInstaller() + } + if err != nil { + return err + } + return installer.Install(data.Namespace) +} + +//func (data *Data) sonataFlowOperatorHasPodsRunning(numberOfPods int, name, phase string) error { +// return framework.WaitForPodsWithLabel(data.Namespace, "control-plane", "sonataflow-operator", numberOfPods, 1) +//} +// +//func (data *Data) kogitoOperatorShouldBeInstalled() error { +// return framework.WaitForKogitoOperatorRunning(data.Namespace) +//} +// +//func (data *Data) cliInstallKogitoOperator() error { +// _, err := framework.ExecuteCliCommandInNamespace(data.Namespace, "install", "operator") +// return err +//} diff --git a/packages/kogito-serverless-operator/testbdd/steps/sonataflow.go b/packages/kogito-serverless-operator/testbdd/steps/sonataflow.go new file mode 100644 index 00000000000..69d29756fc9 --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/steps/sonataflow.go @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "fmt" + "net/url" + "path/filepath" + "strings" + + "github.com/cucumber/godog" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test/utils" +) + +func registerSonataFlowSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^SonataFlow orderprocessing example is deployed$`, data.sonataFlowOrderProcessingExampleIsDeployed) + ctx.Step(`^SonataFlow "([^"]*)" has the condition "(Running|Succeed|Built)" set to "(True|False|Unknown)" within (\d+) minutes?$`, data.sonataFlowHasTheConditionSetToWithinMinutes) + ctx.Step(`^SonataFlow "([^"]*)" is addressable within (\d+) minutes?$`, data.sonataFlowIsAddressableWithinMinutes) + ctx.Step(`^HTTP POST request as Cloud Event on SonataFlow "([^"]*)" is successful within (\d+) minutes? with path "([^"]*)", headers "([^"]*)" and body:$`, data.httpPostRequestAsCloudEventOnSonataFlowIsSuccessfulWithinMinutesWithPathHeadersAndBody) +} + +func (data *Data) sonataFlowOrderProcessingExampleIsDeployed() error { + projectDir, _ := utils.GetProjectDir() + projectDir = strings.Replace(projectDir, "/testbdd", "", -1) + + // TODO or kubectl + out, err := framework.CreateCommand("oc", "apply", "-f", filepath.Join(projectDir, + test.GetSonataFlowE2eOrderProcessingFolder()), "-n", data.Namespace).Execute() + + if err != nil { + framework.GetLogger(data.Namespace).Error(err, fmt.Sprintf("Applying SonataFlow failed, output: %s", out)) + } + return err +} + +func (data *Data) sonataFlowHasTheConditionSetToWithinMinutes(name, conditionType, conditionStatus string, timeoutInMin int) error { + return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("SonataFlow %s has the condition %s with status %s", name, conditionType, conditionStatus), timeoutInMin, + func() (bool, error) { + if sonataFlow, err := getSonataFlow(data.Namespace, name); err != nil { + return false, err + } else if sonataFlow == nil { + return false, nil + } else { + condition := sonataFlow.Status.GetCondition(api.ConditionType(conditionType)) + return condition != nil && condition.Status == v1.ConditionStatus(conditionStatus), nil + } + }) +} + +func (data *Data) sonataFlowIsAddressableWithinMinutes(name string, timeoutInMin int) error { + return framework.WaitForOnOpenshift(data.Namespace, fmt.Sprintf("SonataFlow %s is addressable", name), timeoutInMin, + func() (bool, error) { + sonataFlow, err := getSonataFlow(data.Namespace, name) + if err != nil { + return false, err + } else if sonataFlow == nil { + return false, fmt.Errorf("No SonataFlow found with name %s in namespace %s", name, data.Namespace) + } + + if sonataFlow.Status.Address.URL == nil { + return false, fmt.Errorf("SonataFlow %s does NOT have an address", name) + } + + if _, err := url.ParseRequestURI(sonataFlow.Status.Address.URL.String()); err != nil { + return false, fmt.Errorf("SonataFlow %s address '%s' is not valid: %w", name, sonataFlow.Status.Address.URL, err) + } + + return true, nil + }) +} + +func getSonataFlow(namespace, name string) (*v1alpha08.SonataFlow, error) { + sonataFlow := &v1alpha08.SonataFlow{} + if exists, err := framework.GetObjectWithKey(types.NamespacedName{Namespace: namespace, Name: name}, sonataFlow); err != nil { + return nil, fmt.Errorf("Error while trying to look for SonataFlow %s: %w ", name, err) + } else if !exists { + return nil, nil + } + return sonataFlow, nil +} + +func (data *Data) httpPostRequestAsCloudEventOnSonataFlowIsSuccessfulWithinMinutesWithPathHeadersAndBody(name string, timeoutInMin int, path, headersContent string, body *godog.DocString) error { + path = data.ResolveWithScenarioContext(path) + bodyContent := data.ResolveWithScenarioContext(body.Content) + framework.GetLogger(data.Namespace).Debug("httpPostRequestAsCloudEventOnSonataFlowIsSuccessfulWithinMinutesWithPathHeadersAndBody", "sonataflow", name, "path", path, "bodyMediaType", body.MediaType, "bodyContent", bodyContent, "timeout", timeoutInMin) + sonataFlow, err := getSonataFlow(data.Namespace, name) + if err != nil { + return err + } else if sonataFlow == nil { + return fmt.Errorf("No SonataFlow found with name %s in namespace %s", name, data.Namespace) + } + sonataFlowUri := sonataFlow.Status.Endpoint + uri := strings.TrimSuffix(sonataFlowUri.String(), sonataFlowUri.Path) + headers, err := parseHeaders(headersContent) + if err != nil { + return err + } + + requestInfo := framework.NewPOSTHTTPRequestInfoWithHeaders(uri, path, headers, body.MediaType, bodyContent) + return framework.WaitForSuccessfulHTTPRequest(data.Namespace, requestInfo, timeoutInMin) +} + +func parseHeaders(headersContent string) (map[string]string, error) { + headers := make(map[string]string) + + for _, headerEntry := range strings.Split(headersContent, ",") { + keyValuePair := strings.Split(headerEntry, "=") + + if len(keyValuePair) == 1 { + return nil, fmt.Errorf("Header key and value need to be separated by `=`, parsed header: %s", headerEntry) + } + if len(keyValuePair) > 2 { + return nil, fmt.Errorf("Found multiple `=` in parsed header: %s", headerEntry) + } + + headers[keyValuePair[0]] = strings.TrimSpace(keyValuePair[1]) + } + + return headers, nil +} diff --git a/packages/kogito-serverless-operator/testbdd/steps/sonataflowplatform.go b/packages/kogito-serverless-operator/testbdd/steps/sonataflowplatform.go new file mode 100644 index 00000000000..b03fd7a2be5 --- /dev/null +++ b/packages/kogito-serverless-operator/testbdd/steps/sonataflowplatform.go @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package steps + +import ( + "fmt" + "path/filepath" + "strings" + + "github.com/cucumber/godog" + + framework "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/bddframework/pkg/framework" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test/utils" + + //"github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/test" + "os" +) + +const ( + minikubePlatform = "minikube" + openshiftPlatform = "openshift" +) + +func registerPlatformSteps(ctx *godog.ScenarioContext, data *Data) { + ctx.Step(`^SonataFlowPlatform is deployed$`, data.sonataFlowPlatformIsDeployed) +} + +func (data *Data) sonataFlowPlatformIsDeployed() error { + projectDir, _ := utils.GetProjectDir() + projectDir = strings.Replace(projectDir, "/testbdd", "", -1) + + // TODO or kubectl + out, err := framework.CreateCommand("oc", "apply", "-f", filepath.Join(projectDir, getSonataFlowPlatformFilename()), "-n", data.Namespace).Execute() + + if err != nil { + framework.GetLogger(data.Namespace).Error(err, fmt.Sprintf("Applying SonataFlowPlatform failed, output: %s", out)) + } + + return err +} + +func getSonataFlowPlatformFilename() string { + if getClusterPlatform() == openshiftPlatform { + return test.GetPlatformOpenshiftE2eTest() + } + return test.GetPlatformMinikubeE2eTest() +} + +func getClusterPlatform() string { + if v, ok := os.LookupEnv("CLUSTER_PLATFORM"); ok { + return v + } + return minikubePlatform +} diff --git a/packages/kogito-serverless-operator/utils/client.go b/packages/kogito-serverless-operator/utils/client.go new file mode 100644 index 00000000000..9b1cd085687 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/client.go @@ -0,0 +1,32 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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 "sigs.k8s.io/controller-runtime/pkg/client" + +var k8sClient client.Client + +// TODO: consider refactor the internals as we progress adding features to rely on this client instead of passing it through all the functions + +// GetClient default client created by the main operator's thread. +// It's safe to use since it's set when the operator main function runs. +func GetClient() client.Client { + return k8sClient +} + +// SetClient is meant for internal use only. Don't call it! +func SetClient(client client.Client) { + k8sClient = client +} diff --git a/packages/kogito-serverless-operator/utils/cluster.go b/packages/kogito-serverless-operator/utils/cluster.go new file mode 100644 index 00000000000..8df5de313b1 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/cluster.go @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "github.com/RHsyseng/operator-utils/pkg/utils/openshift" + "k8s.io/client-go/rest" +) + +var isOpenShift = false + +// IsOpenShift is a global flag that can be safely called across reconciliation cycles, defined at the controller manager start. +func IsOpenShift() bool { + return isOpenShift +} + +// SetIsOpenShift sets the global flag isOpenShift by the controller manager. +// We don't need to keep fetching the API every reconciliation cycle that we need to know about the platform. +func SetIsOpenShift(cfg *rest.Config) { + var err error + isOpenShift, err = openshift.IsOpenShift(cfg) + if err != nil { + panic("Impossible to verify if the cluster is OpenShift or not: " + err.Error()) + } +} diff --git a/packages/kogito-serverless-operator/utils/common.go b/packages/kogito-serverless-operator/utils/common.go new file mode 100644 index 00000000000..5028ffc3fd6 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/common.go @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "os" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" +) + +const ( + HttpScheme = "http" +) + +// 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 +} + +// Pint returns a pointer to an int +func Pint(i int32) *int32 { + return &i +} + +func Compare(a, b []byte) bool { + a = append(a, b...) + c := 0 + for _, x := range a { + c ^= int(x) + } + return c == 0 +} + +func GetEnv(key, fallback string) string { + value := os.Getenv(key) + if len(value) == 0 { + return fallback + } + return value +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/annotations.go b/packages/kogito-serverless-operator/utils/kubernetes/annotations.go new file mode 100644 index 00000000000..71e1937c626 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/annotations.go @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + "strconv" + + "k8s.io/klog/v2" + + "sigs.k8s.io/controller-runtime/pkg/client" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" +) + +func getWorkflow(namespace string, name string, c client.Client, ctx context.Context) *operatorapi.SonataFlow { + serverlessWorkflowType := &operatorapi.SonataFlow{} + serverlessWorkflowType.Namespace = namespace + serverlessWorkflowType.Name = name + serverlessWorkflow := &operatorapi.SonataFlow{} + if err := c.Get(ctx, client.ObjectKeyFromObject(serverlessWorkflowType), serverlessWorkflow); err != nil { + klog.V(log.E).ErrorS(err, "unable to retrieve SonataFlow definition") + } + return serverlessWorkflow +} + +func GetLastGeneration(namespace string, name string, c client.Client, ctx context.Context) int64 { + workflow := getWorkflow(namespace, name, c, ctx) + return workflow.Generation +} + +// GetAnnotationAsBool returns the boolean value from the given annotation. +// If the annotation is not present or is there an error in the ParseBool conversion, returns false. +func GetAnnotationAsBool(object client.Object, key string) bool { + if object.GetAnnotations() != nil { + b, err := strconv.ParseBool(object.GetAnnotations()[key]) + if err != nil { + return false + } + return b + } + return false +} + +// SetAnnotation Safely set the annotation to the object +func SetAnnotation(object client.Object, key, value string) { + if object.GetAnnotations() != nil { + object.GetAnnotations()[key] = value + } else { + object.SetAnnotations(map[string]string{key: value}) + } +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/collection.go b/packages/kogito-serverless-operator/utils/kubernetes/collection.go new file mode 100644 index 00000000000..adecfe6b2ae --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/collection.go @@ -0,0 +1,399 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + + ctrl "sigs.k8s.io/controller-runtime/pkg/client" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/utils/kubernetes/deployment.go b/packages/kogito-serverless-operator/utils/kubernetes/deployment.go new file mode 100644 index 00000000000..df86256182c --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/deployment.go @@ -0,0 +1,205 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + "time" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/log" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj" + appsv1 "k8s.io/api/apps/v1" + v1 "k8s.io/api/core/v1" + "k8s.io/klog/v2" +) + +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 + } +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/deployment_failure.go b/packages/kogito-serverless-operator/utils/kubernetes/deployment_failure.go new file mode 100644 index 00000000000..d4a58327b0e --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/deployment_failure.go @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/labels" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ( + containerReasonContainerCreating = "ContainerCreating" +) + +var _ DeploymentUnavailabilityReader = &deploymentUnavailabilityReader{} + +// DeploymentUnavailabilityReader implementations find the reason behind a deployment failure +type DeploymentUnavailabilityReader interface { + // ReasonMessage returns the reason message in string format fetched from the culprit resource. For example, a Container status. + ReasonMessage() (string, error) +} + +// DeploymentTroubleshooter creates a new DeploymentUnavailabilityReader for finding out why a deployment failed +func DeploymentTroubleshooter(client client.Client, deployment *v1.Deployment, container string) DeploymentUnavailabilityReader { + return &deploymentUnavailabilityReader{ + c: client, + deployment: deployment, + container: container, + } +} + +type deploymentUnavailabilityReader struct { + c client.Client + deployment *v1.Deployment + container string +} + +// ReasonMessage tries to find a human-readable reason message for why the deployment is not available or in a failed state. +// This implementation fetches the given container status for this information. +// Returning an empty string means that no reason has been found in the underlying pods. +// +// See: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-states +// +// Future implementations might look in other objects for a more specific reason. +// Additionally, future work might involve returning a typed Reason, so controllers may take actions depending on what have happened. +func (d deploymentUnavailabilityReader) ReasonMessage() (string, error) { + podList := &corev1.PodList{} + // ideally we should get the latest replicaset, then the pods. + // problem is that we don't have a reliable field to get this information, + // it's in a message within the deployment status + // since this use case is only to show the deployment problem for user's troubleshooting, it's ok showing all of them. + // additionally, we are using a unique label identifier for matching + opts := &client.ListOptions{ + LabelSelector: labels.SelectorFromSet(d.deployment.Spec.Selector.MatchLabels), + Namespace: d.deployment.Namespace, + } + + if err := d.c.List(context.TODO(), podList, opts); err != nil { + return "", err + } + + for _, pod := range podList.Items { + if pod.Status.Phase == corev1.PodRunning || pod.Status.Phase == corev1.PodSucceeded { + continue + } + for _, container := range pod.Status.ContainerStatuses { + if container.Name == d.container { + if !container.Ready { + if container.State.Waiting != nil && container.State.Waiting.Reason != containerReasonContainerCreating { + return fmt.Sprintf("ContainerNotReady: (%s) %s", container.State.Waiting.Reason, container.State.Waiting.Message), nil + } + if container.State.Terminated != nil && container.State.Terminated.ExitCode > 0 { + return fmt.Sprintf("ContainerNotReady: (%s) %s", container.State.Terminated.Reason, container.State.Terminated.Message), nil + } + } + } + } + } + + return "", nil +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/env.go b/packages/kogito-serverless-operator/utils/kubernetes/env.go new file mode 100644 index 00000000000..5ca80656a2d --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/env.go @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 v1 "k8s.io/api/core/v1" + +func CreateOrReplaceEnv(container *v1.Container, name, value string) { + found := false + for i := range container.Env { + if container.Env[i].Name == name { + container.Env[i].Value = value + found = true + } + } + if !found { + container.Env = append(container.Env, v1.EnvVar{ + Name: name, + Value: value, + }) + } +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/env_test.go b/packages/kogito-serverless-operator/utils/kubernetes/env_test.go new file mode 100644 index 00000000000..d209edd6b12 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/env_test.go @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "testing" + + "github.com/stretchr/testify/assert" + appsv1 "k8s.io/api/apps/v1" + v1 "k8s.io/api/core/v1" +) + +func TestCreateOrReplaceEnv(t *testing.T) { + containerNoEnv := &appsv1.Deployment{ + Spec: appsv1.DeploymentSpec{ + Template: v1.PodTemplateSpec{ + Spec: v1.PodSpec{ + Containers: []v1.Container{{Env: nil}}, + }, + }, + }, + } + containerWithEnv := &appsv1.Deployment{ + Spec: appsv1.DeploymentSpec{ + Template: v1.PodTemplateSpec{ + Spec: v1.PodSpec{ + Containers: []v1.Container{{Env: []v1.EnvVar{{ + Name: "myvar", + Value: "myvalue", + }}}}, + }, + }, + }, + } + + CreateOrReplaceEnv(&containerNoEnv.Spec.Template.Spec.Containers[0], "myvar", "mutated") + assert.Equal(t, "mutated", containerNoEnv.Spec.Template.Spec.Containers[0].Env[0].Value) + + CreateOrReplaceEnv(&containerWithEnv.Spec.Template.Spec.Containers[0], "myvar", "mutated") + assert.Equal(t, "mutated", containerWithEnv.Spec.Template.Spec.Containers[0].Env[0].Value) +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/image.go b/packages/kogito-serverless-operator/utils/kubernetes/image.go new file mode 100644 index 00000000000..93c317c72b7 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/image.go @@ -0,0 +1,51 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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 ( + "strings" + + corev1 "k8s.io/api/core/v1" +) + +// GetImagePullPolicy gets the default corev1.PullPolicy depending on the image tag specified. +// It follows the conventions of docker client and OpenShift. If no tag specified, it assumes latest. +// Returns PullAlways if latest tag, empty otherwise to let the cluster figure it out. +// See: https://kubernetes.io/docs/concepts/containers/images/#updating-images +func GetImagePullPolicy(imageTag string) corev1.PullPolicy { + if len(imageTag) == 0 { + return "" + } + idx := strings.LastIndex(imageTag, ":") + if idx < 0 { + return corev1.PullAlways + } + if GetImageTag(imageTag) == "latest" { + return corev1.PullAlways + } + return "" +} + +// GetImageTag gets the tag after `:` in an image tag or empty if not found. +func GetImageTag(imageTag string) string { + if len(imageTag) == 0 { + return "" + } + idx := strings.LastIndex(imageTag, ":") + if idx < 0 { + return "" + } + return imageTag[idx+1:] +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/image_test.go b/packages/kogito-serverless-operator/utils/kubernetes/image_test.go new file mode 100644 index 00000000000..e9a4b07315f --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/image_test.go @@ -0,0 +1,47 @@ +// Copyright 2024 Apache Software Foundation (ASF) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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 ( + "testing" + + "github.com/stretchr/testify/assert" + v1 "k8s.io/api/core/v1" +) + +func TestGetImagePullPolicy(t *testing.T) { + type args struct { + imageTag string + } + tests := []struct { + name string + args args + want v1.PullPolicy + }{ + {"Short name with latest", args{"ubi9-micro:latest"}, v1.PullAlways}, + {"Long name with latest", args{"gcr.io/knative-releases/knative.dev/eventing/cmd/event_display:latest"}, v1.PullAlways}, + {"No tag specified", args{"ubi9-micro"}, v1.PullAlways}, + {"Short name with tag", args{"ubi9-micro:9.3.1-2"}, ""}, + {"Long name with tag", args{"gcr.io/knative-releases/knative.dev/eventing/cmd/event_display:1.2"}, ""}, + {"Empty tag", args{""}, ""}, + {"Messy tag", args{":"}, ""}, + {"Sha tag", args{"ubuntu@sha256:3235326357dfb65f1781dbc4df3b834546d8bf914e82cce58e6e6b676e23ce8f"}, ""}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, GetImagePullPolicy(tt.args.imageTag), "GetImagePullPolicy(%v)", tt.args.imageTag) + }) + } +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/loader.go b/packages/kogito-serverless-operator/utils/kubernetes/loader.go new file mode 100644 index 00000000000..9b088d0b9d6 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/loader.go @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "encoding/json" + "fmt" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/util/yaml" + ctrl "sigs.k8s.io/controller-runtime/pkg/client" +) + +// LoadResourceFromYaml returns a Kubernetes resource from its serialized YAML definition. +func LoadResourceFromYaml(scheme *runtime.Scheme, data string) (ctrl.Object, error) { + source := []byte(data) + jsonSource, err := yaml.ToJSON(source) + if err != nil { + return nil, err + } + u := unstructured.Unstructured{} + err = u.UnmarshalJSON(jsonSource) + if err != nil { + return nil, err + } + ro, err := runtimeObjectFromUnstructured(scheme, &u) + if err != nil { + return nil, err + } + o, ok := ro.(ctrl.Object) + if !ok { + return nil, fmt.Errorf("type assertion failed: %v", ro) + } + + return o, nil +} + +// LoadUnstructuredFromYaml returns an unstructured resource from its serialized YAML definition. +func LoadUnstructuredFromYaml(data string) (ctrl.Object, error) { + source, err := yaml.ToJSON([]byte(data)) + if err != nil { + return nil, err + } + var obj map[string]interface{} + if err = json.Unmarshal(source, &obj); err != nil { + return nil, err + } + return &unstructured.Unstructured{ + Object: obj, + }, nil +} + +func runtimeObjectFromUnstructured(scheme *runtime.Scheme, u *unstructured.Unstructured) (runtime.Object, error) { + gvk := u.GroupVersionKind() + codecs := serializer.NewCodecFactory(scheme) + decoder := codecs.UniversalDecoder(gvk.GroupVersion()) + + b, err := u.MarshalJSON() + if err != nil { + return nil, fmt.Errorf("error running MarshalJSON on unstructured object: %w", err) + } + ro, _, err := decoder.Decode(b, &gvk, nil) + if err != nil { + return nil, fmt.Errorf("failed to decode json data with gvk(%v): %w", gvk.String(), err) + } + return ro, nil +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/naming.go b/packages/kogito-serverless-operator/utils/kubernetes/naming.go new file mode 100644 index 00000000000..9f78df375f9 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/naming.go @@ -0,0 +1,49 @@ +// Copyright 2023 Red Hat, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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 ( + "fmt" + + "k8s.io/apimachinery/pkg/api/validation" + "k8s.io/apimachinery/pkg/util/rand" +) + +const dns1035MaxChar int = 63 + +// SafeDNS1035 generates a safe encoded string based on "s" with the given prefix. +// Ideally used with internal generated names. +// +// See https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#rfc-1035-label-names +func SafeDNS1035(prefix, s string) (string, error) { + safeNaming := prefix + rand.SafeEncodeString(s) + if len(safeNaming) > dns1035MaxChar { + safeNaming = safeNaming[:dns1035MaxChar] + } + errMsgs := validation.NameIsDNS1035Label(safeNaming, false) + if len(errMsgs) > 0 { + return "", fmt.Errorf("failed to generate a safe name for %s with prefix %s: %v", s, prefix, errMsgs) + } + return safeNaming, nil +} + +// MustSafeDNS1035 see SafeDNS1035. Use this function only if you control the prefix. +func MustSafeDNS1035(prefix, s string) string { + name, err := SafeDNS1035(prefix, s) + if err != nil { + panic(err) + } + return name +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/naming_test.go b/packages/kogito-serverless-operator/utils/kubernetes/naming_test.go new file mode 100644 index 00000000000..4c2697f52e3 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/naming_test.go @@ -0,0 +1,27 @@ +// Copyright 2023 Red Hat, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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 ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMustSafeDNS1035_EnsureEquality(t *testing.T) { + s1 := MustSafeDNS1035("prefix-", "bananas") + s2 := MustSafeDNS1035("prefix-", "bananas") + assert.Equal(t, s1, s2) +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/object.go b/packages/kogito-serverless-operator/utils/kubernetes/object.go new file mode 100644 index 00000000000..d536d87526d --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/object.go @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + v1 "k8s.io/api/core/v1" + ctrl "sigs.k8s.io/controller-runtime/pkg/client" +) + +// IsObjectNew verifies if the given object hasn't been created in the cluster +func IsObjectNew(object ctrl.Object) bool { + // UID should be enough, but we check for resourceVersion because the Fake client won't set UIDs, failing our tests + return len(object.GetUID()) == 0 && len(object.GetResourceVersion()) == 0 +} + +// ToTypedLocalReference ... +func ToTypedLocalReference(object ctrl.Object) *v1.TypedLocalObjectReference { + apiGroup := object.GetObjectKind().GroupVersionKind().GroupVersion().String() + return &v1.TypedLocalObjectReference{ + APIGroup: &apiGroup, + Kind: object.GetObjectKind().GroupVersionKind().Kind, + Name: object.GetName(), + } + +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/replace.go b/packages/kogito-serverless-operator/utils/kubernetes/replace.go new file mode 100644 index 00000000000..ff8c5eb7105 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/replace.go @@ -0,0 +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. + */ + +package kubernetes + +import ( + "context" + "fmt" + + client "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/utils/kubernetes/security.go b/packages/kogito-serverless-operator/utils/kubernetes/security.go new file mode 100644 index 00000000000..794da250bdb --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/security.go @@ -0,0 +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. + */ + +package kubernetes + +import ( + corev1 "k8s.io/api/core/v1" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" +) + +func SecurityDefaults() *corev1.SecurityContext { + return &corev1.SecurityContext{ + AllowPrivilegeEscalation: utils.Pbool(false), + Privileged: utils.Pbool(false), + RunAsNonRoot: utils.Pbool(true), + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + }, + } +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/service.go b/packages/kogito-serverless-operator/utils/kubernetes/service.go new file mode 100644 index 00000000000..53deb202fce --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/service.go @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "net/url" + + v1 "k8s.io/api/core/v1" + "knative.dev/pkg/apis" +) + +// TODO: retrieve the cluster domain from the /etc/resolve inside the pod or from the Platform CRD - will be addressed by KOGITO-9198 +var defaultClusterDomain = "svc.cluster.local" + +// retrieveServiceHost function that based on the service name, namespace and eventually the nodeport, will provide the service URI +func retrieveServiceHost(service *v1.Service) string { + namespace := service.Namespace + if len(namespace) == 0 { + namespace = "default" + } + // TODO: Retrieve the cluster domain or use the default one + return service.Name + "." + namespace + "." + defaultClusterDomain +} + +// 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{ + Scheme: "http", + Host: retrieveServiceHost(service), + Path: service.Name} + return apis.ParseURL(url.String()) +} + +// GetServicePortByName returns a pointer to the ServicePort within the given Service. +// If none found, returns nil. +// It also returns the position where the service port por was found, -1 if none. +func GetServicePortByName(name string, service *v1.Service) (*v1.ServicePort, int) { + if service == nil { + return nil, -1 + } + for i, servicePort := range service.Spec.Ports { + if name == servicePort.Name { + return &servicePort, i + } + } + return nil, -1 +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/service_test.go b/packages/kogito-serverless-operator/utils/kubernetes/service_test.go new file mode 100644 index 00000000000..793a343398d --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/service_test.go @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "testing" + + "github.com/stretchr/testify/assert" + v1 "k8s.io/api/core/v1" +) + +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" + host := retrieveServiceHost(svc) + + assert.NotNil(t, host) + assert.Equal(t, host, svc.Name+".default.svc.cluster.local") + + }) + + 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.Namespace = "ns" + host := retrieveServiceHost(svc) + + assert.NotNil(t, host) + assert.Equal(t, host, svc.Name+"."+svc.Namespace+".svc.cluster.local") + + }) +} + +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) + + url, err := RetrieveServiceURL(svc) + + assert.NoError(t, err) + assert.NotNil(t, url) + assert.Equal(t, url.String(), "http://"+svc.Name+".default.svc.cluster.local/"+svc.Name) + + }) + + 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.Namespace = "ns" + RetrieveServiceURL(svc) + + url, err := RetrieveServiceURL(svc) + + assert.NoError(t, err) + assert.NotNil(t, url) + assert.Equal(t, url.String(), "http://"+svc.Name+"."+svc.Namespace+".svc.cluster.local/"+svc.Name) + + }) + +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/volumes.go b/packages/kogito-serverless-operator/utils/kubernetes/volumes.go new file mode 100644 index 00000000000..71b56d62022 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/volumes.go @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" +) + +// VolumeProjectionAddConfigMap adds the given ConfigMap to the ProjectedVolumeSource sources. +// Overrides the items if already exists in the list. +func VolumeProjectionAddConfigMap(volumeSource *corev1.ProjectedVolumeSource, cmName string, items ...corev1.KeyToPath) { + for _, source := range volumeSource.Sources { + if source.ConfigMap.Name == cmName { + source.ConfigMap.Items = items + return + } + } + + volumeSource.Sources = append(volumeSource.Sources, corev1.VolumeProjection{ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{Name: cmName}, + Items: items, + }}) + +} + +// VolumeAddVolumeProjectionConfigMap adds a new ConfigMapProjection to the given Volume array. +// It looks for the given mount name in the Volume array. +// If finds it, adds a new projection for the given ConfigMap. +// If it doesn't find it, adds a new VolumeSource and the projection to it. +func VolumeAddVolumeProjectionConfigMap(volumes []corev1.Volume, cmName, mountName string) []corev1.Volume { + resourceProjection := + corev1.VolumeProjection{ConfigMap: &corev1.ConfigMapProjection{LocalObjectReference: corev1.LocalObjectReference{Name: cmName}}} + projectionExists := false + for i, vol := range volumes { + if vol.Name == mountName { + volumes[i].Projected.Sources = + append(volumes[i].Projected.Sources, resourceProjection) + projectionExists = true + } + } + if !projectionExists { + volumes = append(volumes, + corev1.Volume{ + Name: mountName, + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{Sources: []corev1.VolumeProjection{resourceProjection}}}}) + } + return volumes +} + +// VolumeConfigMap creates a new Volume referencing the given ConfigMap name. +func VolumeConfigMap(name string, cmName string, items ...corev1.KeyToPath) corev1.Volume { + return corev1.Volume{ + Name: name, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{Name: cmName}, + Items: items, + }, + }, + } +} + +func VolumeMount(name string, readonly bool, mountPath string) corev1.VolumeMount { + return corev1.VolumeMount{ + Name: name, + ReadOnly: readonly, + MountPath: mountPath, + } +} + +// VolumeMountAdd adds a new VolumeMount to the given collection. +// If there's already a VolumeMount with the same mount path, the function overrides the name. +func VolumeMountAdd(volumeMount []corev1.VolumeMount, name, mountPath string) []corev1.VolumeMount { + for _, v := range volumeMount { + if v.MountPath == mountPath { + v.Name = name + return volumeMount + } + } + return append(volumeMount, corev1.VolumeMount{Name: name, MountPath: mountPath}) +} + +// AddOrReplaceVolume adds or removes the given volumes to the PodSpec. +// If there's already a volume with the same name, it's replaced. +func AddOrReplaceVolume(podSpec *corev1.PodSpec, volumes ...corev1.Volume) { + // volumes iterated here are read/constructed by the caller following the order defined in the original CRD, and that + // order must be preserved. If not preserved, in the reconciliation cycles an order change in the volumes might be + // interpreted as configuration change in the original resource, causing undesired side effects like creating + // a new ReplicaSet for a deployment with the subsequent pods spawning reported here. + volumesToAdd := make([]corev1.Volume, 0) + wasAdded := false + for _, volume := range volumes { + wasAdded = false + for i := 0; !wasAdded && i < len(podSpec.Volumes); i++ { + if volume.Name == podSpec.Volumes[i].Name { + // replace existing + podSpec.Volumes[i] = volume + wasAdded = true + } + } + if !wasAdded { + // remember to add it later in order + volumesToAdd = append(volumesToAdd, volume) + } + } + for _, volume := range volumesToAdd { + podSpec.Volumes = append(podSpec.Volumes, volume) + } +} + +// AddOrReplaceVolumeMount same as AddOrReplaceVolume, but with VolumeMounts in a specific container +func AddOrReplaceVolumeMount(containerIndex int, podSpec *corev1.PodSpec, mounts ...corev1.VolumeMount) { + // analogous to AddOrReplaceVolume function, the processing must be realized en order. + // see: AddOrReplaceVolume + mountsToAdd := make([]corev1.VolumeMount, 0) + wasAdded := false + container := &podSpec.Containers[containerIndex] + for _, mount := range mounts { + wasAdded = false + for i := 0; !wasAdded && i < len(container.VolumeMounts); i++ { + if mount.Name == container.VolumeMounts[i].Name { + // replace existing + container.VolumeMounts[i] = mount + wasAdded = true + } + } + if !wasAdded { + // remember to add it later in order + mountsToAdd = append(mountsToAdd, mount) + } + } + for _, mount := range mountsToAdd { + container.VolumeMounts = append(container.VolumeMounts, mount) + } +} diff --git a/packages/kogito-serverless-operator/utils/kubernetes/volumes_test.go b/packages/kogito-serverless-operator/utils/kubernetes/volumes_test.go new file mode 100644 index 00000000000..6b296c67132 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/kubernetes/volumes_test.go @@ -0,0 +1,129 @@ +// Copyright 2023 Red Hat, Inc. and/or its affiliates +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES 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 ( + "testing" + + "github.com/stretchr/testify/assert" + v1 "k8s.io/api/core/v1" +) + +func TestReplaceOrAddVolume(t *testing.T) { + podSpec := v1.PodSpec{Volumes: []v1.Volume{ + {Name: "volume1", VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{Name: "cm1"}, + }}}, + {Name: "volume2", VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{Name: "cm2"}, + }}}, + }} + volumes := []v1.Volume{ + {Name: "volume1", VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{Name: "cmA"}, + }}}, + {Name: "volume2", VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{Name: "cmB"}, + }}}, + {Name: "volume3", VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{Name: "cmC"}, + }}}, + } + + AddOrReplaceVolume(&podSpec, volumes...) + + assert.Len(t, podSpec.Volumes, 3) + assert.Equal(t, "cmA", podSpec.Volumes[0].ConfigMap.Name) + assert.Equal(t, "cmB", podSpec.Volumes[1].ConfigMap.Name) + assert.Equal(t, "cmC", podSpec.Volumes[2].ConfigMap.Name) +} + +func TestReplaceOrAddVolume_Append(t *testing.T) { + podSpec := v1.PodSpec{Volumes: []v1.Volume{ + {Name: "volume1", VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{Name: "cm1"}, + }}}, + }} + volumes := []v1.Volume{ + {Name: "volume2", VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{Name: "cmB"}, + }}}, + } + + AddOrReplaceVolume(&podSpec, volumes...) + + assert.Len(t, podSpec.Volumes, 2) + assert.Equal(t, "cm1", podSpec.Volumes[0].ConfigMap.Name) + assert.Equal(t, "cmB", podSpec.Volumes[1].ConfigMap.Name) +} + +func TestReplaceOrAddVolume_EmptyVolumes(t *testing.T) { + podSpec := v1.PodSpec{Volumes: []v1.Volume{ + {Name: "volume1", VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{Name: "cm1"}, + }}}, + {Name: "volume2", VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{Name: "cm2"}, + }}}, + }} + var volumes []v1.Volume + + AddOrReplaceVolume(&podSpec, volumes...) + + assert.Len(t, podSpec.Volumes, 2) + assert.Equal(t, "cm1", podSpec.Volumes[0].ConfigMap.Name) + assert.Equal(t, "cm2", podSpec.Volumes[1].ConfigMap.Name) +} + +func TestReplaceOrAddVolume_EmptyPodVolumes(t *testing.T) { + podSpec := v1.PodSpec{} + volumes := []v1.Volume{ + {Name: "volume1", VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{Name: "cmA"}, + }}}, + {Name: "volume2", VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{Name: "cmB"}, + }}}, + {Name: "volume3", VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{Name: "cmC"}, + }}}, + } + + AddOrReplaceVolume(&podSpec, volumes...) + + assert.Len(t, podSpec.Volumes, 3) + assert.Equal(t, "cmA", podSpec.Volumes[0].ConfigMap.Name) + assert.Equal(t, "cmB", podSpec.Volumes[1].ConfigMap.Name) + assert.Equal(t, "cmC", podSpec.Volumes[2].ConfigMap.Name) +} + +func TestAddOrReplaceVolumeMount(t *testing.T) { + podSpec := v1.PodSpec{ + Containers: []v1.Container{ + {Name: "container1", VolumeMounts: []v1.VolumeMount{ + {Name: "mount1", MountPath: "/tmp/any/path"}, + }}, + }, + } + mounts := []v1.VolumeMount{ + {Name: "mount2", MountPath: "/tmp/any/path"}, + {Name: "mount1", MountPath: "/dev"}, + } + + AddOrReplaceVolumeMount(0, &podSpec, mounts...) + assert.Len(t, podSpec.Containers[0].VolumeMounts, 2) + assert.Equal(t, "/dev", podSpec.Containers[0].VolumeMounts[0].MountPath) + assert.Equal(t, "/tmp/any/path", podSpec.Containers[0].VolumeMounts[1].MountPath) +} diff --git a/packages/kogito-serverless-operator/utils/openshift/addscheme.go b/packages/kogito-serverless-operator/utils/openshift/addscheme.go new file mode 100644 index 00000000000..ceb33ea50dd --- /dev/null +++ b/packages/kogito-serverless-operator/utils/openshift/addscheme.go @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + buildv1 "github.com/openshift/api/build/v1" + imgv1 "github.com/openshift/api/image/v1" + routev1 "github.com/openshift/api/route/v1" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +// MustAddToScheme adds OpenShift API Scheme to the given scheme or panic. +func MustAddToScheme(s *runtime.Scheme) { + utilruntime.Must(routev1.Install(s)) + utilruntime.Must(buildv1.Install(s)) + utilruntime.Must(imgv1.Install(s)) +} diff --git a/packages/kogito-serverless-operator/utils/openshift/route.go b/packages/kogito-serverless-operator/utils/openshift/route.go new file mode 100644 index 00000000000..3d541a6fe2b --- /dev/null +++ b/packages/kogito-serverless-operator/utils/openshift/route.go @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj" + + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/utils/openshift/route_test.go b/packages/kogito-serverless-operator/utils/openshift/route_test.go new file mode 100644 index 00000000000..8c891bdea07 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/openshift/route_test.go @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/utils/properties.go b/packages/kogito-serverless-operator/utils/properties.go new file mode 100644 index 00000000000..97c3c54c228 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/properties.go @@ -0,0 +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. + */ + +package utils + +import ( + "github.com/magiconair/properties" +) + +type ApplicationPropertiesBuilder interface { + WithInitialProperties(initialProperties *properties.Properties) ApplicationPropertiesBuilder + WithImmutableProperties(immutableProperties *properties.Properties) ApplicationPropertiesBuilder + WithDefaultManagedProperties(defaultManagedProperties *properties.Properties) ApplicationPropertiesBuilder + BuildAsString() string + Build() *properties.Properties +} + +type applicationPropertiesBuilder struct { + initialProperties *properties.Properties + immutableProperties *properties.Properties + defaultManagedProperties *properties.Properties +} + +func (a *applicationPropertiesBuilder) WithInitialProperties(initialProperties *properties.Properties) ApplicationPropertiesBuilder { + a.initialProperties = initialProperties + return a +} + +func (a *applicationPropertiesBuilder) WithImmutableProperties(immutableProperties *properties.Properties) ApplicationPropertiesBuilder { + a.immutableProperties = immutableProperties + return a +} + +func (a *applicationPropertiesBuilder) WithDefaultManagedProperties(defaultManagedProperties *properties.Properties) ApplicationPropertiesBuilder { + a.defaultManagedProperties = defaultManagedProperties + return a +} + +func (a *applicationPropertiesBuilder) BuildAsString() string { + return a.Build().String() +} + +func (a *applicationPropertiesBuilder) Build() *properties.Properties { + var props *properties.Properties + if a.initialProperties != nil { + props = a.initialProperties + } else { + props = 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. + props.DisableExpansion = true + + if a.defaultManagedProperties != nil { + defaultManagedProperties := a.defaultManagedProperties + for _, k := range defaultManagedProperties.Keys() { + if _, ok := props.Get(k); ok { + defaultManagedProperties.Delete(k) + } + } + props.Merge(defaultManagedProperties) + } + + if a.immutableProperties != nil { + // finally overwrite with the defaults immutable properties. + props.Merge(a.immutableProperties) + } + return props +} + +func NewApplicationPropertiesBuilder() ApplicationPropertiesBuilder { + return &applicationPropertiesBuilder{} +} diff --git a/packages/kogito-serverless-operator/utils/resources/resources.go b/packages/kogito-serverless-operator/utils/resources/resources.go new file mode 100644 index 00000000000..e18a17b0c47 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/resources/resources.go @@ -0,0 +1,203 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/apache/incubator-kie-tools/packages/kogito-serverless-operator/container-builder/client" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/utils" + + v08 "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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/packages/kogito-serverless-operator/utils/resources/resources_support.go b/packages/kogito-serverless-operator/utils/resources/resources_support.go new file mode 100644 index 00000000000..ec4c2768936 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/resources/resources_support.go @@ -0,0 +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. + */ + +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/packages/kogito-serverless-operator/utils/strings.go b/packages/kogito-serverless-operator/utils/strings.go new file mode 100644 index 00000000000..85b503afdd4 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/strings.go @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "strings" +) + +func RemoveFileExtension(fileName string) string { + if i := strings.LastIndex(fileName, "."); i >= 0 { + return fileName[:i] + } + return fileName +} + +func RemoveKnownExtension(fileName, extension string) string { + if i := strings.LastIndex(fileName, extension); i >= 0 { + return fileName[:i] + } + return fileName +} diff --git a/packages/kogito-serverless-operator/utils/strings_test.go b/packages/kogito-serverless-operator/utils/strings_test.go new file mode 100644 index 00000000000..2a155165986 --- /dev/null +++ b/packages/kogito-serverless-operator/utils/strings_test.go @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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 ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRemoveFileExtension(t *testing.T) { + type args struct { + fileName string + } + tests := []struct { + name string + args args + want string + }{ + {name: "Basic", args: struct{ fileName string }{fileName: "myfile.json"}, want: "myfile"}, + {name: "Just the extension", args: struct{ fileName string }{fileName: ".json"}, want: ""}, + {name: "Many extension separators", args: struct{ fileName string }{fileName: "my.file.awesome.json"}, want: "my.file.awesome"}, + {name: "No extension", args: struct{ fileName string }{fileName: "myfileisrad"}, want: "myfileisrad"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, RemoveFileExtension(tt.args.fileName), "RemoveFileExtension(%v)", tt.args.fileName) + }) + } +} + +func TestRemoveKnownExtension(t *testing.T) { + type args struct { + fileName string + extension string + } + tests := []struct { + name string + args args + want string + }{ + {name: "Basic", args: args{fileName: "myworkflow.sw.json", extension: ".sw.json"}, want: "myworkflow"}, + {name: "No Extension", args: args{fileName: "myworkflow", extension: ".sw.json"}, want: "myworkflow"}, + {name: "No Extension Extension", args: args{fileName: "myworkflow.sw.json", extension: ""}, want: "myworkflow.sw.json"}, + {name: "Mess Extension", args: args{fileName: "myworkflow.sw.json", extension: ".json"}, want: "myworkflow.sw"}, + {name: "No filename", args: args{fileName: "", extension: ".json"}, want: ""}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, RemoveKnownExtension(tt.args.fileName, tt.args.extension), "RemoveKnownExtension(%v, %v)", tt.args.fileName, tt.args.extension) + }) + } +} diff --git a/packages/kogito-serverless-operator/version/version.go b/packages/kogito-serverless-operator/version/version.go new file mode 100644 index 00000000000..313ae7971a9 --- /dev/null +++ b/packages/kogito-serverless-operator/version/version.go @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package version + +import ( + "strings" +) + +const ( + // Current version + OperatorVersion = "0.0.0" + + // Should not be changed + latestVersion = "0.0.0" +) + +func IsSnapshot() bool { + return OperatorVersion == "0.0.0" +} + +func IsLatestVersion() bool { + return latestVersion == OperatorVersion +} + +func GetMajorMinor() string { + v := strings.Split(OperatorVersion, ".") + return v[0] + "." + v[1] +} diff --git a/packages/kogito-serverless-operator/workflowproj/Makefile b/packages/kogito-serverless-operator/workflowproj/Makefile new file mode 100644 index 00000000000..21599a40925 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/Makefile @@ -0,0 +1,21 @@ +.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/packages/kogito-serverless-operator/workflowproj/README.md b/packages/kogito-serverless-operator/workflowproj/README.md new file mode 100644 index 00000000000..b47092bd04f --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/README.md @@ -0,0 +1,62 @@ +# 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/kogito-serverless-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" +``` diff --git a/packages/kogito-serverless-operator/workflowproj/camelschema.go b/packages/kogito-serverless-operator/workflowproj/camelschema.go new file mode 100644 index 00000000000..6406d187de7 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/camelschema.go @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/workflowproj/go.mod b/packages/kogito-serverless-operator/workflowproj/go.mod new file mode 100644 index 00000000000..46e5d9476a8 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/go.mod @@ -0,0 +1,87 @@ +module github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/workflowproj + +go 1.21 + +toolchain go1.21.6 + +// Internal dependencies +replace github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api v0.0.0 => ../api + +require ( + github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api v0.0.0 + 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.2.5 + github.com/stretchr/testify v1.8.4 + k8s.io/api v0.27.6 + k8s.io/apimachinery v0.27.6 + k8s.io/client-go v0.27.6 + sigs.k8s.io/controller-runtime v0.15.0 + sigs.k8s.io/yaml v1.3.0 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.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.10.2 // indirect + github.com/evanphx/json-patch/v5 v5.7.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-logr/logr v1.2.4 // 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.0 // indirect + github.com/go-playground/universal-translator v0.18.0 // indirect + github.com/go-playground/validator/v10 v10.11.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.3 // indirect + github.com/google/gnostic v0.6.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.3.1 // 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.2.1 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // 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.17.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.11.1 // indirect + github.com/relvacode/iso8601 v1.3.0 // indirect + github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/sync v0.4.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.3.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.33.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.27.6 // indirect + k8s.io/component-base v0.27.6 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 // indirect + k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // 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.3.0 // indirect +) diff --git a/packages/kogito-serverless-operator/workflowproj/go.sum b/packages/kogito-serverless-operator/workflowproj/go.sum new file mode 100644 index 00000000000..76febac129b --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/go.sum @@ -0,0 +1,360 @@ +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= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +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/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.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/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +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.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +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 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= +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.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +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/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +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-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +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-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/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.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/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +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.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.5.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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +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-20230705174524-200ffdc848b8 h1:n6vlPhxsA+BW/XsS5+uqi7GyzaLa5MH7qlSLBZtRdiA= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +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/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.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +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.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +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/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.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +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.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +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/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +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/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/relvacode/iso8601 v1.3.0 h1:HguUjsGpIMh/zsTczGN3DVJFxTU/GX+MMmzcKoMO7ko= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +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/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 h1:Dz0HrI1AtNSGCE8LXLLqoZU4iuOJXPWndenCsZfstA8= +github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46/go.mod h1:is8FVkzSi7PYLWEXT5MgWhglFsyyiW8ffxAoJqfuFZo= +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.2.5 h1:/TFqBBni0hDpTA0bKadGTWbyBRiQ0o2ppz2ScY6DdTM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +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/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/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.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +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/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +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/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +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.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +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-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-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +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-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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +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-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.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-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-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +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.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/text v0.3.0/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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +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-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +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.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +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= +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.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +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.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +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/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.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.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.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/api v0.27.6 h1:PBWu/lywJe2qQcshMjubzcBg7+XDZOo7O8JJAWuYtUo= +k8s.io/apiextensions-apiserver v0.27.6 h1:mOwSBJtThZhpJr+8gEkc3wFDIjq87E3JspR5mtZxIg8= +k8s.io/apimachinery v0.27.6 h1:mGU8jmBq5o8mWBov+mLjdTBcU+etTE19waies4AQ6NE= +k8s.io/client-go v0.27.6 h1:vzI8804gpUtpMCNaFjIFyJrifH7u//LJCJPy8fQuYQg= +k8s.io/component-base v0.27.6 h1:hF5WxX7Tpi9/dXAbLjPVkIA6CA6Pi6r9JOHyo0uCDYI= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 h1:OmK1d0WrkD3IPfkskvroRykOulHVHf0s0ZIFRjyt+UI= +k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc= +knative.dev/pkg v0.0.0-20231023151236-29775d7c9e5c h1:xyPoEToTWeBdn6tinhLxXfnhJhTNQt5WzHiTNiFphRw= +sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= +sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +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.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/packages/kogito-serverless-operator/workflowproj/io.go b/packages/kogito-serverless-operator/workflowproj/io.go new file mode 100644 index 00000000000..152d37bee47 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/io.go @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/workflowproj/operator.go b/packages/kogito-serverless-operator/workflowproj/operator.go new file mode 100644 index 00000000000..f4a98e1a6e3 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/operator.go @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/v1alpha08" +) + +const ( + workflowUserConfigMapNameSuffix = "-props" + // ApplicationPropertiesFileName is the default application properties file name holding user properties + ApplicationPropertiesFileName = "application.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" + // LabelService key to use among object selectors + LabelService = metadata.Domain + "/service" + // LabelWorkflow specialized label managed by the controller + LabelWorkflow = metadata.Domain + "/workflow-app" +) + +// 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) +} + +// GetDefaultLabels gets the default labels based on the given workflow. +func GetDefaultLabels(workflow *operatorapi.SonataFlow) map[string]string { + return map[string]string{ + LabelApp: workflow.Name, + LabelWorkflow: workflow.Name, + } +} + +// 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: ""}, + } +} + +// CreateNewManagedPropsConfigMap creates a new ConfigMap object to hold the managed application properties of the workflos. +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/packages/kogito-serverless-operator/workflowproj/resources.go b/packages/kogito-serverless-operator/workflowproj/resources.go new file mode 100644 index 00000000000..bd96819b291 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/resources.go @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/workflowproj/resources_test.go b/packages/kogito-serverless-operator/workflowproj/resources_test.go new file mode 100644 index 00000000000..da8dff73a7e --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/resources_test.go @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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/packages/kogito-serverless-operator/workflowproj/testdata/mygeneric.wsdl b/packages/kogito-serverless-operator/workflowproj/testdata/mygeneric.wsdl new file mode 100644 index 00000000000..85e44784f47 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/testdata/mygeneric.wsdl @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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. + + + + + + + + \ No newline at end of file diff --git a/packages/kogito-serverless-operator/workflowproj/testdata/valid-asyncapi.json b/packages/kogito-serverless-operator/workflowproj/testdata/valid-asyncapi.json new file mode 100644 index 00000000000..d6b64171268 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/testdata/valid-asyncapi.json @@ -0,0 +1,72 @@ +{ + "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/packages/kogito-serverless-operator/workflowproj/testdata/valid-asyncapi.yaml b/packages/kogito-serverless-operator/workflowproj/testdata/valid-asyncapi.yaml new file mode 100644 index 00000000000..15b50aa5c50 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/testdata/valid-asyncapi.yaml @@ -0,0 +1,63 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/workflowproj/testdata/valid-camelroute.json b/packages/kogito-serverless-operator/workflowproj/testdata/valid-camelroute.json new file mode 100644 index 00000000000..1c4f187b1c3 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/testdata/valid-camelroute.json @@ -0,0 +1,393 @@ +[ + { + "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/packages/kogito-serverless-operator/workflowproj/testdata/valid-camelroute.yaml b/packages/kogito-serverless-operator/workflowproj/testdata/valid-camelroute.yaml new file mode 100644 index 00000000000..2b56189cd28 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/testdata/valid-camelroute.yaml @@ -0,0 +1,275 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/workflowproj/testdata/valid-openapi.json b/packages/kogito-serverless-operator/workflowproj/testdata/valid-openapi.json new file mode 100644 index 00000000000..477a3171278 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/testdata/valid-openapi.json @@ -0,0 +1,58 @@ +{ + "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/packages/kogito-serverless-operator/workflowproj/testdata/valid-openapi.yaml b/packages/kogito-serverless-operator/workflowproj/testdata/valid-openapi.yaml new file mode 100644 index 00000000000..7480df277dd --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/testdata/valid-openapi.yaml @@ -0,0 +1,53 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/workflowproj/testdata/workflows/application.properties b/packages/kogito-serverless-operator/workflowproj/testdata/workflows/application.properties new file mode 100644 index 00000000000..8bec78e2add --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/testdata/workflows/application.properties @@ -0,0 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/packages/kogito-serverless-operator/workflowproj/testdata/workflows/specs/workflow-service-openapi.json b/packages/kogito-serverless-operator/workflowproj/testdata/workflows/specs/workflow-service-openapi.json new file mode 100644 index 00000000000..fd1b74b0307 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/testdata/workflows/specs/workflow-service-openapi.json @@ -0,0 +1,59 @@ +{ + "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/packages/kogito-serverless-operator/workflowproj/testdata/workflows/specs/workflow-service-schema.json b/packages/kogito-serverless-operator/workflowproj/testdata/workflows/specs/workflow-service-schema.json new file mode 100644 index 00000000000..5e4544eee94 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/testdata/workflows/specs/workflow-service-schema.json @@ -0,0 +1,10 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "required": ["name"] +} diff --git a/packages/kogito-serverless-operator/workflowproj/testdata/workflows/workflow-minimal-invalid.sw.json b/packages/kogito-serverless-operator/workflowproj/testdata/workflows/workflow-minimal-invalid.sw.json new file mode 100644 index 00000000000..978f8feadf2 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/testdata/workflows/workflow-minimal-invalid.sw.json @@ -0,0 +1,12 @@ +{ + "states": [ + { + "name": "HelloWorld", + "type": "inject", + "data": { + "message": "Hello World" + }, + "end": true + } + ] +} diff --git a/packages/kogito-serverless-operator/workflowproj/testdata/workflows/workflow-minimal.sw.json b/packages/kogito-serverless-operator/workflowproj/testdata/workflows/workflow-minimal.sw.json new file mode 100644 index 00000000000..9ffadb521c2 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/testdata/workflows/workflow-minimal.sw.json @@ -0,0 +1,16 @@ +{ + "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/packages/kogito-serverless-operator/workflowproj/testdata/workflows/workflow-service.sw.json b/packages/kogito-serverless-operator/workflowproj/testdata/workflows/workflow-service.sw.json new file mode 100644 index 00000000000..ab71201f0a9 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/testdata/workflows/workflow-service.sw.json @@ -0,0 +1,30 @@ +{ + "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/packages/kogito-serverless-operator/workflowproj/workflowproj.go b/packages/kogito-serverless-operator/workflowproj/workflowproj.go new file mode 100644 index 00000000000..a71ab8b7f21 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/workflowproj.go @@ -0,0 +1,312 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + "strings" + + "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/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + operatorapi "github.com/apache/incubator-kie-tools/packages/kogito-serverless-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 + // 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) +} + +// 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 + // 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 + 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) 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 + } + } + 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.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) parseRawResources() error { + if len(w.rawResources) == 0 { + return nil + } + + resourceCount := 1 + for path, resources := range w.rawResources { + cm := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{Namespace: w.namespace, Name: fmt.Sprintf("%02d-%s-resources", resourceCount, w.name)}, + Data: map[string]string{}, + } + + for _, r := range resources { + 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 +} + +// IsDevProfile detects if the workflow is using the Dev profile or not +func IsDevProfile(workflow *operatorapi.SonataFlow) bool { + profile := workflow.Annotations[metadata.Profile] + if len(profile) == 0 { + return false + } + return metadata.ProfileType(profile) == metadata.DevProfile +} diff --git a/packages/kogito-serverless-operator/workflowproj/workflowproj_test.go b/packages/kogito-serverless-operator/workflowproj/workflowproj_test.go new file mode 100644 index 00000000000..03e05716a34 --- /dev/null +++ b/packages/kogito-serverless-operator/workflowproj/workflowproj_test.go @@ -0,0 +1,259 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES 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" + + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/apache/incubator-kie-tools/packages/kogito-serverless-operator/api/metadata" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/kubernetes/scheme" +) + +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"}) + 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", 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", proj.Resources[0].Name) + assert.Equal(t, "02-hello-resources", 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 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.yaml", + "03-configmap_02-service-resources.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 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 mustGetFile(filepath string) io.Reader { + file, err := os.OpenFile(filepath, os.O_RDONLY, os.ModePerm) + if err != nil { + panic(err) + } + return file +} diff --git a/packages/kogito-swf-builder/README.md b/packages/kogito-swf-builder/README.md new file mode 100644 index 00000000000..98a43dac228 --- /dev/null +++ b/packages/kogito-swf-builder/README.md @@ -0,0 +1,67 @@ +# kogito-swf-builder + +This package contains the `cekit` image descriptor (`kogito-swf-builder-image.yaml`) and modules needed to build the `kogito-swf-builder` +image along with the modules and scripts provided in `@kie-tools/kogito-swf-common`. + +## Additional requirements + +- **python3** with the following packages installed: + - `behave` `lxml` `docker` `docker-squash` `elementPath` `pyyaml` `ruamel.yaml` `python-dateutil` `Jinja2` `pykwalify` `colorlog` `click` +- **cekit 4.11.0**: [docs.cekit.io](https://docs.cekit.io/en/latest/index.html) +- **s2i**: [source-to-image](https://github.com/openshift/source-to-image) +- **make** +- **docker** or **podman** + +## Build + +- Enable the image to be built: + + ```bash + export KIE_TOOLS_BUILD__buildContainerImages=true + ``` + +- (Optional) The image name and tags can be customized by setting the following environment variables: + + ```bash + export KOGITO_SWF_BUILDER_IMAGE__registry= + export KOGITO_SWF_BUILDER_IMAGE__account= + export KOGITO_SWF_BUILDER_IMAGE__name= + export KOGITO_SWF_BUILDER_IMAGE__buildTag= + ``` + + > Default values can be found [here](./env/index.js). + +- After optionally setting up the environment variables, run the following in the root folder of the repository to build the package: + + ```bash + pnpm -F @kie-tools/kogito-swf-builder build:prod + ``` + +- Then check if the image is correctly stored: + + ```bash + docker images + ``` + + or + + ```bash + podman images + ``` + +## Testing the generated image (only for Linux) + +- With the image generated, run: + + ```bash + pnpm -F @kie-tools/kogito-swf-builder image:test + ``` + +## Envs + +| Name | Description | Default | +| :----------------------------------: | :------------------------------------------------: | :------------------: | +| `KOGITO_SWF_BUILDER_IMAGE__registry` | Registry where the generated image will be pushed. | "quay.io" | +| `KOGITO_SWF_BUILDER_IMAGE__account` | Account where image will be stored. | "kiegroup" | +| `KOGITO_SWF_BUILDER_IMAGE__name` | SWF Builder Image name. | "kogito-swf-builder" | +| `KOGITO_SWF_BUILDER_IMAGE__buildTag` | Tag to use . | "latest" | diff --git a/packages/kogito-swf-builder/env/index.js b/packages/kogito-swf-builder/env/index.js new file mode 100644 index 00000000000..0c9c2a7ea57 --- /dev/null +++ b/packages/kogito-swf-builder/env/index.js @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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"); + +module.exports = composeEnv([require("@kie-tools/root-env/env")], { + vars: varsWithName({ + KOGITO_SWF_BUILDER_IMAGE__registry: { + default: "quay.io", + description: "The image registry.", + }, + KOGITO_SWF_BUILDER_IMAGE__account: { + default: "kiegroup", + description: "The image registry account.", + }, + KOGITO_SWF_BUILDER_IMAGE__name: { + default: "kogito-swf-builder-nightly", + description: "The image name.", + }, + KOGITO_SWF_BUILDER_IMAGE__buildTag: { + default: "latest", + description: "The image tag.", + }, + }), + get env() { + return { + kogitoSwfBuilder: { + registry: getOrDefault(this.vars.KOGITO_SWF_BUILDER_IMAGE__registry), + account: getOrDefault(this.vars.KOGITO_SWF_BUILDER_IMAGE__account), + name: getOrDefault(this.vars.KOGITO_SWF_BUILDER_IMAGE__name), + tag: getOrDefault(this.vars.KOGITO_SWF_BUILDER_IMAGE__buildTag), + version: require("../package.json").version, + }, + }; + }, +}); diff --git a/packages/kogito-swf-builder/install.js b/packages/kogito-swf-builder/install.js new file mode 100644 index 00000000000..360abf22804 --- /dev/null +++ b/packages/kogito-swf-builder/install.js @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 { execSync } = require("child_process"); +const fs = require("fs"); + +const buildEnv = require("./env"); +const path = require("path"); +const pythonVenvDir = path.dirname(require.resolve("@kie-tools/python-venv/package.json")); +const kogitoSwfCommonDir = path.dirname(require.resolve("@kie-tools/kogito-swf-common/package.json")); + +const activateCmd = + process.platform === "win32" + ? `${pythonVenvDir}\\venv\\Scripts\\Activate.bat` + : `. ${pythonVenvDir}/venv/bin/activate`; + +execSync( + `${activateCmd} && \ + python3 ${kogitoSwfCommonDir}/resources/scripts/versions_manager.py --bump-to ${buildEnv.env.kogitoSwfBuilder.version} --source-folder ./resources`, + { stdio: "inherit" } +); + +// Find and read the -image.yaml file +const resourcesPath = path.resolve(__dirname, "./resources"); +const files = fs.readdirSync(resourcesPath); +const imageYamlFiles = files.filter((fileName) => fileName.endsWith("-image.yaml")); +if (imageYamlFiles.length !== 1) { + throw new Error("There should only be one -image.yaml file on ./resources!"); +} +const originalYamlPath = path.join(resourcesPath, imageYamlFiles[0]); +let imageYaml = fs.readFileSync(originalYamlPath, "utf8"); + +// Replace the whole string between quotes ("") with the image name +imageYaml = imageYaml.replace( + /(?<=")(.*kogito-swf-builder.*)(?=")/gm, + `${buildEnv.env.kogitoSwfBuilder.registry}/${buildEnv.env.kogitoSwfBuilder.account}/${buildEnv.env.kogitoSwfBuilder.name}` +); + +// Write file and then rename it to match the image name +fs.writeFileSync(originalYamlPath, imageYaml); +fs.renameSync(originalYamlPath, path.join(resourcesPath, `${buildEnv.env.kogitoSwfBuilder.name}-image.yaml`)); diff --git a/packages/kogito-swf-builder/package.json b/packages/kogito-swf-builder/package.json new file mode 100644 index 00000000000..91c3dd46cd4 --- /dev/null +++ b/packages/kogito-swf-builder/package.json @@ -0,0 +1,47 @@ +{ + "private": true, + "name": "@kie-tools/kogito-swf-builder", + "version": "0.0.0", + "description": "", + "license": "Apache-2.0", + "homepage": "https://github.com/apache/incubator-kie-tools", + "repository": { + "type": "git", + "url": "https://github.com/apache/incubator-kie-tools.git" + }, + "bugs": { + "url": "https://github.com/apache/incubator-kie-tools/issues" + }, + "scripts": { + "build:dev": "run-script-if --bool \"$(build-env containerImages.build)\" --then \"pnpm copy-assets\" \"pnpm image:build\"", + "build:prod": "pnpm build:dev && pnpm image:test", + "copy-assets": "run-script-os", + "copy-assets:linux:darwin": "rimraf build && cp -R ./node_modules/@kie-tools/kogito-swf-common/resources build && cp -R resources/* build", + "copy-test-assets": "run-script-os", + "copy-test-assets:linux:darwin": "cp -R ./node_modules/@kie-tools/kogito-swf-common/test-resources/* build && cp -R test-resources/* build", + "format": "prettier --write .", + "image:build": "run-script-os", + "image:build:darwin:win32": "echo \"Build skipped on macOS and Windows\"", + "image:build:linux": "pnpm setup:env make -C ./build build", + "image:test": "run-script-if --ignore-errors \"$(build-env tests.ignoreFailures)\" --bool \"$(build-env tests.run)\" --then \"run-script-os\"", + "image:test:darwin:win32": "echo \"Tests skipped on macOS and Windows\"", + "image:test:linux": "pnpm copy-test-assets && pnpm setup:env make -C ./build test-image", + "install": "node install.js && pnpm format", + "setup:env": ". ./node_modules/@kie-tools/python-venv/venv/bin/activate && cross-env SWF_IMAGE_REGISTRY=$(build-env kogitoSwfBuilder.registry) SWF_IMAGE_REGISTRY_ACCOUNT=$(build-env kogitoSwfBuilder.account) SWF_IMAGE_NAME=$(build-env kogitoSwfBuilder.name) SWF_IMAGE_TAG=$(build-env kogitoSwfBuilder.tag) QUARKUS_PLATFORM_VERSION=$(build-env quarkusPlatform.version) KOGITO_VERSION=$(build-env kogitoRuntime.version)" + }, + "devDependencies": { + "@kie-tools/kogito-swf-common": "workspace:*", + "@kie-tools/python-venv": "workspace:*", + "@kie-tools/root-env": "workspace:*", + "cross-env": "^7.0.3", + "rimraf": "^3.0.2", + "run-script-os": "^1.1.6" + }, + "kieTools": { + "requiredPreinstalledCliCommands": [ + "python3", + "make", + "s2i" + ] + } +} \ No newline at end of file diff --git a/packages/kogito-swf-builder/resources/kogito-swf-builder-nightly-image.yaml b/packages/kogito-swf-builder/resources/kogito-swf-builder-nightly-image.yaml new file mode 100644 index 00000000000..a63b040a6b9 --- /dev/null +++ b/packages/kogito-swf-builder/resources/kogito-swf-builder-nightly-image.yaml @@ -0,0 +1,74 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: builder + from: "registry.access.redhat.com/ubi8/openjdk-17:1.19" + version: "0.0.0" + modules: + repositories: + - path: modules + install: + - name: org.kie.kogito.system.user + - name: org.kie.kogito.logging + - name: org.kie.kogito.launch.scripts + - name: org.kie.kogito.dynamic.resources + - name: org.kie.kogito.maven.common + - name: org.kie.kogito.project.versions + - name: org.kie.kogito.swf.common.scripts + - name: org.kie.kogito.swf.builder.build-config + - name: org.kie.kogito.swf.common.build + +- name: "quay.io/kiegroup/kogito-swf-builder-nightly" + from: "registry.access.redhat.com/ubi8/openjdk-17:1.19" + version: "0.0.0" + description: "Kogito Serverless Workflow base builder with Quarkus extensions libraries preinstalled" + + labels: + - name: "io.openshift.s2i.scripts-url" + value: "image:///usr/local/s2i" + - name: "io.openshift.s2i.destination" + value: "/tmp" + - name: "io.quarkus.platform.version" + value: "### SET ME DURING BUILD PROCESS ###" + - name: "org.kie.kogito.version" + value: "### SET ME DURING BUILD PROCESS ###" + - name: "maintainer" + value: "Apache KIE " + - name: "io.k8s.description" + value: "Kogito Serverless Workflow base builder with Quarkus extensions libraries preinstalled." + - name: "io.k8s.display-name" + value: "Kogito SWF Builder" + - name: "io.openshift.tags" + value: "kogito,builder,serverless,workflow" + + modules: + repositories: + - path: modules + install: + - name: org.kie.kogito.system.user + - name: org.kie.kogito.logging + - name: org.kie.kogito.launch.scripts + - name: org.kie.kogito.dynamic.resources + - name: org.kie.kogito.maven.common + - name: org.kie.kogito.project.versions + - name: org.kie.kogito.swf.common.scripts + - name: org.kie.kogito.swf.builder.runtime.community + + run: + workdir: "/home/kogito/${PROJECT_ARTIFACT_ID}" + user: 1001 diff --git a/packages/kogito-swf-builder/resources/modules/kogito-swf/builder/build-config/module.yaml b/packages/kogito-swf-builder/resources/modules/kogito-swf/builder/build-config/module.yaml new file mode 100644 index 00000000000..de71907ea4d --- /dev/null +++ b/packages/kogito-swf-builder/resources/modules/kogito-swf/builder/build-config/module.yaml @@ -0,0 +1,29 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: org.kie.kogito.swf.builder.build-config +version: "0.0.0" +description: "Kogito Serverless Workflow builder image build configuration" + +envs: + - name: "SCRIPT_DEBUG" + value: "false" + - name: QUARKUS_EXTENSIONS + # Follow up issue to remove KOGITO_VERSION: https://issues.redhat.com/browse/KOGITO-9270 + value: quarkus-kubernetes,smallrye-health,org.apache.kie.sonataflow:sonataflow-quarkus:${KOGITO_VERSION},org.kie:kie-addons-quarkus-knative-eventing:${KOGITO_VERSION},org.kie:kogito-addons-quarkus-microprofile-config-service-catalog:${KOGITO_VERSION},org.kie:kie-addons-quarkus-kubernetes:${KOGITO_VERSION},org.kie:kie-addons-quarkus-events-process:${KOGITO_VERSION},org.kie:kie-addons-quarkus-process-management:${KOGITO_VERSION},org.kie:kie-addons-quarkus-source-files:${KOGITO_VERSION},org.kie:kogito-addons-quarkus-knative-serving:${KOGITO_VERSION},org.kie:kogito-addons-quarkus-jobs-knative-eventing:${KOGITO_VERSION} diff --git a/packages/kogito-swf-builder/resources/modules/kogito-swf/builder/runtime/community/configure.sh b/packages/kogito-swf-builder/resources/modules/kogito-swf/builder/runtime/community/configure.sh new file mode 100644 index 00000000000..8d26bb5940e --- /dev/null +++ b/packages/kogito-swf-builder/resources/modules/kogito-swf/builder/runtime/community/configure.sh @@ -0,0 +1,33 @@ +#!/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. +# + +set -e + +SOURCES_DIR=/tmp/artifacts + +mkdir -p "${KOGITO_HOME}"/.m2/repository +mkdir -p "${KOGITO_HOME}/${PROJECT_ARTIFACT_ID}" + +# Unzip Quarkus app and Maven repository +tar xf "${SOURCES_DIR}"/kogito-swf-quarkus-app.tar -C "${KOGITO_HOME}/${PROJECT_ARTIFACT_ID}" +tar xf "${SOURCES_DIR}"/kogito-swf-maven-repo.tar -C "${KOGITO_HOME}"/.m2/repository + +chown -R 1001:0 "${KOGITO_HOME}" +chmod -R ug+rwX "${KOGITO_HOME}" diff --git a/packages/kogito-swf-builder/resources/modules/kogito-swf/builder/runtime/community/module.yaml b/packages/kogito-swf-builder/resources/modules/kogito-swf/builder/runtime/community/module.yaml new file mode 100644 index 00000000000..dbf630cf39e --- /dev/null +++ b/packages/kogito-swf-builder/resources/modules/kogito-swf/builder/runtime/community/module.yaml @@ -0,0 +1,31 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: org.kie.kogito.swf.builder.runtime.community +version: "0.0.0" +description: "Kogito Serverless Workflow builder runtime module" + +artifacts: + - image: builder + path: /home/kogito/build_output/kogito-swf-quarkus-app.tar + - image: builder + path: /home/kogito/build_output/kogito-swf-maven-repo.tar + +execute: + - script: configure.sh diff --git a/packages/kogito-swf-builder/test-resources/modules/kogito-swf/common/scripts/tests/bats/kogito-swf-builder-build-app.bats b/packages/kogito-swf-builder/test-resources/modules/kogito-swf/common/scripts/tests/bats/kogito-swf-builder-build-app.bats new file mode 100644 index 00000000000..9ffce5d374c --- /dev/null +++ b/packages/kogito-swf-builder/test-resources/modules/kogito-swf/common/scripts/tests/bats/kogito-swf-builder-build-app.bats @@ -0,0 +1,45 @@ +#!/usr/bin/env bats +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +setup() { + export KOGITO_HOME=/tmp/kogito + export HOME="${KOGITO_HOME}" + mkdir -p "${KOGITO_HOME}"/launch + mkdir -p "${KOGITO_HOME}"/serverless-workflow-project/src/main/resources/ + cp $BATS_TEST_DIRNAME/../../../../../kogito-logging/added/logging.sh "${KOGITO_HOME}"/launch/ + cp $BATS_TEST_DIRNAME/../../added/jvm-settings.sh "${KOGITO_HOME}"/launch/ + cp $BATS_TEST_DIRNAME/../../added/build-app.sh "${KOGITO_HOME}"/launch/ +} + +teardown() { + rm -rf "${KOGITO_HOME}" + rm -rf /tmp/resources +} + +@test "verify copy resources is working" { + TEMPD=$(mktemp -d) + cp -r $BATS_TEST_DIRNAME/../../../../../../tests/shell/kogito-swf-builder/resources/greet-with-inputschema/* ${TEMPD} + + # We don't care about the errors to try to execute and build the program, just the copy matters + source ${KOGITO_HOME}/launch/build-app.sh ${TEMPD} || true + + [[ -f "${KOGITO_HOME}"/serverless-workflow-project/src/main/resources/greet.sw.json ]] + [[ -f "${KOGITO_HOME}"/serverless-workflow-project/src/main/resources/schemas/input.json ]] +} diff --git a/packages/kogito-swf-builder/test-resources/tests/features/kogito-swf-builder-2.feature b/packages/kogito-swf-builder/test-resources/tests/features/kogito-swf-builder-2.feature new file mode 100644 index 00000000000..51de9c6fdca --- /dev/null +++ b/packages/kogito-swf-builder/test-resources/tests/features/kogito-swf-builder-2.feature @@ -0,0 +1,14 @@ +@quay.io/kiegroup/kogito-swf-builder +Feature: Serverless Workflow images common + + Scenario: Verify if the swf and quarkus files are under /home/kogito/.m2/repository + When container is started with command bash + Then file /home/kogito/.m2/repository/io/quarkus/platform/quarkus-bom should exist and be a directory + And file /home/kogito/.m2/repository/org/apache/kie/sonataflow/sonataflow-quarkus/ should exist and be a directory + + # This check should be enabled again once a similar check is done on runtimes + # to make sure we only have one version of quarkus bom ... + # See https://issues.redhat.com/browse/KOGITO-8555 to enable again + # Scenario: verify if there is no dependencies with multiple versions in /home/kogito/.m2/repository + # When container is started with command bash + # Then run sh -c 'ls /home/kogito/.m2/repository/io/quarkus/quarkus-bom | wc -l' in container and immediately check its output for 1 diff --git a/packages/kogito-swf-builder/test-resources/tests/features/kogito-swf-builder.feature b/packages/kogito-swf-builder/test-resources/tests/features/kogito-swf-builder.feature new file mode 100644 index 00000000000..acae47c9ca3 --- /dev/null +++ b/packages/kogito-swf-builder/test-resources/tests/features/kogito-swf-builder.feature @@ -0,0 +1,38 @@ +@quay.io/kiegroup/kogito-swf-builder +Feature: Serverless Workflow builder images + + Scenario: Verify that the application is built and started correctly + When container is started with command bash -c '/home/kogito/launch/build-app.sh && java -jar target/quarkus-app/quarkus-run.jar' + | variable | value | + | SCRIPT_DEBUG | true | + Then check that page is served + | property | value | + | port | 8080 | + | path | /q/health/ready | + | wait | 480 | + | request_method | GET | + | expected_status_code | 200 | + And container log should contain --no-transfer-progress + And container log should contain -Duser.home=/home/kogito + And container log should match regex Installed features:.*kogito-serverless-workflow + And container log should match regex Installed features:.*kie-addon-knative-eventing-extension + And container log should match regex Installed features:.*smallrye-health + + Scenario: Verify that the application is built and started correctly when QUARKUS_EXTENSIONS env is used + When container is started with command bash -c '/home/kogito/launch/build-app.sh && java -jar target/quarkus-app/quarkus-run.jar' + | variable | value | + | SCRIPT_DEBUG | true | + | QUARKUS_EXTENSIONS | io.quarkus:quarkus-elytron-security-jdbc | + Then check that page is served + | property | value | + | port | 8080 | + | path | /q/health/ready | + | wait | 480 | + | request_method | GET | + | expected_status_code | 200 | + And container log should contain -Duser.home=/home/kogito + And container log should contain Extension io.quarkus:quarkus-elytron-security-jdbc has been installed + And container log should match regex Installed features:.*kogito-serverless-workflow + And container log should match regex Installed features:.*kie-addon-knative-eventing-extension + And container log should match regex Installed features:.*smallrye-health + And container log should match regex Installed features:.*security-jdbc \ No newline at end of file diff --git a/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/.vscode/launch.json b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/.vscode/launch.json new file mode 100644 index 00000000000..82cbbc6179c --- /dev/null +++ b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/.vscode/launch.json @@ -0,0 +1,22 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "RunTests-port-4004", + "request": "attach", + "hostName": "localhost", + "port": 4004 + }, + { + "type": "java", + "name": "Debug (Launch) - RunTests", + "request": "launch", + "mainClass": "RunTests", + "projectName": "RunTests" + } + ] +} diff --git a/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/.vscode/settings.json b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/.vscode/settings.json new file mode 100644 index 00000000000..b57ea44670f --- /dev/null +++ b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "java.import.gradle.enabled": false, + "java.import.maven.enabled": false, + "java.eclipse.downloadSources": true, + "files.exclude": { + "bin/": true, + ".eclipse/": true, + ".project": true, + ".classpath": true, + "build.gradle": true + }, + "java.completion.importOrder": ["", "javax", "java", "#"] +} diff --git a/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet-with-inputschema/Dockerfile b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet-with-inputschema/Dockerfile new file mode 100644 index 00000000000..2172c7129d0 --- /dev/null +++ b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet-with-inputschema/Dockerfile @@ -0,0 +1,40 @@ +ARG BUILDER_IMAGE_TAG="quay.io/kiegroup/kogito-swf-builder:2.0" + +FROM ${BUILDER_IMAGE_TAG} AS builder + +# Kogito user +USER 1001 + +ARG QUARKUS_PACKAGE_TYPE="jar" +ARG SCRIPT_DEBUG="true" +ARG MAVEN_DOWNLOAD_OUTPUT="true" +ARG MAVEN_OFFLINE_MODE="true" + +# Copy from build context to resources directory +COPY --chown=1001 . ./resources + +# Build app with given resources +RUN "${KOGITO_HOME}"/launch/build-app.sh './resources' + +#============================= +# Runtime Run +#============================= +FROM registry.access.redhat.com/ubi8/openjdk-17-runtime:latest + +ARG QUARKUS_LAUNCH_DEVMODE=false + +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' +# Default name is 'serverless-workflow-project' +ARG PROJECT_ARTIFACT_ID='serverless-workflow-project' + +# 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/${PROJECT_ARTIFACT_ID}/target/quarkus-app/lib/ /deployments/lib/ +COPY --from=builder --chown=185 /home/kogito/${PROJECT_ARTIFACT_ID}/target/quarkus-app/*.jar /deployments/ +COPY --from=builder --chown=185 /home/kogito/${PROJECT_ARTIFACT_ID}/target/quarkus-app/app/ /deployments/app/ +COPY --from=builder --chown=185 /home/kogito/${PROJECT_ARTIFACT_ID}/target/quarkus-app/quarkus/ /deployments/quarkus/ + +EXPOSE 8080 +USER 185 +ENV AB_JOLOKIA_OFF="" +ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Dquarkus.http.port=8080 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" diff --git a/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet-with-inputschema/greet.sw.json b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet-with-inputschema/greet.sw.json new file mode 100644 index 00000000000..5e3c8b0d00d --- /dev/null +++ b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet-with-inputschema/greet.sw.json @@ -0,0 +1,89 @@ +{ + "id": "greeting", + "description": "Greeting example on k8s!", + "version": "0.0.1", + "start": { + "stateName": "ChooseOnLanguage" + }, + "dataInputSchema": { + "schema": "schemas/input.json", + "failOnValidationErrors": true + }, + "specVersion": "0.8", + "expressionLang": "jq", + "states": [ + { + "name": "ChooseOnLanguage", + "type": "switch", + "defaultCondition": { + "transition": { + "nextState": "GreetInEnglish" + } + }, + "dataConditions": [ + { + "condition": "${ .language == \"English\" }", + "transition": { + "nextState": "GreetInEnglish" + } + }, + { + "condition": "${ .language == \"Spanish\" }", + "transition": { + "nextState": "GreetInSpanish" + } + } + ] + }, + { + "name": "GreetInEnglish", + "type": "inject", + "transition": { + "nextState": "GreetPerson" + }, + "data": { + "greeting": "Hello from JSON Workflow, " + } + }, + { + "name": "GreetInSpanish", + "type": "inject", + "transition": { + "nextState": "GreetPerson" + }, + "data": { + "greeting": "Saludos desde JSON Workflow, " + } + }, + { + "name": "GreetPerson", + "type": "operation", + "end": { + "terminate": true + }, + "actionMode": "sequential", + "actions": [ + { + "name": "greetAction", + "functionRef": { + "refName": "greetFunction", + "arguments": { + "message": ".greeting+.name" + }, + "invoke": "sync" + }, + "actionDataFilter": { + "useResults": true + } + } + ] + } + ], + "functions": [ + { + "name": "greetFunction", + "operation": "sysout", + "type": "custom" + } + ] +} diff --git a/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet-with-inputschema/schemas/input.json b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet-with-inputschema/schemas/input.json new file mode 100644 index 00000000000..965e88ea634 --- /dev/null +++ b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet-with-inputschema/schemas/input.json @@ -0,0 +1,13 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "language": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": ["language", "name"] +} diff --git a/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet/Dockerfile b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet/Dockerfile new file mode 100644 index 00000000000..2172c7129d0 --- /dev/null +++ b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet/Dockerfile @@ -0,0 +1,40 @@ +ARG BUILDER_IMAGE_TAG="quay.io/kiegroup/kogito-swf-builder:2.0" + +FROM ${BUILDER_IMAGE_TAG} AS builder + +# Kogito user +USER 1001 + +ARG QUARKUS_PACKAGE_TYPE="jar" +ARG SCRIPT_DEBUG="true" +ARG MAVEN_DOWNLOAD_OUTPUT="true" +ARG MAVEN_OFFLINE_MODE="true" + +# Copy from build context to resources directory +COPY --chown=1001 . ./resources + +# Build app with given resources +RUN "${KOGITO_HOME}"/launch/build-app.sh './resources' + +#============================= +# Runtime Run +#============================= +FROM registry.access.redhat.com/ubi8/openjdk-17-runtime:latest + +ARG QUARKUS_LAUNCH_DEVMODE=false + +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' +# Default name is 'serverless-workflow-project' +ARG PROJECT_ARTIFACT_ID='serverless-workflow-project' + +# 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/${PROJECT_ARTIFACT_ID}/target/quarkus-app/lib/ /deployments/lib/ +COPY --from=builder --chown=185 /home/kogito/${PROJECT_ARTIFACT_ID}/target/quarkus-app/*.jar /deployments/ +COPY --from=builder --chown=185 /home/kogito/${PROJECT_ARTIFACT_ID}/target/quarkus-app/app/ /deployments/app/ +COPY --from=builder --chown=185 /home/kogito/${PROJECT_ARTIFACT_ID}/target/quarkus-app/quarkus/ /deployments/quarkus/ + +EXPOSE 8080 +USER 185 +ENV AB_JOLOKIA_OFF="" +ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Dquarkus.http.port=8080 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" diff --git a/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet/greet.sw.json b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet/greet.sw.json new file mode 100644 index 00000000000..a619b3b8bc7 --- /dev/null +++ b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/resources/greet/greet.sw.json @@ -0,0 +1,67 @@ +{ + "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/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/src/RunTests.java b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/src/RunTests.java new file mode 100644 index 00000000000..2ec43afadc8 --- /dev/null +++ b/packages/kogito-swf-builder/test-resources/tests/shell/kogito-swf-builder/src/RunTests.java @@ -0,0 +1,140 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? + +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//DEPS org.slf4j:slf4j-simple:2.0.9 + +// Junit console to start the test engine: +//DEPS org.junit.platform:junit-platform-console:1.10.1 + +// engine to run the tests (tests are written with Junit5): +//DEPS org.junit.jupiter:junit-jupiter-engine:5.10.1 + +// testcontainers +//DEPS org.testcontainers:testcontainers:1.19.3 +//DEPS org.testcontainers:junit-jupiter:1.19.3 + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.nio.file.Paths; +import java.time.Duration; +import org.junit.jupiter.api.Test; +import org.junit.platform.console.ConsoleLauncher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.images.builder.ImageFromDockerfile; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@Testcontainers +public class RunTests { + + private static Logger LOGGER = LoggerFactory.getLogger(RunTests.class); + + private Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOGGER); + + @Container + private GenericContainer greetBuiltImage = new GenericContainer( + new ImageFromDockerfile( + "dev.local/jbang-test/swf-test:" + Math.round(Math.random() * 1000000.00)) + .withDockerfile(Paths.get(getScriptDirPath(), "resources/greet", "Dockerfile")) + .withBuildArg("BUILDER_IMAGE_TAG", getTestImage())) + .withExposedPorts(8080) + .withEnv("KOGITO_SERVICE_URL", "http://localhost:8080") + .waitingFor(Wait.forHttp("/jsongreet")) + .withLogConsumer(logConsumer); + + @Test + public void testBuiltContainerAnswerCorrectly() throws URISyntaxException, IOException, InterruptedException { + greetBuiltImage.start(); + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("http://" + greetBuiltImage.getHost() + ":" + + greetBuiltImage.getFirstMappedPort() + "/jsongreet")) + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .timeout(Duration.ofSeconds(10)) + .POST(HttpRequest.BodyPublishers + .ofString("{\"workflowdata\" : {\"name\": \"John\", \"language\": \"English\"}}")) + .build(); + HttpResponse response = HttpClient.newHttpClient().send(request, BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + greetBuiltImage.stop(); + } + + @Container + private GenericContainer greetWithInputSchemaBuiltImage = new GenericContainer( + new ImageFromDockerfile( + "dev.local/jbang-test/swf-test:" + Math.round(Math.random() * 1000000.00)) + .withDockerfile(Paths.get(getScriptDirPath(), + "resources/greet-with-inputschema", "Dockerfile")) + .withBuildArg("BUILDER_IMAGE_TAG", getTestImage())) + .withExposedPorts(8080) + .withEnv("KOGITO_SERVICE_URL", "http://localhost:8080") + .waitingFor(Wait.forHttp("/greeting")) + .withLogConsumer(logConsumer); + + @Test + public void testBuiltContainerWithInputSchemaAnswerCorrectly() + throws URISyntaxException, IOException, InterruptedException { + greetWithInputSchemaBuiltImage.start(); + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("http://" + greetWithInputSchemaBuiltImage.getHost() + ":" + + greetWithInputSchemaBuiltImage.getFirstMappedPort() + "/greeting")) + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .timeout(Duration.ofSeconds(10)) + .POST(HttpRequest.BodyPublishers + .ofString("{\"name\": \"John\", \"language\": \"English\"}")) + .build(); + HttpResponse response = HttpClient.newHttpClient().send(request, BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + greetWithInputSchemaBuiltImage.stop(); + } + + public static void main(String... args) throws Exception { + // Log docker build. Source: + // https://github.com/testcontainers/testcontainers-java/issues/3093 + System.setProperty( + "org.slf4j.simpleLogger.log.com.github.dockerjava.api.command.BuildImageResultCallback", + "debug"); + ConsoleLauncher.main("--select-class=" + RunTests.class.getName(), + "--reports-dir=" + Paths.get(getOutputDir()).toString()); + } + + static String getTestImage() { + return System.getenv("TEST_IMAGE"); + } + + static String getOutputDir() { + return System.getenv("OUTPUT_DIR"); + } + + static String getScriptDirPath() { + return System.getenv("TESTS_SCRIPT_DIR_PATH"); + } +} \ No newline at end of file diff --git a/packages/kogito-swf-common/README.md b/packages/kogito-swf-common/README.md new file mode 100644 index 00000000000..1f2067bff57 --- /dev/null +++ b/packages/kogito-swf-common/README.md @@ -0,0 +1,39 @@ +# kogito-swf-common + +This package contains the necessary resources to help other modules to build the `kogito-swf-{builder|devmode}` images. + +The contents of this package are: + +- [Makefile](./resources/Makefile): convenience tool to help building and testing the images. +- [Cekit Modules](./resources/modules): Common Cekit Module descriptors to be used when building the images. +- [Utility Scripts](./resources/scripts): Utility scripts to be used during the image building process or bootstraping packages +- [Testing infra](./resources/tests): Testing infra to help testing the generated images + +## Requirements + +- **python3** with the following packages installed: + - `behave` `lxml` `docker` `docker-squash` `elementPath` `pyyaml` `ruamel.yaml` `python-dateutil` `Jinja2` `pykwalify` `colorlog` `click` +- **cekit 4.11.0**: [docs.cekit.io](https://docs.cekit.io/en/latest/index.html) +- **make** +- **docker** or **podman** + +## Using the Makefile + +To build and tests the images the package provides a convenient `Makefile` that will do the hard work for you. It relies in the following Envs (or arguments): + +- `SWF_IMAGE_NAME`: (required) Specifies the image name to build. It should match the image descriptor. +- `SWF_IMAGE_REGISTRY`: Image registry to use, defaults to 'quay.io' +- `SWF_IMAGE_REGISTRY_ACCOUNT`: Image registry account to use, defaults to 'kiegroup' +- `SWF_IMAGE_TAG`: Custom tag for the image. If not provided it will use the version in the image descriptor. + +- `QUARKUS_PLATFORM_VERSION`: (required) Quarkus platform version to use inside the image. +- `KOGITO_VERSION`: (required) Kogito platform version to use inside the image. + +- `CEKIT_BUILD_OPTIONS`: extra build options, please refer to [docs.cekit.io](https://docs.cekit.io/en/latest/index.html) +- `BUILD_ENGINE`: (docker/podman) engine used to build the image, defaults to docker +- `BUILD_ENGINE_OPTIONS`: extra build options to pass to the build engine + +## Building images.. + +- Copy your image descriptor and modules along with the contents of the `resources` into a separate folder (eg: `/tmp/build`) +- diff --git a/packages/kogito-swf-common/env/index.js b/packages/kogito-swf-common/env/index.js new file mode 100644 index 00000000000..9213caf648f --- /dev/null +++ b/packages/kogito-swf-common/env/index.js @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 } = require("@kie-tools-scripts/build-env"); + +module.exports = composeEnv([require("@kie-tools/root-env/env")], { + vars: varsWithName({}), + get env() { + return { + kogitoSwfCommon: { + version: require("../package.json").version, + }, + }; + }, +}); diff --git a/packages/kogito-swf-common/install.js b/packages/kogito-swf-common/install.js new file mode 100644 index 00000000000..bfad9eb1271 --- /dev/null +++ b/packages/kogito-swf-common/install.js @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 { execSync } = require("child_process"); + +const buildEnv = require("./env"); +const path = require("path"); +const pythonVenvDir = path.dirname(require.resolve("@kie-tools/python-venv/package.json")); + +const activateCmd = + process.platform === "win32" + ? `${pythonVenvDir}\\venv\\Scripts\\Activate.bat` + : `. ${pythonVenvDir}/venv/bin/activate`; + +execSync( + `${activateCmd} && \ + python3 ./resources/scripts/versions_manager.py --bump-to ${buildEnv.env.kogitoSwfCommon.version} --source-folder ./resources`, + { stdio: "inherit" } +); diff --git a/packages/kogito-swf-common/package.json b/packages/kogito-swf-common/package.json new file mode 100644 index 00000000000..115f5fc677e --- /dev/null +++ b/packages/kogito-swf-common/package.json @@ -0,0 +1,29 @@ +{ + "private": true, + "name": "@kie-tools/kogito-swf-common", + "version": "0.0.0", + "description": "", + "license": "Apache-2.0", + "homepage": "https://github.com/apache/incubator-kie-tools", + "repository": { + "type": "git", + "url": "https://github.com/apache/incubator-kie-tools.git" + }, + "bugs": { + "url": "https://github.com/apache/incubator-kie-tools/issues" + }, + "scripts": { + "install": "node install.js" + }, + "devDependencies": { + "@kie-tools/python-venv": "workspace:*", + "@kie-tools/root-env": "workspace:*" + }, + "kieTools": { + "requiredPreinstalledCliCommands": [ + "python3", + "pip3", + "make" + ] + } +} \ No newline at end of file diff --git a/packages/kogito-swf-common/resources/Makefile b/packages/kogito-swf-common/resources/Makefile new file mode 100644 index 00000000000..8c2303c2d4c --- /dev/null +++ b/packages/kogito-swf-common/resources/Makefile @@ -0,0 +1,82 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +.DEFAULT_GOAL := build + +# Image build envs +CEKIT_BUILD_OPTIONS ?= +CEKIT_CMD := cekit ${CEKIT_BUILD_OPTIONS} +BUILD_ENGINE ?= docker +BUILD_ENGINE_OPTIONS ?= + +# Resolving the current image version from the kogito.project.versions module. Cekit will use it to tag the image. +CURRENT_IMAGE_VERSION := $(shell python3 scripts/retrieve_version.py) + +# SWF Image creation envs +SWF_IMAGE_NAME ?= # Image name +SWF_IMAGE_REGISTRY ?= 'quay.io' +SWF_IMAGE_REGISTRY_ACCOUNT ?= 'kiegroup' +SWF_IMAGE_TAG ?= $(CURRENT_IMAGE_VERSION) # Setting a default value if SWF_IMAGE_TAG env is not present +SWF_FULL_IMAGE_NAME := $(SWF_IMAGE_REGISTRY)/$(SWF_IMAGE_REGISTRY_ACCOUNT)/$(SWF_IMAGE_NAME) +SWF_IMAGE_FILENAME := ${SWF_IMAGE_NAME}-image.yaml + +_check_swf_image_name: +ifndef SWF_IMAGE_NAME + $(error Cannot build image, please provide a valid image name using the SWF_IMAGE_NAME env) +endif + +# Check if there are Quarkus and Kogito version envs +_check_versions: +ifndef QUARKUS_PLATFORM_VERSION + $(error Cannot build image, please provide a valid Quarkus version using the QUARKUS_PLATFORM_VERSION env) +endif +ifndef KOGITO_VERSION + $(error Cannot build image, please provide a valid Kogito version using the KOGITO_VERSION env) +endif + +# Upgrade Quarkus & Kogito versions in the images and modules +_run_version_manager: +ifneq ($(SONATAFLOW_QUARKUS_DEVUI_VERSION),) + python3 scripts/versions_manager.py --quarkus-version ${QUARKUS_PLATFORM_VERSION} --kogito-version ${KOGITO_VERSION} --sonataflow-quarkus-devui-version ${SONATAFLOW_QUARKUS_DEVUI_VERSION} +else + python3 scripts/versions_manager.py --quarkus-version ${QUARKUS_PLATFORM_VERSION} --kogito-version ${KOGITO_VERSION} +endif + +_fix_platform_versions: _check_versions _run_version_manager + +# Building the SWF image with Cekit +_cekit_build: + ${CEKIT_CMD} --descriptor ${SWF_IMAGE_FILENAME} build ${CEKIT_BUILD_OPTIONS} ${BUILD_ENGINE} ${BUILD_ENGINE_OPTIONS} + +# Tagging the generated image if SWF_IMAGE_TAG doesn't match the CURRENT_IMAGE_VERSION +_tag_image: +ifneq ($(SWF_IMAGE_TAG), $(CURRENT_IMAGE_VERSION)) + ${BUILD_ENGINE} tag ${SWF_FULL_IMAGE_NAME}:${CURRENT_IMAGE_VERSION} ${SWF_FULL_IMAGE_NAME}:${SWF_IMAGE_TAG} +endif + +# Trigger the image tests +.PHONY test-image: _check_swf_image_name bats _test_image +_test_image: + ${CEKIT_CMD} --descriptor ${SWF_IMAGE_FILENAME} test behave + tests/shell/run.sh ${SWF_IMAGE_NAME} ${SWF_FULL_IMAGE_NAME}:${SWF_IMAGE_TAG} + +.PHONY build: _check_swf_image_name _fix_platform_versions _cekit_build _tag_image + +# run bat tests locally +.PHONY: bats +bats: + ./scripts/run-bats.sh \ No newline at end of file diff --git a/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/added/container-limits b/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/added/container-limits new file mode 100644 index 00000000000..f262ee7c408 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/added/container-limits @@ -0,0 +1,137 @@ +#!/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. +# +# Detects container limits +# If found these are exposed as the following environment variables: +# +# - CONTAINER_MAX_MEMORY +# - CONTAINER_CORE_LIMIT +# +# This script is meant to be sourced. + +if [ "${SCRIPT_DEBUG}" = "true" ] ; then + set -x +fi + +# query the resources based on cgroups version +# cgroups v1 points to tmpfs +# cgroups v2 points to cgroup2fs +CGROUPS_VERSION="v1" +tmp_fs=$(stat -fc %T /sys/fs/cgroup) +if [ "${tmp_fs}" = "cgroup2fs" ]; then + CGROUPS_VERSION="v2" +fi + + +ceiling() { + awk -vnumber="$1" -vdiv="$2" ' + function ceiling(x){ + return x%1 ? int(x)+1 : x + } + BEGIN{ + print ceiling(number/div) + } + ' +} + +# Based on the cgroups limits, figure out the max number of core we should use +core_limit() { + if [ "${CGROUPS_VERSION}" = "v1" ]; then + local cpu_period_file="/sys/fs/cgroup/cpu/cpu.cfs_period_us" + local cpu_quota_file="/sys/fs/cgroup/cpu/cpu.cfs_quota_us" + if [ -r "${cpu_period_file}" ]; then + local cpu_period="$(cat ${cpu_period_file})" + if [ -r "${cpu_quota_file}" ]; then + local cpu_quota="$(cat ${cpu_quota_file})" + # cfs_quota_us == -1 --> no restrictions + if [ "x$cpu_quota" != "x-1" ]; then + ceiling "$cpu_quota" "$cpu_period" + fi + fi + fi + else + # v2 + # on cgroupsv2 the period and quota a queried from the same file + local cpu_max_file="/sys/fs/cgroup/cpu.max" + # when both are set we will have the following output: + # $MAX $PERIOD + # where the first number is the quota/max and the second is the period + # if the quota/max is not set then we will have only the period set: + # max 100000 + if [ -r "${cpu_max_file}" ]; then + local cpu_max="$(cat ${cpu_max_file})" + if [ "x$cpu_max" != "x" ]; then + local cpu_quota="$(echo $cpu_max | awk '{print $1}')" + local cpu_period="$(echo $cpu_max | awk '{print $2}')" + if [ "$cpu_quota" != "max" ] && [ "x$cpu_period" != "x" ]; then + ceiling "$cpu_quota" "$cpu_period" + fi + fi + fi + fi +} + +max_unbounded() { + cat /proc/meminfo | grep 'MemTotal:' | awk '{print $2*1024}' +} + +container_memory() { + local max_mem_unbounded="$(max_unbounded)" + # High number which is the max limit unit which memory is supposed to be unbounded. + if [ "${CGROUPS_VERSION}" = "v1" ]; then + local mem_file="/sys/fs/cgroup/memory/memory.limit_in_bytes" + if [ -r "${mem_file}" ]; then + local max_mem="$(cat ${mem_file})" + if [ ${max_mem} -lt ${max_mem_unbounded} ]; then + echo "${max_mem}" + fi + fi + else + # v2 + local mem_file="/sys/fs/cgroup/memory.max" + if [ -r "${mem_file}" ]; then + local max_mem="$(cat ${mem_file})" + # if not set, it will contain only the string "max" + if [ "$max_mem" != "max" ]; then + if [ ${max_mem} -lt ${max_mem_unbounded} ]; then + echo "${max_mem}" + fi + fi + fi + fi +} + +min() { + printf "%s\n" "$@" | sort -g | head -n1 +} + +limit="$(core_limit)" +if [ x$limit != x ]; then + export CONTAINER_CORE_LIMIT="$limit" +fi + +env_core_limit="$(min $CONTAINER_CORE_LIMIT $JAVA_CORE_LIMIT)" +if [ -n "$env_core_limit" ]; then + export CORE_LIMIT="$env_core_limit" +fi + +max_mem="$(container_memory)" +if [ x$max_mem != x ]; then + export CONTAINER_MAX_MEMORY="$max_mem" +fi diff --git a/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/added/debug-options b/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/added/debug-options new file mode 100644 index 00000000000..b7ea7d4ed10 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/added/debug-options @@ -0,0 +1,35 @@ +#!/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. +# +# Check for debug options and echo them if enabled. Meant to be included by +# a run script. + +if [ "${SCRIPT_DEBUG}" = "true" ] ; then + set -x +fi + +debug_options() { + if [ "x${JAVA_DEBUG}" != "x" ]; then + local debug_port=${JAVA_DEBUG_PORT:-5005} + echo "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${debug_port}" + fi +} + +## Echo options, trimming trailing and multiple spaces +echo "$(debug_options)" | awk '$1=$1' diff --git a/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/added/java-default-options b/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/added/java-default-options new file mode 100644 index 00000000000..5ec707a68f7 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/added/java-default-options @@ -0,0 +1,201 @@ +#!/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. +# +# ================================================================= +# Detect whether running in a container and set appropriate options +# for limiting Java VM resources +# +# Usage: JAVA_OPTS="$(java-default-options) $(debug_options)" + +# Env Vars respected: + +# JAVA_OPTIONS: Checked for already set options. +# JAVA_OPTS: Checked for already set options +# JAVA_INITIAL_MEM_RATIO: Ratio of maximum memory to use for initial heap size +# (i.e. -Xms). Defaults to 25 (i.e -Xms=-Xmx/4). +# JAVA_MAX_INITIAL_MEM: The maximum value of the initial heap size, defaults to 4G. +# JAVA_MAX_MEM_RATIO: Ratio use to calculate a default maximum Memory, in percent. +# E.g. the default value "50" implies that 50% of the Memory +# given to the container is used as the maximum heap memory with +# '-Xmx'. It is a heuristic and should be better backed up with real +# experiments and measurements. +# For a good overviews what tuning options are available --> +# https://youtu.be/Vt4G-pHXfs4 +# https://www.youtube.com/watch?v=w1rZOY5gbvk +# https://vimeo.com/album/4133413/video/181900266 +# Also note that heap is only a small portion of the memory used by a JVM. There are lot +# of other memory areas (metadata, thread, code cache, ...) which addes to the overall +# size. There is no easy solution for this, 50% seems to be are reasonable compromise. +# However, when your container gets killed because of an OOM, then you should tune +# the absolute values +# +if [ "${SCRIPT_DEBUG}" = "true" ] ; then + set -x +fi + +__DEFAULT_JAVA_MAX_MEM_RATIO=50 +__DEFAULT_JAVA_INITIAL_MEM_RATIO=25 +__DEFAULT_JAVA_MAX_INITIAL_MEM=4096 + +# stubs for jvm specific overrides +jvm_specific_options() { + : +} + +jvm_specific_diagnostics() { + : +} + +# Include overridden jvm_specific_*() functions +if [ -f "${JBOSS_CONTAINER_OPENJDK_JDK_MODULE}/jvm-options" ]; then + source "${JBOSS_CONTAINER_OPENJDK_JDK_MODULE}/jvm-options" +fi + +initialize_container_limits() { + # we can't run without limits + source ${JBOSS_CONTAINER_JAVA_JVM_MODULE}/container-limits +} + +# Check for memory options and calculate a sane default if not given +max_memory() { + # Check whether -Xmx is already given in JAVA_OPTIONS. Then we dont + # do anything here + # XXX: I think this should be removed. If folks want to hard code max/min, + # then they can set the ratios to zero and set the options in JAVA_OPTS_APPEND. + if echo "${JAVA_OPTS:-${JAVA_OPTIONS}}" | grep -q -- "-Xmx"; then + return + fi + + # Check if explicitly disabled + if [ "x$JAVA_MAX_MEM_RATIO" = "x0" ]; then + return + fi + + # Check for the 'real memory size' and calculate mx from a ratio + # given (default is 50%) + if [ "x$CONTAINER_MAX_MEMORY" != x ]; then + local max_mem="${CONTAINER_MAX_MEMORY}" + local ratio=${JAVA_MAX_MEM_RATIO:-${__DEFAULT_JAVA_MAX_MEM_RATIO}} + local mx=$(echo "${max_mem} ${ratio} 1048576" | awk '{printf "%d\n" , ($1*$2)/(100*$3) + 0.5}') + echo "-Xmx${mx}m" + fi +} + +# Check for memory options and calculate a sane default if not given +initial_memory() { + # Check whether -Xms is already given in JAVA_OPTS. Then we dont + # do anything here + # XXX: I think this should be removed. If folks want to hard code max/min, + # then they can set the ratios to zero and set the options in JAVA_OPTS_APPEND. + if echo "${JAVA_OPTS:-${JAVA_OPTIONS}}" | grep -q -- "-Xms"; then + return + fi + + # Check if explicitly disabled + if [ "x$JAVA_INITIAL_MEM_RATIO" = "x0" ]; then + return + fi + + # Check for the 'real memory size' and calculate ms from a ratio + # given (default is 25%) + if [ "x$CONTAINER_MAX_MEMORY" != x ]; then + local max_mem="${CONTAINER_MAX_MEMORY}" + local max_ratio=${JAVA_MAX_MEM_RATIO:-${__DEFAULT_JAVA_MAX_MEM_RATIO}} + local initial_ratio=${JAVA_INITIAL_MEM_RATIO:-${__DEFAULT_JAVA_INITIAL_MEM_RATIO}} + local ms=$(echo "${max_mem} ${max_ratio} ${initial_ratio} 1048576" | awk '{printf "%d\n" , ($1*(($2*$3)/10000))/$4 + 0.5}') + local max_initial_memory=${JAVA_MAX_INITIAL_MEM:-${__DEFAULT_JAVA_MAX_INITIAL_MEM}} + if [ "${ms}" -lt "${max_initial_memory}" ] ; then + echo "-Xms${ms}m" + else + echo "-Xms${max_initial_memory}m" + fi + fi +} + +# Switch on diagnostics except when switched off +diagnostics() { + if [ "x$JAVA_DIAGNOSTICS" != "x" ]; then + echo "$(jvm_specific_diagnostics)" + fi +} + +cpu_core_tunning() { + # If both are set rely on JAVA_CORE_LIMIT limited to CONTAINER_CORE_LIMIT + # If none are set, just return. + local core_limit=${JAVA_CORE_LIMIT:-${CONTAINER_CORE_LIMIT}} + if [ "x$core_limit" = "x0" -o "x$core_limit" = "x" ]; then + return + else + if [ "x$CONTAINER_CORE_LIMIT" != "x" ] && [ $core_limit -gt $CONTAINER_CORE_LIMIT ]; then + core_limit=$CONTAINER_CORE_LIMIT + fi + echo "-XX:ParallelGCThreads=${core_limit} " \ + "-Djava.util.concurrent.ForkJoinPool.common.parallelism=${core_limit} "\ + "-XX:CICompilerCount=2" + fi +} + +gc_config() { + local minHeapFreeRatio=${GC_MIN_HEAP_FREE_RATIO:-10} + local maxHeapFreeRatio=${GC_MAX_HEAP_FREE_RATIO:-20} + local timeRatio=${GC_TIME_RATIO:-4} + local adaptiveSizePolicyWeight=${GC_ADAPTIVE_SIZE_POLICY_WEIGHT:-90} + local maxMetaspaceSize + local gcOptions="${GC_CONTAINER_OPTIONS:--XX:+UseParallelGC}" + # for compat reasons we don't set a default value for metaspaceSize + local metaspaceSize + + if [ -n "${GC_MAX_METASPACE_SIZE}" ]; then + maxMetaspaceSize=${GC_MAX_METASPACE_SIZE} + fi + + if [ -n "${GC_METASPACE_SIZE}" ]; then + metaspaceSize=${GC_METASPACE_SIZE} + if [ -n "${maxMetaspaceSize}" ]; then + # clamp the max size of metaspaceSize to be <= maxMetaspaceSize + if [ "${metaspaceSize}" -gt "${maxMetaspaceSize}" ]; then + metaspaceSize=${maxMetaspaceSize} + fi + fi + fi + + local allOptions="$(jvm_specific_options) " + allOptions+="${gcOptions} " + allOptions+="-XX:MinHeapFreeRatio=${minHeapFreeRatio} " + allOptions+="-XX:MaxHeapFreeRatio=${maxHeapFreeRatio} " + allOptions+="-XX:GCTimeRatio=${timeRatio} " + allOptions+="-XX:AdaptiveSizePolicyWeight=${adaptiveSizePolicyWeight} " + if [ -n "${maxMetaspaceSize}" ]; then + allOptions+="-XX:MaxMetaspaceSize=${maxMetaspaceSize}m " + fi + if [ -n "${metaspaceSize}" ]; then + allOptions+="-XX:MetaspaceSize=${metaspaceSize}m " + fi + + echo "${allOptions}" +} + +error_handling() { + echo "-XX:+ExitOnOutOfMemoryError" +} + +initialize_container_limits > /dev/null + +## Echo options, trimming trailing and multiple spaces +echo "$(initial_memory) $(max_memory) $(gc_config) $(diagnostics) $(cpu_core_tunning) $(error_handling)" | awk '$1=$1' diff --git a/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/configure b/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/configure new file mode 100644 index 00000000000..4a24c6e9a75 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/configure @@ -0,0 +1,29 @@ +#!/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 + +SCRIPT_DIR=$(dirname "$0") + +mkdir -p "${JBOSS_CONTAINER_JAVA_JVM_MODULE}" + +cp -prv "${SCRIPT_DIR}"/added/* "${JBOSS_CONTAINER_JAVA_JVM_MODULE}"/ +chown -R kogito:root "${JBOSS_CONTAINER_JAVA_JVM_MODULE}" +chmod -R ug+x-w "${JBOSS_CONTAINER_JAVA_JVM_MODULE}"/ + diff --git a/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/module.yaml b/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/module.yaml new file mode 100644 index 00000000000..8761f126a4f --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-dynamic-resources/module.yaml @@ -0,0 +1,75 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: org.kie.kogito.dynamic.resources +version: "0.0.0" + +description: -| Module retrieved from https://github.com/jboss-openshift/cct_module/blob/master/jboss/container/java/jvm/bash However it contains a few customizations to fit Kogito needs. + +execute: + - script: configure + +envs: + - name: JAVA_OPTIONS + description: User specified Java options to be appended to generated options in JAVA_OPTS (internal use). + example: "-verbose:class" + - name: JAVA_MAX_MEM_RATIO + description: Is used when no `-Xmx` option is given in **JAVA_OPTIONS**. This is used to calculate a default maximal heap memory based on a containers restriction. If used in a container without any memory constraints for the container then this option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio of the container available memory as set here. The default is `50` which means 50% of the available memory is used as an upper boundary. You can skip this mechanism by setting this value to `0` in which case no `-Xmx` option is added. + - name: JAVA_INITIAL_MEM_RATIO + description: Is used when no `-Xms` option is given in **JAVA_OPTIONS**. This is used to calculate a default initial heap memory based on the maximum heap memory. If used in a container without any memory constraints for the container then this option has no effect. If there is a memory constraint then `-Xms` is set to a ratio of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx` is used as the initial heap size. You can skip this mechanism by setting this value to `0` in which case no `-Xms` option is added. + example: "25" + - name: JAVA_MAX_INITIAL_MEM + description: Is used when no `-Xms` option is given in **JAVA_OPTIONS**. This is used to calculate the maximum value of the initial heap memory. If used in a container without any memory constraints for the container then this option has no effect. If there is a memory constraint then `-Xms` is limited to the value set here. The default is 4096Mb which means the calculated value of `-Xms` never will be greater than 4096Mb. The value of this variable is expressed in MB. + example: "4096" + - name: JAVA_DIAGNOSTICS + description: Set this to get some diagnostics information to standard output when things are happening. **Disabled by default.** + example: "true" + - name: JAVA_DEBUG + description: If set remote debugging will be switched on. **Disabled by default.** + example: "true" + - name: JAVA_DEBUG_PORT + description: Port used for remote debugging. Defaults to *5005*. + example: "8787" + - name: CONTAINER_CORE_LIMIT + description: A calculated core limit as described in https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. + example: "2" + - name: CONTAINER_MAX_MEMORY + description: Memory limit given to the container. + example: "1024" + - name: GC_MIN_HEAP_FREE_RATIO + description: Minimum percentage of heap free after GC to avoid expansion. + example: "20" + - name: GC_MAX_HEAP_FREE_RATIO + description: Maximum percentage of heap free after GC to avoid shrinking. + example: "40" + - name: GC_TIME_RATIO + description: Specifies the ratio of the time spent outside the garbage collection (for example, the time spent for application execution) to the time spent in the garbage collection. + example: "4" + - name: GC_ADAPTIVE_SIZE_POLICY_WEIGHT + description: The weighting given to the current GC time versus previous GC times. + example: "90" + - name: GC_METASPACE_SIZE + description: The initial metaspace size. + example: "20" + - name: GC_MAX_METASPACE_SIZE + description: The maximum metaspace size. + example: "100" + - name: GC_CONTAINER_OPTIONS + description: specify Java GC to use. The value of this variable should contain the necessary JRE command-line options to specify the required GC, which will override the default of `-XX:+UseParallelGC`. + example: -XX:+UseG1GC diff --git a/packages/kogito-swf-common/resources/modules/kogito-launch-scripts/added/configure.sh b/packages/kogito-swf-common/resources/modules/kogito-launch-scripts/added/configure.sh new file mode 100644 index 00000000000..8244ba32ff6 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-launch-scripts/added/configure.sh @@ -0,0 +1,132 @@ +#!/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. +# + +# This script executes a list of modules defined by CONFIGURE_SCRIPTS. +# +# Configuration occurs over three basic phases: preConfigure, configure and +# postConfigure. +# +# The configure phase is special in that it iterates over a series of +# environments. In addition to the execution environment, users may specify +# additional configuration details through environment scripts specified through +# the ENV_FILES variable. The processing of env files is similar to the process +# for the execution environment, with the addition of a prepareEnv method, which +# is used to clean the environment before processing the env contributed by +# a file. This is to help ensure that duplicate configurations are not created +# when processing env files. +# +# The following details the API which the modules may implement. If a +# particular function is not implemented by a module, it is treated as a no-op. +# +# preConfigure: invoked before any configuration takes place. Use this to +# manipulate the environment prior to configuration. For +# example, the backward-compatiblity.sh module initializes +# environment variables from older variable names, if present. +# +# configure: invoked to configure based on the execution environment. +# +# postConfigure: invoked after all configuration has been completed. +# +# prepareEnv: invoked prior to processing env files. Modules should +# use this to prepare the environment before processing +# configuration from a file, e.g. by unset variables +# defined in the execution environment to prevent duplicate +# configuration entries. This method is invoked once, as +# each env file is processed in a subshell, thus preventing +# contamination of the environment from file to file. +# +# preConfigureEnv: similar to preConfigure, except this is invoked after an env +# file has been sourced, but before configureEnv. +# +# configureEnv: similar to configure. +# +# postConfigureEnv: simliar to postConfigure, except that it is invoked for each +# env file. +# +# The reason the configuration API is duplicated for an Env, is that some +# modules may not support env files, or may require configuration of "singleton" +# type entries, which should only be processed once. +# + +#import +source "${KOGITO_HOME}"/launch/logging.sh + +# clear functions from any previous module +function prepareModule() { + unset -f preConfigure + unset -f configure + unset -f postConfigure + + unset -f prepareEnv + unset -f preConfigureEnv + unset -f configureEnv + unset -f postConfigureEnv +} + +# Execute a particular function from a module +# $1 - module file +# $2 - function name +function executeModule() { + # shellcheck source=/dev/null + source "$1" + if [ -n "$(type -t "$2")" ]; then + eval "$2" + fi +} + +# Run through the list of scripts, executing the specified function for each. +# $1 - function name +function executeModules() { + # shellcheck disable=SC2048 + for module in ${CONFIGURE_SCRIPTS[*]}; do + prepareModule + executeModule "${module}" "${1}" + done +} + +# Processes the files provided by ENV_FILES. Invokes the *Env functions for +# each module. Env processing is done in subshells. The outer subshell +# provides a sanitized environment, that will be used by each inner subshell. +# This insulates the execution environment from any changes made during env +# file processing, and keeps the base environment the same from file to file +# (i.e. we don't have to run prepareEnv for each file). +function processEnvFiles() { + if [ -n "$ENV_FILES" ]; then + executeModules prepareEnv + for prop_file_arg in ${ENV_FILES//,/ }; do + while IFS= read -r -d '' prop_file + do + if [ -f "${prop_file}" ]; then + source "${prop_file}" + executeModules preConfigureEnv + executeModules configureEnv + executeModules postConfigureEnv + else + log_warning "Could not process environment for ${prop_file}. File does not exist." + fi + done < <(find "${prop_file_arg}" -maxdepth 0 2>/dev/null) + done + fi +} + +executeModules preConfigure +executeModules configure +processEnvFiles +executeModules postConfigure \ No newline at end of file diff --git a/packages/kogito-swf-common/resources/modules/kogito-launch-scripts/configure b/packages/kogito-swf-common/resources/modules/kogito-launch-scripts/configure new file mode 100644 index 00000000000..096018fd528 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-launch-scripts/configure @@ -0,0 +1,26 @@ +#!/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 + +SOURCES_DIR=/tmp/artifacts +SCRIPT_DIR=$(dirname "${0}") + +mkdir -p "${KOGITO_HOME}"/launch +cp -v "${SCRIPT_DIR}"/added/* "${KOGITO_HOME}"/launch \ No newline at end of file diff --git a/packages/kogito-swf-common/resources/modules/kogito-launch-scripts/module.yaml b/packages/kogito-swf-common/resources/modules/kogito-launch-scripts/module.yaml new file mode 100644 index 00000000000..801c65cb8f1 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-launch-scripts/module.yaml @@ -0,0 +1,24 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: org.kie.kogito.launch.scripts +version: "0.0.0" + +execute: + - script: configure diff --git a/packages/kogito-swf-common/resources/modules/kogito-logging/added/logging.sh b/packages/kogito-swf-common/resources/modules/kogito-logging/added/logging.sh new file mode 100644 index 00000000000..9c72c21edb7 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-logging/added/logging.sh @@ -0,0 +1,43 @@ +#!/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. +# + + +BLACK='\033[0;30m' +RED='\033[0;31m' +YELLOW='\033[0;33m' +DEFAULT='\033[0m' + +function log_warning() { + local message="${1}" + + echo >&2 -e "${YELLOW}WARN ${message}${DEFAULT}" +} + +function log_error() { + local message="${1}" + + echo >&2 -e "${RED}ERROR ${message}${DEFAULT}" +} + +function log_info() { + local message="${1}" + + echo >&2 -e "INFO ${message}" +} diff --git a/packages/kogito-swf-common/resources/modules/kogito-logging/configure b/packages/kogito-swf-common/resources/modules/kogito-logging/configure new file mode 100644 index 00000000000..f16737b464c --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-logging/configure @@ -0,0 +1,25 @@ +#!/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. +# +SCRIPT_DIR=$(dirname "${0}") + +# logging +mkdir -p "${KOGITO_HOME}"/launch/ +cp -v "${SCRIPT_DIR}"/added/* "${KOGITO_HOME}"/launch/ +chmod +x-w "${KOGITO_HOME}"/launch/logging.sh \ No newline at end of file diff --git a/packages/kogito-swf-common/resources/modules/kogito-logging/module.yaml b/packages/kogito-swf-common/resources/modules/kogito-logging/module.yaml new file mode 100644 index 00000000000..238ed43465f --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-logging/module.yaml @@ -0,0 +1,24 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: org.kie.kogito.logging +version: "0.0.0" + +execute: + - script: configure diff --git a/packages/kogito-swf-common/resources/modules/kogito-maven/common/added/configure-maven.sh b/packages/kogito-swf-common/resources/modules/kogito-maven/common/added/configure-maven.sh new file mode 100644 index 00000000000..b2b41b7cba4 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-maven/common/added/configure-maven.sh @@ -0,0 +1,272 @@ +#!/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. +# + + +#Please keep them in alphabetical order +function prepareEnv() { + unset HTTP_PROXY_HOST + unset HTTP_PROXY_PORT + unset HTTP_PROXY_PASSWORD + unset HTTP_PROXY_USERNAME + unset HTTP_PROXY_NONPROXYHOSTS + unset HTTPS_PROXY + unset MAVEN_DOWNLOAD_OUTPUT + unset MAVEN_IGNORE_SELF_SIGNED_CERTIFICATE + unset MAVEN_MIRROR_URL + unset MAVEN_REPO_ID + unset MAVEN_REPO_LAYOUT + unset MAVEN_REPO_RELEASES_ENABLED + unset MAVEN_REPO_RELEASES_UPDATE_POLICY + unset MAVEN_REPO_RELEASES_CHECKSUM_POLICY + unset MAVEN_REPO_SNAPSHOTS_ENABLED + unset MAVEN_REPO_SNAPSHOTS_UPDATE_POLICY + unset MAVEN_REPO_SNAPSHOTS_CHECKSUM_POLICY + unset MAVEN_REPO_URL + unset MAVEN_REPOS +} + +function configure() { + log_info "Configure Maven" + + configure_proxy + configure_mirrors + configure_maven_download_output + configure_maven_offline_mode + ignore_maven_self_signed_certificates + set_kogito_maven_repo + add_maven_repo + configureMavenHome + + if [ "${SCRIPT_DEBUG}" = "true" ] ; then + cat "${MAVEN_SETTINGS_PATH}" + fi + + rm -rf *.bak +} + +# When Running on OpenShift with AnyUID the HOME environment variable gets overridden to "/" +# Maven build might fail with this issue: 'Could not create local repository at /.m2/repository' +# Set the property maven.home to $KOGITO_HOME so the HOME env is ignored. +function configureMavenHome() { + export MAVEN_ARGS_APPEND="${MAVEN_ARGS_APPEND} -Duser.home=${KOGITO_HOME}" +} + +# insert settings for HTTP proxy into maven settings.xml if supplied +function configure_proxy() { + # prefer old http_proxy_ format for username/password, but + # also allow proxy_ format. + HTTP_PROXY_USERNAME=${HTTP_PROXY_USERNAME:-$PROXY_USERNAME} + HTTP_PROXY_PASSWORD=${HTTP_PROXY_PASSWORD:-$PROXY_PASSWORD} + + proxy=${HTTPS_PROXY:-${https_proxy:-${HTTP_PROXY:-$http_proxy}}} + # if http_proxy_host/port is set, prefer that (oldest mechanism) + # before looking at HTTP(S)_PROXY + proxyhost=${HTTP_PROXY_HOST:-$(echo "${proxy}" | cut -d : -f 1,2)} + proxyport=${HTTP_PROXY_PORT:-$(echo "${proxy}" | cut -d : -f 3)} + + if [ -n "$proxyhost" ]; then + if echo "${proxyhost}" | grep -q -i https://; then + proxyport=${proxyport:-443} + proxyprotocol="https" + else + proxyport=${proxyport:-80} + proxyprotocol="http" + fi + + xml="\ + genproxy\ + true\ + $proxyprotocol\ + $proxyhost\ + $proxyport" + + if [ -n "$HTTP_PROXY_USERNAME" ] && [ -n "$HTTP_PROXY_PASSWORD" ]; then + xml="$xml\ + $HTTP_PROXY_USERNAME\ + $HTTP_PROXY_PASSWORD" + fi + if [ -n "$HTTP_PROXY_NONPROXYHOSTS" ]; then + nonproxyhosts="${HTTP_PROXY_NONPROXYHOSTS//|/\\|}" + xml="$xml\ + $nonproxyhosts" + fi + xml="$xml\ + " + sed -i.bak "s||${xml}|" "${MAVEN_SETTINGS_PATH}" + fi +} + +# insert settings for mirrors/repository managers into settings.xml if supplied +function configure_mirrors() { + if [ -n "$MAVEN_MIRROR_URL" ]; then + xml=" \ + mirror.default\ + $MAVEN_MIRROR_URL\ + external:*\ + " + sed -i.bak "s||$xml|" "${MAVEN_SETTINGS_PATH}" + fi +} + +function configure_maven_download_output() { + if [ "${MAVEN_DOWNLOAD_OUTPUT}" != "true" ]; then + export MAVEN_ARGS_APPEND="${MAVEN_ARGS_APPEND} --no-transfer-progress" + fi +} + +function configure_maven_offline_mode() { + if [ "${MAVEN_OFFLINE_MODE}" = "true" ]; then + log_info "Setup Maven offline mode. No artifact will be downloaded !!!" + export MAVEN_ARGS_APPEND="${MAVEN_ARGS_APPEND} -o" + fi +} + +function ignore_maven_self_signed_certificates() { + if [ "${MAVEN_IGNORE_SELF_SIGNED_CERTIFICATE}" == "true" ]; then + export MAVEN_ARGS_APPEND="${MAVEN_ARGS_APPEND} -Denforcer.skip -Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true" + fi +} + +function set_kogito_maven_repo() { + local kogito_maven_repo_url="${DEFAULT_MAVEN_REPO_URL}" + if [ -n "${kogito_maven_repo_url}" ]; then + sed -i.bak "s|https://repository.apache.org/content/groups/public/|${kogito_maven_repo_url}|" "${MAVEN_SETTINGS_PATH}" + fi +} + +function add_maven_repo() { + # single remote repository scenario: respect fully qualified url if specified, otherwise find and use service + local single_repo_url="${MAVEN_REPO_URL}" + if [ -n "$single_repo_url" ]; then + single_repo_id=$(_maven_find_env "MAVEN_REPO_ID" "repo-$(_generate_random_id)") + _add_maven_repo "$single_repo_url" "$single_repo_id" "" + fi + + # multiple remote repositories scenario: respect fully qualified url(s) if specified, otherwise find and use service(s); can be used together with "single repo scenario" above + local multi_repo_counter=1 + IFS=',' read -r -a multi_repo_prefixes <<<"${MAVEN_REPOS}" + for multi_repo_prefix in "${multi_repo_prefixes[@]}"; do + multi_repo_url=$(_maven_find_prefixed_env "${multi_repo_prefix}" "MAVEN_REPO_URL") + multi_repo_id=$(_maven_find_prefixed_env "${multi_repo_prefix}" "MAVEN_REPO_ID" "repo${multi_repo_counter}-$(_generate_random_id)") + _add_maven_repo "$multi_repo_url" "$multi_repo_id" "$multi_repo_prefix" + multi_repo_counter=$((multi_repo_counter + 1)) + done +} +# add maven repositories +# Parameters: +# $1 - repo url +# $2 - repo id +# $3 - repo prefix +function _add_maven_repo() { + local repo_url=$1 + local repo_id=$2 + local prefix=$3 + + repo_name=$(_maven_find_prefixed_env "${prefix}" "MAVEN_REPO_NAME" "${repo_id}") + repo_layout=$(_maven_find_prefixed_env "${prefix}" "MAVEN_REPO_LAYOUT" "default") + releases_enabled=$(_maven_find_prefixed_env "${prefix}" "MAVEN_REPO_RELEASES_ENABLED" "true") + releases_update_policy=$(_maven_find_prefixed_env "${prefix}" "MAVEN_REPO_RELEASES_UPDATE_POLICY" "always") + releases_checksum_policy=$(_maven_find_prefixed_env "${prefix}" "MAVEN_REPO_RELEASES_CHECKSUM_POLICY" "warn") + snapshots_enabled=$(_maven_find_prefixed_env "${prefix}" "MAVEN_REPO_SNAPSHOTS_ENABLED" "true") + snapshots_update_policy=$(_maven_find_prefixed_env "${prefix}" "MAVEN_REPO_SNAPSHOTS_UPDATE_POLICY" "always") + snapshots_checksum_policy=$(_maven_find_prefixed_env "${prefix}" "MAVEN_REPO_SNAPSHOTS_CHECKSUM_POLICY" "warn") + + local repo="\n\ + \n\ + ${repo_id}\n\ + ${repo_name}\n\ + ${repo_url}\n\ + ${repo_layout}\n\ + \n\ + ${releases_enabled}\n\ + ${releases_update_policy}\n\ + ${releases_checksum_policy}\n\ + \n\ + \n\ + ${snapshots_enabled}\n\ + ${snapshots_update_policy}\n\ + ${snapshots_checksum_policy}\n\ + \n\ + \n\ + " + sed -i.bak "s||${repo}|" "${MAVEN_SETTINGS_PATH}" + + local pluginRepo="\n\ + \n\ + ${repo_id}\n\ + ${repo_name}\n\ + ${repo_url}\n\ + ${repo_layout}\n\ + \n\ + ${releases_enabled}\n\ + ${releases_update_policy}\n\ + ${releases_checksum_policy}\n\ + \n\ + \n\ + ${snapshots_enabled}\n\ + ${snapshots_update_policy}\n\ + ${snapshots_checksum_policy}\n\ + \n\ + \n\ + " + + sed -i.bak "s||${pluginRepo}|" "${MAVEN_SETTINGS_PATH}" + + # new repo should be skipped by mirror if exists + sed -i.bak "s||,!${repo_id}|g" "${MAVEN_SETTINGS_PATH}" +} + +# Finds the environment variable and returns its value if found. +# Otherwise returns the default value if provided. +# +# Arguments: +# $1 env variable name to check +# $2 default value if environment variable was not set +function _maven_find_env() { + local var=${!1} + echo "${var:-$2}" +} + +# Finds the environment variable with the given prefix. If not found +# the default value will be returned. If no prefix is provided will +# rely on _maven_find_env +# +# Arguments +# - $1 prefix. Transformed to uppercase and replace - by _ +# - $2 variable name. Prepended by "prefix_" +# - $3 default value if the variable is not defined +function _maven_find_prefixed_env() { + local prefix=$1 + + if [[ -z $prefix ]]; then + _maven_find_env "${2}" "${3}" + else + prefix=${prefix^^} # uppercase + prefix=${prefix//-/_} #replace - by _ + + local var_name="${prefix}_${2}" + echo "${!var_name:-${3}}" + fi +} + +# private +function _generate_random_id() { + env LC_CTYPE=C < /dev/urandom tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1 +} diff --git a/packages/kogito-swf-common/resources/modules/kogito-maven/common/configure b/packages/kogito-swf-common/resources/modules/kogito-maven/common/configure new file mode 100755 index 00000000000..e28dccbbd17 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-maven/common/configure @@ -0,0 +1,39 @@ +#!/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 + +SOURCES_DIR=/tmp/artifacts +SCRIPT_DIR=$(dirname "${0}") + +mvn_install_dir="/usr/share/maven" + +# Verify if mvn is installed +if [ ! -d ${mvn_install_dir} ] && ! command -v mvn > /dev/null 2>&1 ; +then + echo "---> Maven not found, downloading and installing it" + tar xzf "${SOURCES_DIR}"/apache-maven-"${MAVEN_VERSION}"-bin.tar.gz -C /usr/share + mv /usr/share/apache-maven-"${MAVEN_VERSION}" ${mvn_install_dir} +else + echo "---> Maven already present in the current context" +fi + +mkdir "${KOGITO_HOME}"/.m2 +cp -v "${SCRIPT_DIR}"/maven/* "${KOGITO_HOME}"/.m2 +cp -v "${SCRIPT_DIR}"/added/* "${KOGITO_HOME}"/launch/ diff --git a/packages/kogito-swf-common/resources/modules/kogito-maven/common/maven/settings.xml b/packages/kogito-swf-common/resources/modules/kogito-maven/common/maven/settings.xml new file mode 100644 index 00000000000..2a23213c48b --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-maven/common/maven/settings.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + kogito-images + + + apache-public-repository-group + Apache Public Repository Group + https://repository.apache.org/content/groups/public/ + default + + true + never + + + true + always + + + + + + + + apache-public-repository-group + Apache Public Repository Group + https://repository.apache.org/content/groups/public/ + default + + true + never + + + true + always + + + + + + + + + kogito-images + + diff --git a/packages/kogito-swf-common/resources/modules/kogito-maven/common/module.yaml b/packages/kogito-swf-common/resources/modules/kogito-maven/common/module.yaml new file mode 100644 index 00000000000..bf616eaa8dc --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-maven/common/module.yaml @@ -0,0 +1,94 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: org.kie.kogito.maven.common +version: "0.0.0" + +envs: + - name: "MAVEN_VERSION" + description: "The Maven version to setup with this module" + - name: "MAVEN_HOME" + value: "/usr/share/maven" + - name: "MAVEN_SETTINGS_PATH" + description: "The location of the settings.xml file" + value: "${KOGITO_HOME}/.m2/settings.xml" + - name: "HTTP_PROXY" + description: "The location of the http proxy, will be used for both Maven builds and Java runtime." + example: "http://127.0.0.1:8080" + - name: "HTTP_PROXY_HOST" + description: "Proxy Host, don't need to be set if HTTP_PROXY is used." + example: "127.0.0.1" + - name: "HTTP_PROXY_PORT" + description: "Proxy Port, don't need to be set if HTTP_PROXY is used." + example: "8181" + - name: "HTTP_PROXY_PASSWORD" + description: "Proxy Password" + - name: "HTTP_PROXY_USERNAME" + description: "Proxy Username" + - name: "HTTP_PROXY_NONPROXYHOSTS" + description: "Non proxy hosts, list of hosts that will ot be proxied." + example: "localhost" + - name: "MAVEN_MIRROR_URL" + description: "The base URL of a mirror used for retrieving artifacts." + example: "http://10.0.0.1:8080/repository/internal/" + - name: "MAVEN_DOWNLOAD_OUTPUT" + description: "If set to true will print the transfer logs for downloading/uploading of maven dependencies. Defaults to false" + example: "true" + - name: "DEFAULT_MAVEN_REPO_URL" + value: "https://repository.apache.org/content/groups/public/" + description: "Defines the default Maven repository for Kogito artifacts." + - name: "MAVEN_REPO_URL" + description: "Defines an extra Maven repository." + example: "https://nexus.test.com/group/public" + - name: "MAVEN_REPO_ID" + description: "Defines the id of the new Repository" + example: "nexus-test" + - name: "MAVEN_REPO_LAYOUT" + description: "The type of layout this repository uses for locating and storing artifacts - can be 'legacy' or 'default'.Defaults to 'default'." + example: "legacy" + - name: "MAVEN_REPO_RELEASES_ENABLED" + description: "Whether to use this repository for downloading this type of artifact. Default value is: true." + example: "false" + - name: "MAVEN_REPO_RELEASES_UPDATE_POLICY" + description: "The frequency for downloading updates - can be 'always', 'daily', 'interval:XXX' (in minutes) or 'never'. Defaults to always." + example: "never" + - name: "MAVEN_REPO_RELEASES_CHECKSUM_POLICY" + description: "What to do when verification of an artifact checksum fails - warn, fail, etc. Valid values are 'fail' or 'warn'. Defaults to warn" + example: "fail" + - name: "MAVEN_REPO_SNAPSHOTS_ENABLED" + description: "Whether to use this repository for downloading this type of artifact. Default value is: true." + example: "false" + - name: "MAVEN_REPO_SNAPSHOTS_UPDATE_POLICY" + description: "The frequency for downloading updates - can be 'always', 'daily', 'interval:XXX' (in minutes) or 'never'. Defaults to always." + example: "never" + - name: "MAVEN_REPO_SNAPSHOTS_CHECKSUM_POLICY" + description: "What to do when verification of an artifact checksum fails - warn, fail, etc. Valid values are 'fail' or 'warn'. Defaults to warn" + example: "fail" + - name: "MAVEN_REPOS" + description: "Used to define multiple repositories, this env defines a prefix that will be used to create different repositories." + example: "CENTRAL,INTERNAL" + - name: "MAVEN_IGNORE_SELF_SIGNED_CERTIFICATE" + description: "When set, use of relaxed SSL check for user generated certificates. Default value is false" + example: "true" + - name: "MAVEN_OFFLINE_MODE" + description: "When set to true, tells Maven to work in offline mode. See Maven `-o` option for more information." + example: "true" + +execute: + - script: configure diff --git a/packages/kogito-swf-common/resources/modules/kogito-maven/tests/bats/maven-settings.bats b/packages/kogito-swf-common/resources/modules/kogito-maven/tests/bats/maven-settings.bats new file mode 100644 index 00000000000..8a7e85067c7 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-maven/tests/bats/maven-settings.bats @@ -0,0 +1,446 @@ +#!/usr/bin/env bats +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + + +# imports +source $BATS_TEST_DIRNAME/../../common/added/configure-maven.sh + + +setup() { + export HOME=$BATS_TMPDIR/maven + mkdir -p ${HOME}/.m2/ + cp $BATS_TEST_DIRNAME/../../common/maven/settings.xml ${HOME}/.m2/ + export MAVEN_SETTINGS_PATH="${HOME}/.m2/settings.xml" +} + +teardown() { + rm -rf ${HOME} +} + +# override this function, cat /dec/urandon makes the test hangs on GH actions +function _generate_random_id() { + echo "testing" | env LC_CTYPE=C tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1 +} + + +@test "test maven mirror configuration" { + prepareEnv + MAVEN_MIRROR_URL="http://localhost:8081/nexus/custom/repo/public" + run configure_mirrors + expected=" mirror.default http://localhost:8081/nexus/custom/repo/public external:* " + result=$(xmllint --xpath "//*[local-name()='mirrors']//*[local-name()='mirror']" ${HOME}/.m2/settings.xml) + echo "expected=${expected}" + echo "expected=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven proxy configuration with HTTPS_PROXY env custom port https" { + prepareEnv + HTTPS_PROXY="https://10.10.10.10:8443" + run configure_proxy + expected=" genproxy true https https://10.10.10.10 8443 " + result=$(xmllint --xpath "//*[local-name()='proxies']//*[local-name()='proxy']" ${HOME}/.m2/settings.xml) + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven proxy configuration with HTTPS_PROXY env default port https" { + prepareEnv + HTTPS_PROXY="https://10.10.10.10:" + run configure_proxy + expected=" genproxy true https https://10.10.10.10 443 " + result=$(xmllint --xpath "//*[local-name()='proxies']//*[local-name()='proxy']" ${HOME}/.m2/settings.xml) + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven proxy configuration with HTTPS_PROXY env custom port https with username and password" { + prepareEnv + HTTPS_PROXY="https://10.10.10.10:8443" + PROXY_USERNAME="hello" + PROXY_PASSWORD="impossible2guess" + run configure_proxy + expected=" genproxy true https https://10.10.10.10 8443 hello impossible2guess " + result=$(xmllint --xpath "//*[local-name()='proxies']//*[local-name()='proxy']" ${HOME}/.m2/settings.xml) + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven proxy configuration with HTTP_PROXY env custom port http" { + prepareEnv + HTTP_PROXY="http://10.10.10.20:8003" + run configure_proxy + expected=" genproxy true http http://10.10.10.20 8003 " + result=$(xmllint --xpath "//*[local-name()='proxies']//*[local-name()='proxy']" ${HOME}/.m2/settings.xml) + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven proxy configuration with HTTP_PROXY env default port http with password" { + prepareEnv + HTTP_PROXY="http://10.10.10.20" + PROXY_USERNAME="hello" + PROXY_PASSWORD="impossible2guess" + run configure_proxy + expected=" genproxy true http http://10.10.10.20 80 hello impossible2guess " + result=$(xmllint --xpath "//*[local-name()='proxies']//*[local-name()='proxy']" ${HOME}/.m2/settings.xml) + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven proxy configuration with HTTP_PROXY env custom port http with username" { + prepareEnv + HTTP_PROXY="http://10.10.10.20:8003" + run configure_proxy + expected=" genproxy true http http://10.10.10.20 8003 " + result=$(xmllint --xpath "//*[local-name()='proxies']//*[local-name()='proxy']" ${HOME}/.m2/settings.xml) + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven proxy configuration with PROXY_ envs http" { + prepareEnv + HTTP_PROXY_HOST="10.10.10.20" + HTTP_PROXY_PORT="8080" + HTTP_PROXY_PASSWORD="impossible2guess" + HTTP_PROXY_USERNAME="beleza_pura" + HTTP_PROXY_NONPROXYHOSTS="127.0.0.1|10.1.1.1" + run configure_proxy + expected=" genproxy true http 10.10.10.20 8080 beleza_pura impossible2guess 127.0.0.1|10.1.1.1 " + result=$(xmllint --xpath "//*[local-name()='proxies']//*[local-name()='proxy']" ${HOME}/.m2/settings.xml) + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven proxy configuration with PROXY_ envs default port http no username" { + prepareEnv + HTTP_PROXY_HOST="10.10.10.20" + HTTP_PROXY_NONPROXYHOSTS="127.0.0.1|10.1.1.1" + run configure_proxy + expected=" genproxy true http 10.10.10.20 80 127.0.0.1|10.1.1.1 " + result=$(xmllint --xpath "//*[local-name()='proxies']//*[local-name()='proxy']" ${HOME}/.m2/settings.xml) + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven proxy configuration with PROXY_ envs https" { + prepareEnv + HTTP_PROXY_HOST="https://10.10.10.20" + HTTP_PROXY_PORT="8443" + HTTP_PROXY_PASSWORD="impossible2guess" + HTTP_PROXY_USERNAME="beleza_pura" + HTTP_PROXY_NONPROXYHOSTS="127.0.0.1|10.1.1.1" + run configure_proxy + expected=" genproxy true https https://10.10.10.20 8443 beleza_pura impossible2guess 127.0.0.1|10.1.1.1 " + result=$(xmllint --xpath "//*[local-name()='proxies']//*[local-name()='proxy']" ${HOME}/.m2/settings.xml) + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven download output logs when MAVEN_DOWNLOAD_OUTPUT is not true" { + prepareEnv + configure_maven_download_output + expected=" --no-transfer-progress" + result="${MAVEN_ARGS_APPEND}" + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven download output logs when MAVEN_DOWNLOAD_OUTPUT is true" { + prepareEnv + MAVEN_DOWNLOAD_OUTPUT="true" + configure_maven_download_output + expected="" + result="${MAVEN_ARGS_APPEND}" + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven args when IGNORE_SELF_SIGNED_CERTIFICATE is true" { + prepareEnv + MAVEN_IGNORE_SELF_SIGNED_CERTIFICATE="true" + ignore_maven_self_signed_certificates + expected=" -Denforcer.skip -Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true" + result="${MAVEN_ARGS_APPEND}" + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven args when IGNORE_SELF_SIGNED_CERTIFICATE is false" { + prepareEnv + ignore_maven_self_signed_certificates + expected="" + result="${MAVEN_ARGS_APPEND}" + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} + +@test "test maven custom repo with ID and all supported configurations" { + prepareEnv + MAVEN_REPO_URL="http://my.cool.mvn.repo.severinolabs.com/group/public" + MAVEN_REPO_ID="my_cool_id" + MAVEN_REPO_LAYOUT="test" + MAVEN_REPO_RELEASES_ENABLED="true" + MAVEN_REPO_RELEASES_UPDATE_POLICY="never" + MAVEN_REPO_RELEASES_CHECKSUM_POLICY="test" + MAVEN_REPO_SNAPSHOTS_ENABLED="false" + MAVEN_REPO_SNAPSHOTS_UPDATE_POLICY="test" + MAVEN_REPO_SNAPSHOTS_CHECKSUM_POLICY="test" + + run add_maven_repo + + repository_expected=" + my_cool_id + my_cool_id + http://my.cool.mvn.repo.severinolabs.com/group/public + test + + true + never + test + + + false + test + test + + " + repository_result=$(xmllint --xpath "(//*[local-name()='profiles']//*[local-name()='profile']//*[local-name()='repositories']//*[local-name()='repository'])[last()]" ${HOME}/.m2/settings.xml) + echo "repository_expected=${repository_expected}" + echo "repository_result =${repository_result}" + [ "${repository_expected}" = "${repository_result}" ] + + plugin_repository_expected=" + my_cool_id + my_cool_id + http://my.cool.mvn.repo.severinolabs.com/group/public + test + + true + never + test + + + false + test + test + + " + plugin_repository_result=$(xmllint --xpath "(//*[local-name()='profiles']//*[local-name()='profile']//*[local-name()='pluginRepositories']//*[local-name()='pluginRepository'])[last()]" ${HOME}/.m2/settings.xml) + echo "plugin_repository_expected=${plugin_repository_expected}" + echo "plugin_repository_result =${plugin_repository_result}" + [ "${plugin_repository_expected}" = "${plugin_repository_result}" ] +} + + +@test "test maven custom repo with no ID and other configuration, test default values" { + prepareEnv + MAVEN_REPO_URL="http://my.cool.mvn.repo.severinolabs.com/group/public" + run add_maven_repo + + repository_url_expected="http://my.cool.mvn.repo.severinolabs.com/group/public" + repository_url_result=$(xmllint --xpath "(//*[local-name()='profiles']//*[local-name()='profile']//*[local-name()='repositories']//*[local-name()='repository']//*[local-name()='url'])[last()]" ${HOME}/.m2/settings.xml) + echo "repository_url_expected=${repository_url_expected}" + echo "repository_url_result =${repository_url_result}" + [ "${repository_url_expected}" = "${repository_url_result}" ] + + repository_releases_expected=" + true + always + warn + " + repository_releases_result=$(xmllint --xpath "(//*[local-name()='profiles']//*[local-name()='profile']//*[local-name()='repositories']//*[local-name()='repository']//*[local-name()='releases'])[last()]" ${HOME}/.m2/settings.xml) + echo "repository_releases_expected=${repository_releases_expected}" + echo "repository_releases_result =${repository_releases_result}" + [ "${repository_releases_expected}" = "${repository_releases_result}" ] + + repository_snapshots_expected=" + true + always + warn + " + repository_snapshots_result=$(xmllint --xpath "(//*[local-name()='profiles']//*[local-name()='profile']//*[local-name()='repositories']//*[local-name()='repository']//*[local-name()='snapshots'])[last()]" ${HOME}/.m2/settings.xml) + echo "repository_snapshots_expected=${repository_snapshots_expected}" + echo "repository_snapshots_result =${repository_snapshots_result}" + [ "${repository_snapshots_expected}" = "${repository_snapshots_result}" ] + + + plugin_repository_url_expected="http://my.cool.mvn.repo.severinolabs.com/group/public" + plugin_repository_url_result=$(xmllint --xpath "(//*[local-name()='profiles']//*[local-name()='profile']//*[local-name()='pluginRepositories']//*[local-name()='pluginRepository']//*[local-name()='url'])[last()]" ${HOME}/.m2/settings.xml) + echo "plugin_repository_url_expected=${plugin_repository_url_expected}" + echo "plugin_repository_url_result =${plugin_repository_url_result}" + [ "${plugin_repository_url_expected}" = "${plugin_repository_url_result}" ] + + plugin_repository_releases_expected=" + true + always + warn + " + plugin_repository_releases_result=$(xmllint --xpath "(//*[local-name()='profiles']//*[local-name()='profile']//*[local-name()='pluginRepositories']//*[local-name()='pluginRepository']//*[local-name()='releases'])[last()]" ${HOME}/.m2/settings.xml) + echo "plugin_repository_releases_expected=${plugin_repository_releases_expected}" + echo "plugin_repository_releases_result =${plugin_repository_releases_result}" + [ "${plugin_repository_releases_expected}" = "${plugin_repository_releases_result}" ] + + plugin_repository_snapshots_expected=" + true + always + warn + " + plugin_repository_snapshots_result=$(xmllint --xpath "(//*[local-name()='profiles']//*[local-name()='profile']//*[local-name()='pluginRepositories']//*[local-name()='pluginRepository']//*[local-name()='snapshots'])[last()]" ${HOME}/.m2/settings.xml) + echo "plugin_repository_snapshots_expected=${plugin_repository_snapshots_expected}" + echo "plugin_repository_snapshots_result =${plugin_repository_snapshots_result}" + [ "${plugin_repository_snapshots_expected}" = "${plugin_repository_snapshots_result}" ] +} + +@test "test maven multiple custom repos with ID and all supported configuration" { + prepareEnv + MAVEN_REPOS="CENTRAL,COMPANY" + CENTRAL_MAVEN_REPO_URL="http://central.severinolabs.com/group/public" + CENTRAL_MAVEN_REPO_ID="my_cool_id_central" + CENTRAL_MAVEN_REPO_LAYOUT="test" + CENTRAL_MAVEN_REPO_RELEASES_ENABLED="true" + CENTRAL_MAVEN_REPO_RELEASES_UPDATE_POLICY="never" + CENTRAL_MAVEN_REPO_RELEASES_CHECKSUM_POLICY="test" + CENTRAL_MAVEN_REPO_SNAPSHOTS_ENABLED="false" + CENTRAL_MAVEN_REPO_SNAPSHOTS_UPDATE_POLICY="test" + CENTRAL_MAVEN_REPO_SNAPSHOTS_CHECKSUM_POLICY="test" + + COMPANY_MAVEN_REPO_URL="http://company.severinolabs.com/group/public" + COMPANY_MAVEN_REPO_ID="my_cool_id_company" + COMPANY_MAVEN_REPO_LAYOUT="another-test" + COMPANY_MAVEN_REPO_RELEASES_ENABLED="true" + COMPANY_MAVEN_REPO_RELEASES_UPDATE_POLICY="never" + COMPANY_MAVEN_REPO_RELEASES_CHECKSUM_POLICY="another-test" + COMPANY_MAVEN_REPO_SNAPSHOTS_ENABLED="false" + COMPANY_MAVEN_REPO_SNAPSHOTS_UPDATE_POLICY="another-test" + COMPANY_MAVEN_REPO_SNAPSHOTS_CHECKSUM_POLICY="another-test" + + run add_maven_repo + + central_repository_expected=" + my_cool_id_central + my_cool_id_central + http://central.severinolabs.com/group/public + test + + true + never + test + + + false + test + test + + " + central_repository_result=$(xmllint --xpath "(//*[local-name()='profiles']//*[local-name()='profile']//*[local-name()='repositories']//*[local-name()='repository'])[last()-1]" ${HOME}/.m2/settings.xml) + echo "central_repository_expected=${central_repository_expected}" + echo "central_repository_result =${central_repository_result}" + [ "${central_repository_expected}" = "${central_repository_result}" ] + + company_repository_expected=" + my_cool_id_company + my_cool_id_company + http://company.severinolabs.com/group/public + another-test + + true + never + another-test + + + false + another-test + another-test + + " + company_repository_result=$(xmllint --xpath "(//*[local-name()='profiles']//*[local-name()='profile']//*[local-name()='repositories']//*[local-name()='repository'])[last()]" ${HOME}/.m2/settings.xml) + echo "company_repository_expected=${company_repository_expected}" + echo "company_repository_result =${company_repository_result}" + [ "${company_repository_expected}" = "${company_repository_result}" ] + + + central_plugin_repository_expected=" + my_cool_id_central + my_cool_id_central + http://central.severinolabs.com/group/public + test + + true + never + test + + + false + test + test + + " + central_plugin_repository_result=$(xmllint --xpath "(//*[local-name()='profiles']//*[local-name()='profile']//*[local-name()='pluginRepositories']//*[local-name()='pluginRepository'])[last()-1]" ${HOME}/.m2/settings.xml) + echo "central_plugin_repository_expected=${central_plugin_repository_expected}" + echo "central_plugin_repository_result =${central_plugin_repository_result}" + [ "${central_plugin_repository_expected}" = "${central_plugin_repository_result}" ] + + company_plugin_repository_expected=" + my_cool_id_company + my_cool_id_company + http://company.severinolabs.com/group/public + another-test + + true + never + another-test + + + false + another-test + another-test + + " + company_plugin_repository_result=$(xmllint --xpath "(//*[local-name()='profiles']//*[local-name()='profile']//*[local-name()='pluginRepositories']//*[local-name()='pluginRepository'])[last()]" ${HOME}/.m2/settings.xml) + echo "company_plugin_repository_expected=${company_plugin_repository_expected}" + echo "company_plugin_repository_result =${company_plugin_repository_result}" + [ "${company_plugin_repository_expected}" = "${company_plugin_repository_result}" ] +} + +@test "test maven args if it contains the user.home pointing to /home/kogito" { + # it is expected that KOGITO_HOME is already set. + export KOGITO_HOME=/home/kogito + prepareEnv + configureMavenHome + expected=" -Duser.home=/home/kogito" + result="${MAVEN_ARGS_APPEND}" + echo "expected=${expected}" + echo "result=${result}" + [ "${expected}" = "${result}" ] +} \ No newline at end of file diff --git a/packages/kogito-swf-common/resources/modules/kogito-project-versions/module.yaml b/packages/kogito-swf-common/resources/modules/kogito-project-versions/module.yaml new file mode 100644 index 00000000000..fb5dc14fc35 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-project-versions/module.yaml @@ -0,0 +1,33 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: org.kie.kogito.project.versions +version: "0.0.0" +description: "Kogito Project versions information" + +envs: + - name: "KOGITO_VERSION" + value: "### SET ME DURING BUILD PROCESS ###" + description: Defines the Kogito version to be used by the builder images. Not intended to be changed by end user. + - name: "QUARKUS_PLATFORM_VERSION" + value: "### SET ME DURING BUILD PROCESS ###" + description: Defines the Quarkus Platform version to be used by the builder images. Not intended to be changed by end user. + - name: "SONATAFLOW_QUARKUS_DEVUI_VERSION" + value: "### SET ME DURING BUILD PROCESS ###" + description: Defines the SonataFlow Quarkus Dev UI version to be used by the devmode image. Not intended to be changed by end user. diff --git a/packages/kogito-swf-common/resources/modules/kogito-swf/common/build/added/cleanup_project.sh b/packages/kogito-swf-common/resources/modules/kogito-swf/common/build/added/cleanup_project.sh new file mode 100755 index 00000000000..69e0a61e975 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-swf/common/build/added/cleanup_project.sh @@ -0,0 +1,43 @@ +#!/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. +# + +set -e + +#remove unnecessary files +echo 'Clean unnecessary files' +rm -rfv "${PROJECT_ARTIFACT_ID}"/target +rm -rfv "${PROJECT_ARTIFACT_ID}"/src/main/resources/* +rm -rfv "${PROJECT_ARTIFACT_ID}"/src/main/docker +rm -rfv "${PROJECT_ARTIFACT_ID}"/.mvn/wrapper +rm -rfv "${PROJECT_ARTIFACT_ID}"/mvnw* +rm -rfv "${PROJECT_ARTIFACT_ID}"/src/test +rm -rfv "${PROJECT_ARTIFACT_ID}"/*.bak + +# Maven useless files +# Needed to avoid Maven to automatically re-download from original Maven repository ... +echo 'Clean Maven useless files' +find "${KOGITO_HOME}"/.m2/repository -name _remote.repositories -type f -delete +find "${KOGITO_HOME}"/.m2/repository -name _maven.repositories -type f -delete +find "${KOGITO_HOME}"/.m2/repository -name '*.lastUpdated' -type f -delete + +# Remove files that include build timestamps to have reproducible images +find "${KOGITO_HOME}"/.m2/ -name resolver-status.properties -delete +# Remove quarkus registry +rm -rf "${KOGITO_HOME}"/.m2/repository/io/quarkus/registry/ diff --git a/packages/kogito-swf-common/resources/modules/kogito-swf/common/build/added/zip_files.sh b/packages/kogito-swf-common/resources/modules/kogito-swf/common/build/added/zip_files.sh new file mode 100755 index 00000000000..3e68296ef2c --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-swf/common/build/added/zip_files.sh @@ -0,0 +1,34 @@ +#!/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. +# + +set -e + +BUILD_OUTPUT="${KOGITO_HOME}"/build_output/ + +mkdir -p "${BUILD_OUTPUT}" + +echo "Zip and copy scaffold project" +tar cf kogito-swf-quarkus-app.tar -C "${PROJECT_ARTIFACT_ID}" . +cp -v kogito-swf-quarkus-app.tar "${BUILD_OUTPUT}" + +echo "Zip and copy maven repo" +cd "${KOGITO_HOME}"/.m2/repository/ +tar cf kogito-swf-maven-repo.tar . +cp -v kogito-swf-maven-repo.tar "${BUILD_OUTPUT}" \ No newline at end of file diff --git a/packages/kogito-swf-common/resources/modules/kogito-swf/common/build/configure.sh b/packages/kogito-swf-common/resources/modules/kogito-swf/common/build/configure.sh new file mode 100644 index 00000000000..50897c656b1 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-swf/common/build/configure.sh @@ -0,0 +1,43 @@ +#!/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. +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ADDED_DIR="${SCRIPT_DIR}"/added +LAUNCH_DIR="${KOGITO_HOME}"/launch +BUILD_DIR="${KOGITO_HOME}"/build + +mkdir -p "${BUILD_DIR}" +cp -v "${ADDED_DIR}"/* "${BUILD_DIR}" + +chown -R 1001:0 "${KOGITO_HOME}" +chmod -R ug+rwX "${KOGITO_HOME}" + +cd "${KOGITO_HOME}" + +# Create app +"${LAUNCH_DIR}"/create-app.sh + +"${BUILD_DIR}"/cleanup_project.sh +"${BUILD_DIR}"/zip_files.sh + +chown -R 1001:0 "${KOGITO_HOME}" +chmod -R ug+rwX "${KOGITO_HOME}" \ No newline at end of file diff --git a/packages/kogito-swf-common/resources/modules/kogito-swf/common/build/module.yaml b/packages/kogito-swf-common/resources/modules/kogito-swf/common/build/module.yaml new file mode 100644 index 00000000000..34aa51197bb --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-swf/common/build/module.yaml @@ -0,0 +1,25 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: org.kie.kogito.swf.common.build +version: "0.0.0" +description: "Kogito Serverless Workflow image build process" + +execute: + - script: configure.sh diff --git a/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/add-extension.sh b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/add-extension.sh new file mode 100755 index 00000000000..6dc158d2a08 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/add-extension.sh @@ -0,0 +1,49 @@ +#!/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. +# + +set -e + +script_dir_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# extensions to be added, comma separated. +extensions="$1" +# parameter passed which will trigger or not the jvm/maven configuration. +ignore_jvm_settings=${2:-false} + +# shellcheck source=/dev/null +source "${script_dir_path}"/logging.sh + +if [ "${SCRIPT_DEBUG}" = "true" ] ; then + set -x + export MAVEN_ARGS_APPEND="${MAVEN_ARGS_APPEND} -X --batch-mode" + log_info "Script debugging is enabled, allowing bash commands and their arguments to be printed as they are executed" + printenv +fi + +if [ "${ignore_jvm_settings}" != "true" ]; then + source "${script_dir_path}"/configure-jvm-mvn.sh +fi + +"${MAVEN_HOME}"/bin/mvn -B ${MAVEN_ARGS_APPEND} \ + -nsu \ + -s "${MAVEN_SETTINGS_PATH}" \ + -DplatformVersion="${QUARKUS_PLATFORM_VERSION}" \ + -Dextensions="${extensions}" \ + ${QUARKUS_ADD_EXTENSION_ARGS} \ + io.quarkus.platform:quarkus-maven-plugin:"${QUARKUS_PLATFORM_VERSION}":add-extension diff --git a/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/build-app.sh b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/build-app.sh new file mode 100755 index 00000000000..671d6e09b1e --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/build-app.sh @@ -0,0 +1,65 @@ +#!/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. +# + +set -e + +script_dir_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +resources_path="$1" +if [ -n "${resources_path}" ]; then + resources_path="$(realpath "${resources_path}")" +fi + +# shellcheck source=/dev/null +source "${script_dir_path}"/logging.sh + +if [ "${SCRIPT_DEBUG}" = "true" ] ; then + set -x + export MAVEN_ARGS_APPEND="${MAVEN_ARGS_APPEND} -X --batch-mode" + log_info "Script debugging is enabled, allowing bash commands and their arguments to be printed as they are executed" + log_info "Resources path is ${resources_path}" + printenv +fi + +# Copy resources if exists +log_info "-> Copying files from ${resources_path}, if any..." +if [ -n "${resources_path}" ]; then + destination="${KOGITO_HOME}/serverless-workflow-project/src/main/resources/" + log_info "-> Destination folder is ${destination}" + cp -vR ${resources_path}/* ${destination} + find "${resources_path}" -name 'jvm.config' -exec echo "--> found {}" \; -exec mkdir -p ${destination}/.mvn \; -exec cp -v {} ${destination}/.mvn/ \; +else + log_warning "-> Nothing to copy from ${resources_path}" +fi + +source "${script_dir_path}"/configure-jvm-mvn.sh + +if [ ! -z "${QUARKUS_EXTENSIONS}" ]; then + log_info "Adding extensions '${QUARKUS_EXTENSIONS}'" + ${script_dir_path}/add-extension.sh "${QUARKUS_EXTENSIONS}" "true" +fi + +cd ${KOGITO_HOME}/serverless-workflow-project + +"${MAVEN_HOME}"/bin/mvn -B ${MAVEN_ARGS_APPEND} \ + -nsu \ + -s "${MAVEN_SETTINGS_PATH}" \ + -DskipTests \ + -Dquarkus.container-image.build=false \ + clean install diff --git a/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/configure-jvm-mvn.sh b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/configure-jvm-mvn.sh new file mode 100755 index 00000000000..cd8292cc014 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/configure-jvm-mvn.sh @@ -0,0 +1,30 @@ +#!/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. +# + +set -e + +export MAVEN_ARGS_APPEND="${MAVEN_ARGS_APPEND} -Dmaven.compiler.release=${JAVA_VERSION}" + +# Call the configure-maven here +source "${KOGITO_HOME}"/launch/configure-maven.sh +configure + +# auto configure JVM settings +source "${KOGITO_HOME}"/launch/jvm-settings.sh \ No newline at end of file diff --git a/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/create-app.sh b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/create-app.sh new file mode 100755 index 00000000000..9d99b521704 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/create-app.sh @@ -0,0 +1,145 @@ +#!/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. +# + +set -e + +script_dir_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# shellcheck source=/dev/null +source "${script_dir_path}"/logging.sh + +if [ "${SCRIPT_DEBUG}" = "true" ] ; then + set -x + export MAVEN_ARGS_APPEND="${MAVEN_ARGS_APPEND} -X --batch-mode" + log_info "Script debugging is enabled, allowing bash commands and their arguments to be printed as they are executed" + printenv +fi + +source "${script_dir_path}"/configure-jvm-mvn.sh + +"${MAVEN_HOME}"/bin/mvn -B ${MAVEN_ARGS_APPEND} \ + -nsu \ + -s "${MAVEN_SETTINGS_PATH}" \ + io.quarkus.platform:quarkus-maven-plugin:"${QUARKUS_PLATFORM_VERSION}":create ${QUARKUS_CREATE_ARGS} \ + -DprojectGroupId="${PROJECT_GROUP_ID}" \ + -DprojectArtifactId="${PROJECT_ARTIFACT_ID}" \ + -DprojectVersionId="${PROJECT_VERSION}" \ + -DplatformVersion="${QUARKUS_PLATFORM_VERSION}" \ + -Dextensions="${QUARKUS_EXTENSIONS}" + +cd "${PROJECT_ARTIFACT_ID}" + +source "${script_dir_path}"/configure-jvm-mvn.sh + +# Fix as we cannot rely on Quarkus platform +# Should be removed once https://issues.redhat.com/browse/KOGITO-9120 is implemented +if [ ! -z ${KOGITO_VERSION} ]; then + echo "Replacing Kogito Platform BOM with version ${KOGITO_VERSION}" + # [ ]* -> is a regexp pattern to match any number of spaces + pattern_1="[ ]*.*<\/groupId>" + pattern_2="[ ]*quarkus-kogito-bom<\/artifactId>\n" + pattern_3="[ ]*.*<\/version>\n" + complete_pattern="$pattern_1\n$pattern_2$pattern_3" + + replace_1=" org.kie.kogito<\/groupId>\n" + replace_2=" kogito-bom<\/artifactId>\n" + replace_3=" ${KOGITO_VERSION}<\/version>\n" + complete_replace="$replace_1$replace_2$replace_3" + + sed -i.bak -e "/$pattern_1/{ + N;N;N + s/$complete_pattern/$complete_replace/ + }" pom.xml +fi + +# if the image being built is X86_64, remove the arm64 maven dependencies from +# kogito-addons-quarkus-jobs-service-embedded and kogito-addons-quarkus-data-index-inmemory +# using maven exclusions +exclusion_jobs_service="" +pattern_jobs_service="kogito-addons-quarkus-jobs-service-embedded" +base_exclusions="\ + io.zonky.test.postgres\ + embedded-postgres-binaries-linux-amd64-alpine\ + \ + \ + io.zonky.test.postgres\ + embedded-postgres-binaries-darwin-amd64\ + \ + \ + io.zonky.test.postgres\ + embedded-postgres-binaries-darwin-arm64v8\ + \ + \ + io.zonky.test.postgres\ + embedded-postgres-binaries-windows-amd64\ + " + +arch=$(uname -p) +if [ "${arch}" = "x86_64" ]; then + echo "Removing arm64 dependencies from kogito-addons-quarkus-jobs-service-embedded and kogito-addons-quarkus-data-index-inmemory dependencies" + exclusion_jobs_service="${pattern_jobs_service}\ + \ + $base_exclusions\ + \ + io.zonky.test.postgres\ + embedded-postgres-binaries-linux-arm64v8\ + \ + " + +elif [ "${arch}" = "aarch64" ]; then + echo "Removing amd64 dependencies from kogito-addons-quarkus-jobs-service-embedded and kogito-addons-quarkus-data-index-inmemory dependencies" + exclusion_jobs_service="${pattern_jobs_service}\ + \ + $base_exclusions\ + \ + io.zonky.test.postgres\ + embedded-postgres-binaries-linux-amd64\ + \ + " +fi + +# Do the replace if needed +if [ ! -z "${exclusion_jobs_service}" ]; then + sed -i.bak "s|$pattern_jobs_service|$exclusion_jobs_service|" pom.xml +fi + +if [ "${SCRIPT_DEBUG^^}" = "TRUE" ]; then + cat pom.xml +fi + +ls -la "${KOGITO_HOME}"/.m2/repository/org/apache/kie/ +ls -la "${KOGITO_HOME}"/.m2/repository/org/kie/ + +# we force the dependencies download beforehand, so we won't have problems when running or building our apps in offline mode +# see: +# https://quarkus.io/guides/maven-tooling#downloading-maven-artifact-dependencies-for-offline-development-and-testing +# https://maven.apache.org/plugins/maven-dependency-plugin/go-offline-mojo.html +"${MAVEN_HOME}"/bin/mvn -B ${MAVEN_ARGS_APPEND} \ + -nsu \ + -s "${MAVEN_SETTINGS_PATH}" \ + -DskipTests=true \ + -Dmaven.javadoc.skip=true \ + clean dependency:go-offline io.quarkus.platform:quarkus-maven-plugin:"${QUARKUS_PLATFORM_VERSION}":go-offline install + +# clean up +"${MAVEN_HOME}"/bin/mvn -B ${MAVEN_ARGS_APPEND} \ + -nsu \ + -s "${MAVEN_SETTINGS_PATH}" \ + clean diff --git a/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/jvm-settings.sh b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/jvm-settings.sh new file mode 100755 index 00000000000..168e5321617 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/added/jvm-settings.sh @@ -0,0 +1,46 @@ +#!/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. +# + +# Calculate the java memory for the given maven build. +# It is based in the container-limits that can be found in +# https://github.com/jboss-openshift/cct_module/blob/master/jboss/container/java/jvm/bash/artifacts/opt/jboss/container/java/jvm/container-limits +# +# It respects the jvm.config of ${maven.projectBasedir}/.mvn/jvm.config +# Usage: add the following line in the desired script: +# source "${KOGITO_HOME}"/launch/jvm-settings.sh +# If you want to provide the jvm.config, be sure to access the target directory before sourcing this script. + + +set -e + +# shellcheck source=/dev/null +source "${KOGITO_HOME}"/launch/logging.sh + +log_info "--> checking if .mvn/jvm.config exists." +if [ -f ".mvn/jvm.config" ]; then + log_info "---> .mvn/jvm.config exists." + JAVA_OPTIONS=$(cat .mvn/jvm.config) + export JAVA_OPTIONS +else + log_info "---> .mvn/jvm.config does not exists, memory will be calculated based on container limits." +fi + +MAVEN_OPTS="${JAVA_OPTIONS} $("${JBOSS_CONTAINER_JAVA_JVM_MODULE}"/java-default-options) $("${JBOSS_CONTAINER_JAVA_JVM_MODULE}"/debug-options)" +export MAVEN_OPTS \ No newline at end of file diff --git a/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/configure.sh b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/configure.sh new file mode 100644 index 00000000000..8fa4b87981a --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/configure.sh @@ -0,0 +1,31 @@ +#!/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. +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SOURCES_DIR=/tmp/artifacts +ADDED_DIR="${SCRIPT_DIR}"/added +LAUNCH_DIR="${KOGITO_HOME}"/launch + +cp -v "${ADDED_DIR}"/* "${LAUNCH_DIR}" + +chown -R 1001:0 "${KOGITO_HOME}" +chmod -R ug+rwX "${KOGITO_HOME}" diff --git a/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/module.yaml b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/module.yaml new file mode 100644 index 00000000000..7ef3a10b0a8 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-swf/common/scripts/module.yaml @@ -0,0 +1,45 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: org.kie.kogito.swf.common.scripts +version: "0.0.0" +description: "Kogito Serverless Workflow image common scripts" + +envs: + - name: QUARKUS_EXTENSIONS + example: "quarkus-kubernetes,org.apache.kie.sonataflow:sonataflow-quarkus:${KOGITO_VERSION},org.kie:kie-addons-quarkus-knative-eventing:${KOGITO_VERSION}" + description: To add extension to your application + + - name: PROJECT_GROUP_ID + value: "org.acme" + description: Please do not change. To change only if you plan to use the ${KOGITO_HOME}/launch/create-app.sh + - name: PROJECT_ARTIFACT_ID + value: "serverless-workflow-project" + description: Please do not change. To change only if you plan to use the ${KOGITO_HOME}/launch/create-app.sh + - name: PROJECT_VERSION + value: "1.0.0-SNAPSHOT" + description: Please do not change. To change only if you plan to use the ${KOGITO_HOME}/launch/create-app.sh + - name: QUARKUS_CREATE_ARGS + example: -DnoCode + description: To use only if you plan to use the ${KOGITO_HOME}/launch/create-app.sh + - name: QUARKUS_ADD_EXTENSION_ARGS + description: To use only if you plan to use the ${KOGITO_HOME}/launch/add-extension.sh + +execute: + - script: configure.sh diff --git a/packages/kogito-swf-common/resources/modules/kogito-system-user/add-user b/packages/kogito-swf-common/resources/modules/kogito-system-user/add-user new file mode 100644 index 00000000000..cd5c209fc8b --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-system-user/add-user @@ -0,0 +1,24 @@ +#!/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. +# +groupadd -r kogito -g 1001 && useradd -u 1001 -r -g root -G "${USER}" -m -d "${KOGITO_HOME}" -s /sbin/nologin -c "Kogito user" ${USER} + +mkdir "${KOGITO_HOME}"/bin +chmod ug+rwX "${KOGITO_HOME}" + diff --git a/packages/kogito-swf-common/resources/modules/kogito-system-user/module.yaml b/packages/kogito-swf-common/resources/modules/kogito-system-user/module.yaml new file mode 100644 index 00000000000..95e925d7cb8 --- /dev/null +++ b/packages/kogito-swf-common/resources/modules/kogito-system-user/module.yaml @@ -0,0 +1,33 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: org.kie.kogito.system.user +version: "0.0.0" + +execute: + - script: add-user + +envs: + - name: "KOGITO_HOME" + value: "/home/kogito" + # Force override here since some images depends on OpenJDK, which sets home to /home/jboss. Might be worth removing the kogito user and keep jboss instead. TODO: open an issue to track it and link to Kogito Operator deprecation. + - name: "HOME" + value: "/home/kogito" + - name: "USER" + value: "kogito" diff --git a/packages/kogito-swf-common/resources/scripts/README.md b/packages/kogito-swf-common/resources/scripts/README.md new file mode 100644 index 00000000000..f1680e20f9b --- /dev/null +++ b/packages/kogito-swf-common/resources/scripts/README.md @@ -0,0 +1,31 @@ +# kogito-swf-common utility scripts + +This directory contains a set of python scripts used to help to perform some tasks during the build and configuration of the `kogito-swf` images: + +## Common script + +The [common.py](common.py) defines the basic functions that will be used by other scripts + +## Retrieve Versions script + +The [retrieve_versions.py](retrieve_version.py) script is used to read the actual image version from the +`kogito-project-versions` module during the image build process. + +## Versions Manager + +The [versions_manager.py](versions_manager.py) script offers a CLI that helps upgrading versions properties in +the images yaml descriptor or cekit modules. This script is being used during the image build time, but it's also used +to update the images / cekit modules versions when bootstraping the `@kie-tools` repo. + +Usage: + +- Bumping images / cekit modules versions of a package in `@kie-tools` + Args: + + - `--bump-to`: bumps the image and module versions (in the `resources` folder) to the specified version. + - `--source-folder`: specifies the path to the `resources` folder. + +- Upgrading platform dependencies in all images / modules envs and labels during the image build process. + Args: +- `--quarkus-version`: Sets the Quarkus version +- `--kogito-version`: Sets the Kogito version diff --git a/packages/kogito-swf-common/resources/scripts/common.py b/packages/kogito-swf-common/resources/scripts/common.py new file mode 100644 index 00000000000..249aa8b1719 --- /dev/null +++ b/packages/kogito-swf-common/resources/scripts/common.py @@ -0,0 +1,304 @@ +import os +import re +import glob + +from ruamel.yaml import YAML + +MODULE_FILENAME = "module.yaml" +MODULES_DIR = "modules" +PROJECT_VERSIONS_MODULE = "modules/kogito-project-versions/module.yaml" + +KOGITO_VERSION_ENV_KEY = "KOGITO_VERSION" +KOGITO_VERSION_LABEL_NAME = "org.kie.kogito.version" + +QUARKUS_PLATFORM_VERSION_ENV_KEY = "QUARKUS_PLATFORM_VERSION" +QUARKUS_PLATFORM_VERSION_LABEL_NAME = "io.quarkus.platform.version" + +SONATAFLOW_QUARKUS_DEVUI_VERSION_ENV_KEY = "SONATAFLOW_QUARKUS_DEVUI_VERSION" + + +def yaml_loader(): + """ + default yaml Loader + :return: yaml object + """ + yaml = YAML() + yaml.preserve_quotes = True + yaml.width = 1024 + yaml.indent(mapping=2, sequence=4, offset=2) + return yaml + +def retrieve_version(): + """ + Retrieve the project version from project data file + """ + return get_project_versions_module_data()['version'] + +def get_all_images(source_folder = None): + """ + Retrieve all images in current dir + """ + root_folder = "." if source_folder is None else source_folder + return glob.glob("{}/*-image.yaml".format(root_folder)) + +def get_project_versions_module_data(): + """ + Get a specific field value from project versions module file + """ + try: + project_versions_module_file = os.path.join(PROJECT_VERSIONS_MODULE) + with open(project_versions_module_file) as project_versions_data: + return yaml_loader().load(project_versions_data) + + except TypeError: + raise + +def get_all_module_dirs(source_folder = None): + """ + Retrieve the module directories + :param source_folder: folder where resources are stored + """ + + root_folder = "." if source_folder is None else source_folder + modules_dir = "{}/{}".format(root_folder, MODULES_DIR) + + modules = [] + + # r=>root, d=>directories, f=>files + for r, d, f in os.walk(modules_dir): + for item in f: + if MODULE_FILENAME == item: + modules.append(os.path.dirname(os.path.join(r, item))) + print("[kogito-swf-common] Processing modules of '" + os.path.dirname(os.path.join(r, item)) + "'") + + return modules + +def update_image_and_modules_version(target_version, source_folder = None): + """ + Update every Kogito module.yaml to the given version. + :param target_version: version used to update all Kogito module.yaml files + :param source_folder: folder where resources are stored + """ + print("Images and Modules version will be updated to {0}".format(target_version)) + update_images_version(target_version, source_folder) + update_modules_version(target_version, source_folder) + + +def update_modules_version(target_version, source_folder = None): + """ + Update every Kogito module.yaml to the given version. + :param target_version: version used to update all Kogito module.yaml files + :param source_folder: folder where resources are stored + """ + modules = get_all_module_dirs(source_folder) + + for module_dir in modules: + update_module_version(module_dir, target_version) + + +def update_module_version(module_dir, target_version): + """ + Set Kogito module.yaml to given version. + :param module_dir: directory where cekit modules are hold + :param target_version: version to set into the module + """ + try: + module_file = os.path.join(module_dir, MODULE_FILENAME) + with open(module_file) as module: + data = yaml_loader().load(module) + print("Updating module {0} version from {1} to {2}".format(data['name'], data['version'], target_version)) + data['version'] = target_version + + with open(module_file, 'w') as module: + yaml_loader().dump(data, module) + + except TypeError: + raise + +def update_images_version(target_version, source_folder = None): + """ + Update image.yml files version tag. + :param target_version: version used to update + :param source_folder: folder where resources are stored + """ + for image_filename in get_all_images(source_folder): + update_image_version_tag_in_yaml_file(target_version, image_filename) + + +def update_image_version_tag_in_yaml_file(target_version, yaml_file): + """ + Update root version tag in yaml file. + :param target_version: version to set + :param yaml_file: yaml file to update + """ + print("Updating Image main file version from file {0} to version {1}".format(yaml_file, target_version)) + try: + with open(yaml_file) as image: + data = yaml_loader().load(image) + update_field_in_dict(data, 'version', target_version) + + with open(yaml_file, 'w') as image: + yaml_loader().dump(data, image) + except TypeError as err: + print("Unexpected error:", err) + +def update_kogito_platform_version(kogito_platform_version): + """ + Update kogito_platform_version version into images/modules + :param kogito_platform_version: kogito version to set + """ + print("Setting Kogito Platform version: " + kogito_platform_version) + update_env_value(KOGITO_VERSION_ENV_KEY, kogito_platform_version) + update_label_value(KOGITO_VERSION_LABEL_NAME, kogito_platform_version) + +def update_quarkus_platform_version(quarkus_platform_version): + """ + Update quarkus_platform_version version into images/modules + :param quarkus_platform_version: quarkus version to set + """ + print("Setting Quarkus version: " + quarkus_platform_version) + update_env_value(QUARKUS_PLATFORM_VERSION_ENV_KEY, quarkus_platform_version) + update_label_value(QUARKUS_PLATFORM_VERSION_LABEL_NAME, quarkus_platform_version) + +def update_sonataflow_quarkus_devui_version(sonataflow_quarkus_devui_version): + """ + Update sonataflow_quarkus_devui_version version into images/modules + :param sonataflow_quarkus_devui_version: sonataflow quarkus devui version to set + """ + print("Setting SonataFlow Quarkus DevUI version: " + sonataflow_quarkus_devui_version) + update_env_value(SONATAFLOW_QUARKUS_DEVUI_VERSION_ENV_KEY, sonataflow_quarkus_devui_version) + +def update_env_value(env_name, env_value): + """ + Update environment value into the given yaml module/image file + :param env_name: environment variable name to update + :param env_value: value to set + """ + + images = get_all_images() + modules = get_all_module_dirs() + + for image_filename in images: + update_env_value_in_file(image_filename, env_name, env_value) + + for module_dir in modules: + module_file = os.path.join(module_dir, "module.yaml") + update_env_value_in_file(module_file, env_name, env_value) + +def update_env_value_in_file(filename, env_name, env_value): + """ + Update environment value into the given yaml module/image file + :param filename: filename to update + :param env_name: environment variable name to update + :param env_value: value to set + """ + print("Updating {0} label {1} with value {2}".format(filename, env_name, env_value)) + try: + with open(filename) as yaml_file: + data = yaml_loader().load(yaml_file) + update_env_value_in_data(data, env_name, env_value) + + with open(filename, 'w') as yaml_file: + yaml_loader().dump(data, yaml_file) + + except TypeError: + raise + + +def update_env_value_in_data(data, env_name, env_value, ignore_empty = False): + """ + Update environment variable value in data dict if exists + :param data: dict to update + :param env_name: environment variable name + :param env_value: environment variable value to set + :param ignore_empty: Whether previous value should be present to set the new value + """ + if isinstance(data, list): + for data_item in data: + update_env_value_in_data(data_item, env_name, env_value, ignore_empty) + else: + if ignore_empty: + if 'envs' not in data: + data['envs'] = [] + data['envs'] += [ dict(name=env_name, value=env_value) ] + elif 'envs' in data: + for _, env in enumerate(data['envs'], start=0): + if env['name'] == env_name: + update_field_in_dict(env, 'value', env_value, ignore_empty) + +def update_field_in_dict(data, key, new_value, ignore_empty = False): + """ + Update version field in given data dict + :param data: dictionary to update + :param key: key to lookup + :param new_value: value to set + :param ignore_empty: Whether previous value should be present to set the new value + """ + if isinstance(data, list): + for data_item in data: + update_field_in_dict(data_item, key, new_value, ignore_empty) + else: + if ignore_empty or key in data: + data[key] = new_value + else: + print("Field " + key + " not found, returning...") + +def update_label_value(label_name, label_value): + """ + Update label value in all modules and images + :param label_name: label name to update + :param label_value: value to set + """ + + images = get_all_images() + modules = get_all_module_dirs() + + for image_filename in images: + print("updating image: " + image_filename) + update_label_value_in_file(image_filename, label_name, label_value) + + for module_dir in modules: + module_file = os.path.join(module_dir, "module.yaml") + update_label_value_in_file(module_file, label_name, label_name) + +def update_label_value_in_file(filename, label_name, label_value): + """ + Update label value into the given yaml module/image file + :param filename: filename to update + :param label_name: label name to update + :param label_value: value to set + """ + print("Updating {0} label {1} with value {2}".format(filename, label_name, label_value)) + try: + with open(filename) as yaml_file: + data = yaml_loader().load(yaml_file) + update_label_value_in_data(data, label_name, label_value) + + with open(filename, 'w') as yaml_file: + yaml_loader().dump(data, yaml_file) + + except TypeError: + raise + + +def update_label_value_in_data(data, label_name, label_value, ignore_empty = False): + """ + Update label value in data dict if exists + :param data: dict to update + :param label_name: label name + :param label_value: label value to set + :param ignore_empty: Whether previous value should be present to set the new value + """ + if isinstance(data, list): + for data_item in data: + update_label_value_in_data(data_item, label_name, label_value, ignore_empty) + else: + if ignore_empty: + if 'labels' not in data: + data['labels'] = [] + data['labels'] += [ dict(name=label_name, value=label_value) ] + elif 'labels' in data: + for _, label in enumerate(data['labels'], start=0): + if label['name'] == label_name: + update_field_in_dict(label, 'value', label_value, ignore_empty) + diff --git a/packages/kogito-swf-common/resources/scripts/retrieve_version.py b/packages/kogito-swf-common/resources/scripts/retrieve_version.py new file mode 100644 index 00000000000..8140e56001c --- /dev/null +++ b/packages/kogito-swf-common/resources/scripts/retrieve_version.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +#Script responsible to update the tests with +#Should be run from root directory of the repository +#Sample usage: python3 scripts/retrieve_version.py + +import sys +sys.dont_write_bytecode = True + +import common + +if __name__ == "__main__": + print(common.retrieve_version()) diff --git a/packages/kogito-swf-common/resources/scripts/run-bats.sh b/packages/kogito-swf-common/resources/scripts/run-bats.sh new file mode 100755 index 00000000000..3da0bf00ce8 --- /dev/null +++ b/packages/kogito-swf-common/resources/scripts/run-bats.sh @@ -0,0 +1,33 @@ +#!/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. +# + + +set -e + +if [[ $(command -v ./bats/bin/bats) ]]; then #skip if bats already installed else will install the bats + echo "---> bats already available running tests" +else + git clone https://github.com/bats-core/bats-core.git + ./bats-core/install.sh bats + rm -rf bats-core +fi + +echo "----> running bats" +./bats/bin/bats modules/kogito-swf/common/scripts/tests/bats diff --git a/packages/kogito-swf-common/resources/scripts/versions_manager.py b/packages/kogito-swf-common/resources/scripts/versions_manager.py new file mode 100644 index 00000000000..d71f18a8917 --- /dev/null +++ b/packages/kogito-swf-common/resources/scripts/versions_manager.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +#Script responsible to update the tests with +#Should be run from root directory of the repository +#Sample usage: python3 scripts/retrieve_version.py + +import sys +import argparse +import common +import re + +sys.dont_write_bytecode = True + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Kie Tools - SWF Image Version Manager') + parser.add_argument('--bump-to', dest='bump_to', help='Bump all images and yamls to the next version') + parser.add_argument('--source-folder', dest='source_folder') + parser.add_argument('--quarkus-version', dest='quarkus_version', help='Sets the image Quarkus Version') + parser.add_argument('--kogito-version', dest='kogito_version', help='Sets the image Kogito Version') + parser.add_argument('--sonataflow-quarkus-devui-version', dest='sonataflow_quarkus_devui_version', help='Sets the image SonataFlow Quarkus DevUI Version', required=False) + + args = parser.parse_args() + + if args.bump_to is None and args.kogito_version is None and args.quarkus_version is None: + print(parser.print_usage()) + else: + if args.bump_to is not None: + common.update_image_and_modules_version(args.bump_to, args.source_folder) + if args.kogito_version is not None: + common.update_kogito_platform_version(args.kogito_version) + if args.quarkus_version is not None: + common.update_quarkus_platform_version(args.quarkus_version) + if args.sonataflow_quarkus_devui_version is not None: + common.update_sonataflow_quarkus_devui_version(args.sonataflow_quarkus_devui_version) \ No newline at end of file diff --git a/packages/kogito-swf-common/resources/tests/shell/README.md b/packages/kogito-swf-common/resources/tests/shell/README.md new file mode 100644 index 00000000000..a8e497bb5e3 --- /dev/null +++ b/packages/kogito-swf-common/resources/tests/shell/README.md @@ -0,0 +1,19 @@ +# Tests in Shell + +## Running Tests With JBang + +- Install JBang +- Install VSCode Red Hat's Java plugin +- Install VSCode JBang plugin + +The `run.sh` should be used to run the tests since it must set a few env vars. To run from your terminal, try: + +```shell +tests/shell/run.sh kogito-swf-devmode quay.io/kiegroup/kogito-swf-devmode:999-SNAPSHOT +``` + +The first argument is the test case to run and the second, the image. + +Under the hood, it uses [Junit's Console Launcher](https://junit.org/junit5/docs/current/user-guide/#running-tests-console-launcher) tool to run the tests from the command line. + +Update this file with new findings, and don't remove the `.vscode` folder. It's useful to run JBang from the IDE. diff --git a/packages/kogito-swf-common/resources/tests/shell/run.sh b/packages/kogito-swf-common/resources/tests/shell/run.sh new file mode 100755 index 00000000000..8903f84a49f --- /dev/null +++ b/packages/kogito-swf-common/resources/tests/shell/run.sh @@ -0,0 +1,51 @@ +#!/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. +# + +set -e + +script_dir_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +image_name=$1 +image_tag=$2 + +if [ -z "${image_name}" ]; then + echo "Please provide the image id to test" + exit 1 +fi + +if [ -z "${image_tag}" ]; then + echo "Please provide the container image full tag (ie 'registry/namespace/image:version')" + exit 1 +fi + +export TEST_IMAGE="${image_tag}" +export OUTPUT_DIR="${script_dir_path}/../../target/shell/${image_name}" +export TESTS_SCRIPT_DIR_PATH="${script_dir_path}/${image_name}" + +echo "image_name=${image_name}" +echo "TEST_IMAGE=${TEST_IMAGE}" +echo "OUTPUT_DIR=${OUTPUT_DIR}" +echo "TESTS_SCRIPT_DIR_PATH=${TESTS_SCRIPT_DIR_PATH}" + +if [ -d "${script_dir_path}/${image_name}" ]; then + curl -Ls https://sh.jbang.dev | bash -s - "${TESTS_SCRIPT_DIR_PATH}/src/RunTests.java" +else + echo "No shell test to run for image ${image_name}" +fi \ No newline at end of file diff --git a/packages/kogito-swf-common/test-resources/modules/kogito-swf/common/scripts/tests/bats/kogito-swf-builder-jvm-settings.bats b/packages/kogito-swf-common/test-resources/modules/kogito-swf/common/scripts/tests/bats/kogito-swf-builder-jvm-settings.bats new file mode 100644 index 00000000000..a0487e8d477 --- /dev/null +++ b/packages/kogito-swf-common/test-resources/modules/kogito-swf/common/scripts/tests/bats/kogito-swf-builder-jvm-settings.bats @@ -0,0 +1,57 @@ +#!/usr/bin/env bats +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + + +export KOGITO_HOME=/tmp/kogito +export HOME="${KOGITO_HOME}" +export JBOSS_CONTAINER_JAVA_JVM_MODULE=/tmp/container/java/jvm +mkdir -p "${KOGITO_HOME}"/launch +mkdir -p "${JBOSS_CONTAINER_JAVA_JVM_MODULE}" +cp $BATS_TEST_DIRNAME/../../../../../kogito-logging/added/logging.sh "${KOGITO_HOME}"/launch/ +cp -r $BATS_TEST_DIRNAME/../../../../../kogito-dynamic-resources/added/* "${JBOSS_CONTAINER_JAVA_JVM_MODULE}"/ +chmod -R +x "${JBOSS_CONTAINER_JAVA_JVM_MODULE}" +cp $BATS_TEST_DIRNAME/../../added/jvm-settings.sh "${KOGITO_HOME}"/launch/ + +teardown() { + rm -rf "${KOGITO_HOME}" + rm -rf "${JBOSS_CONTAINER_JAVA_JVM_MODULE}" +} + +@test "run jvm-settings with no custom conf" { + expected_status_code=0 + mkdir -p $KOGITO_HOME/my-app + + source ${KOGITO_HOME}/launch/jvm-settings.sh + + echo "MAVEN_OPTS is: ${MAVEN_OPTS}" + [[ "${MAVEN_OPTS}" == *"-XX:+UseParallelGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+ExitOnOutOfMemoryError"* ]] +} + +@test "run jvm-settings with custom conf" { + expected_status_code=0 + mkdir -p $KOGITO_HOME/my-app/.mvn + cd $KOGITO_HOME/my-app + echo "-Xmx1024m -Xms512m -Xotherthing" > $KOGITO_HOME/my-app/.mvn/jvm.config + + source ${KOGITO_HOME}/launch/jvm-settings.sh + + echo "MAVEN_OPTS is: ${MAVEN_OPTS}" + [[ "${MAVEN_OPTS}" == *"-Xmx1024m -Xms512m -Xotherthing -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+ExitOnOutOfMemoryError"* ]] +} diff --git a/packages/kogito-swf-devmode/README.md b/packages/kogito-swf-devmode/README.md new file mode 100644 index 00000000000..e29df97bfb1 --- /dev/null +++ b/packages/kogito-swf-devmode/README.md @@ -0,0 +1,67 @@ +# kogito-swf-devmode + +This package contains the `cekit` image descriptor (`kogito-swf-devmode-image.yaml`) and modules needed to build the `kogito-swf-devmode` +image along with the modules and scripts provided in `@kie-tools/kogito-swf-common`. + +## Additional requirements + +- **python3** with the following packages installed: + - `behave` `lxml` `docker` `docker-squash` `elementPath` `pyyaml` `ruamel.yaml` `python-dateutil` `Jinja2` `pykwalify` `colorlog` `click` +- **cekit 4.11.0**: [docs.cekit.io](https://docs.cekit.io/en/latest/index.html) +- **s2i**: [source-to-image](https://github.com/openshift/source-to-image) +- **make** +- **docker** or **podman** + +## Build + +- Enable the image to be built: + + ```bash + export KIE_TOOLS_BUILD__buildContainerImages=true + ``` + +- (Optional) The image name and tags can be customized by setting the following environment variables: + + ```bash + export KOGITO_SWF_DEVMODE_IMAGE__registry= + export KOGITO_SWF_DEVMODE_IMAGE__account= + export KOGITO_SWF_DEVMODE_IMAGE__name= + export KOGITO_SWF_DEVMODE_IMAGE__buildTag= + ``` + + > Default values can be found [here](./env/index.js). + +- After optionally setting up the environment variables, run the following in the root folder of the repository to build the package: + + ```bash + pnpm -F @kie-tools/kogito-swf-devmode build:prod + ``` + +- Then check if the image is correctly stored: + + ```bash + docker images + ``` + + or + + ```bash + podman images + ``` + +## Testing the generated image (only for Linux) + +- With the image generated, run: + + ```bash + pnpm -F @kie-tools/kogito-swf-devmode image:test + ``` + +## Envs + +| Name | Description | Default | +| :----------------------------------: | :------------------------------------------------: | :------------------: | +| `KOGITO_SWF_DEVMODE_IMAGE__registry` | Registry where the generated image will be pushed. | "quay.io" | +| `KOGITO_SWF_DEVMODE_IMAGE__account` | Account where image will be stored. | "kiegroup" | +| `KOGITO_SWF_DEVMODE_IMAGE__name` | SWF DevMode Image name. | "kogito-swf-devmode" | +| `KOGITO_SWF_DEVMODE_IMAGE__buildTag` | Tag to use . | "latest" | diff --git a/packages/kogito-swf-devmode/env/index.js b/packages/kogito-swf-devmode/env/index.js new file mode 100644 index 00000000000..a341b893d45 --- /dev/null +++ b/packages/kogito-swf-devmode/env/index.js @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 sonataFlowQuarkusDevUiEnv = require("@kie-tools/sonataflow-quarkus-devui/env"); + +module.exports = composeEnv([require("@kie-tools/root-env/env")], { + vars: varsWithName({ + KOGITO_SWF_DEVMODE_IMAGE__registry: { + default: "quay.io", + description: "The image registry.", + }, + KOGITO_SWF_DEVMODE_IMAGE__account: { + default: "kiegroup", + description: "The image registry account.", + }, + KOGITO_SWF_DEVMODE_IMAGE__name: { + default: "kogito-swf-devmode-nightly", + description: "The image name.", + }, + KOGITO_SWF_DEVMODE_IMAGE__buildTag: { + default: "latest", + description: "The image tag.", + }, + KOGITO_SWF_DEVMODE_IMAGE__sonataflowQuarkusDevUiVersion: { + default: sonataFlowQuarkusDevUiEnv.env.sonataflowQuarkusDevuiExtension.version, + description: "SonataFlow Quarkus Dev UI version", + }, + }), + get env() { + return { + kogitoSwfDevMode: { + registry: getOrDefault(this.vars.KOGITO_SWF_DEVMODE_IMAGE__registry), + account: getOrDefault(this.vars.KOGITO_SWF_DEVMODE_IMAGE__account), + name: getOrDefault(this.vars.KOGITO_SWF_DEVMODE_IMAGE__name), + tag: getOrDefault(this.vars.KOGITO_SWF_DEVMODE_IMAGE__buildTag), + version: require("../package.json").version, + sonataflowQuarkusDevUiVersion: getOrDefault(this.vars.KOGITO_SWF_DEVMODE_IMAGE__sonataflowQuarkusDevUiVersion), + }, + }; + }, +}); diff --git a/packages/kogito-swf-devmode/install.js b/packages/kogito-swf-devmode/install.js new file mode 100644 index 00000000000..9a4eff75c62 --- /dev/null +++ b/packages/kogito-swf-devmode/install.js @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 { execSync } = require("child_process"); +const fs = require("fs"); + +const buildEnv = require("./env"); +const path = require("path"); +const pythonVenvDir = path.dirname(require.resolve("@kie-tools/python-venv/package.json")); +const kogitoSwfCommonDir = path.dirname(require.resolve("@kie-tools/kogito-swf-common/package.json")); + +const activateCmd = + process.platform === "win32" + ? `${pythonVenvDir}\\venv\\Scripts\\Activate.bat` + : `. ${pythonVenvDir}/venv/bin/activate`; + +execSync( + `${activateCmd} && \ + python3 ${kogitoSwfCommonDir}/resources/scripts/versions_manager.py --bump-to ${buildEnv.env.kogitoSwfDevMode.version} --source-folder ./resources`, + { stdio: "inherit" } +); + +// Find and read the -image.yaml file +const resourcesPath = path.resolve(__dirname, "./resources"); +const files = fs.readdirSync(resourcesPath); +const imageYamlFiles = files.filter((fileName) => fileName.endsWith("-image.yaml")); +if (imageYamlFiles.length !== 1) { + throw new Error("There should only be one -image.yaml file on ./resources!"); +} +const originalYamlPath = path.join(resourcesPath, imageYamlFiles[0]); +let imageYaml = fs.readFileSync(originalYamlPath, "utf8"); + +// Replace the whole string between quotes ("") with the image name +imageYaml = imageYaml.replace( + /(?<=")(.*kogito-swf-devmode.*)(?=")/gm, + `${buildEnv.env.kogitoSwfDevMode.registry}/${buildEnv.env.kogitoSwfDevMode.account}/${buildEnv.env.kogitoSwfDevMode.name}` +); + +// Write file and then rename it to match the image name +fs.writeFileSync(originalYamlPath, imageYaml); +fs.renameSync(originalYamlPath, path.join(resourcesPath, `${buildEnv.env.kogitoSwfDevMode.name}-image.yaml`)); diff --git a/packages/kogito-swf-devmode/package.json b/packages/kogito-swf-devmode/package.json new file mode 100644 index 00000000000..a7131d80edb --- /dev/null +++ b/packages/kogito-swf-devmode/package.json @@ -0,0 +1,49 @@ +{ + "private": true, + "name": "@kie-tools/kogito-swf-devmode", + "version": "0.0.0", + "description": "", + "license": "Apache-2.0", + "homepage": "https://github.com/apache/incubator-kie-tools", + "repository": { + "type": "git", + "url": "https://github.com/apache/incubator-kie-tools.git" + }, + "bugs": { + "url": "https://github.com/apache/incubator-kie-tools/issues" + }, + "scripts": { + "build:dev": "run-script-if --bool \"$(build-env containerImages.build)\" --then \"pnpm copy-assets\" \"pnpm image:build\"", + "build:prod": "pnpm build:dev && pnpm image:test", + "copy-assets": "run-script-os", + "copy-assets:linux:darwin": "rimraf build && cp -R ./node_modules/@kie-tools/kogito-swf-common/resources build && cp -R resources/* build && pnpm copy-devui-repo", + "copy-devui-repo": "tar -C ~/.m2/repository/org/apache/kie/ -cvf build/modules/kogito-swf/devmode/build-config/sonataflow-quarkus-devui-maven-repo.tar sonataflow && tar -C ~/.m2/repository/org/kie/ -cvf build/modules/kogito-swf/devmode/build-config/kie-tools-maven-base-maven-repo.tar kie-tools-maven-base", + "copy-test-assets": "run-script-os", + "copy-test-assets:linux:darwin": "cp -R ./node_modules/@kie-tools/kogito-swf-common/test-resources/* build && cp -R test-resources/* build", + "format": "prettier --write .", + "image:build": "run-script-os", + "image:build:darwin:win32": "echo \"Build skipped on macOS and Windows\"", + "image:build:linux": "pnpm setup:env make -C ./build build", + "image:test": "run-script-if --ignore-errors \"$(build-env tests.ignoreFailures)\" --bool \"$(build-env tests.run)\" --then \"run-script-os\"", + "image:test:darwin:win32": "echo \"Tests skipped on macOS and Windows\"", + "image:test:linux": "pnpm copy-test-assets && pnpm setup:env make -C ./build test-image", + "install": "node install.js && pnpm format", + "setup:env": ". ./node_modules/@kie-tools/python-venv/venv/bin/activate && cross-env SWF_IMAGE_REGISTRY=$(build-env kogitoSwfDevMode.registry) SWF_IMAGE_REGISTRY_ACCOUNT=$(build-env kogitoSwfDevMode.account) SWF_IMAGE_NAME=$(build-env kogitoSwfDevMode.name) SWF_IMAGE_TAG=$(build-env kogitoSwfDevMode.tag) QUARKUS_PLATFORM_VERSION=$(build-env quarkusPlatform.version) KOGITO_VERSION=$(build-env kogitoRuntime.version) SONATAFLOW_QUARKUS_DEVUI_VERSION=$(build-env kogitoSwfDevMode.sonataflowQuarkusDevUiVersion)" + }, + "devDependencies": { + "@kie-tools/kogito-swf-common": "workspace:*", + "@kie-tools/python-venv": "workspace:*", + "@kie-tools/root-env": "workspace:*", + "@kie-tools/sonataflow-quarkus-devui": "workspace:*", + "cross-env": "^7.0.3", + "rimraf": "^3.0.2", + "run-script-os": "^1.1.6" + }, + "kieTools": { + "requiredPreinstalledCliCommands": [ + "python3", + "make", + "s2i" + ] + } +} \ No newline at end of file diff --git a/packages/kogito-swf-devmode/resources/kogito-swf-devmode-nightly-image.yaml b/packages/kogito-swf-devmode/resources/kogito-swf-devmode-nightly-image.yaml new file mode 100644 index 00000000000..dbb3e4f32d1 --- /dev/null +++ b/packages/kogito-swf-devmode/resources/kogito-swf-devmode-nightly-image.yaml @@ -0,0 +1,85 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: builder + from: "registry.access.redhat.com/ubi8/openjdk-17:1.19" + version: "0.0.0" + modules: + repositories: + - path: modules + install: + - name: org.kie.kogito.system.user + - name: org.kie.kogito.logging + - name: org.kie.kogito.launch.scripts + - name: org.kie.kogito.dynamic.resources + - name: org.kie.kogito.maven.common + - name: org.kie.kogito.project.versions + - name: org.kie.kogito.swf.common.scripts + - name: org.kie.kogito.swf.devmode.build-config + - name: org.kie.kogito.swf.common.build + + packages: + manager: microdnf + +- name: "quay.io/kiegroup/kogito-swf-devmode-nightly" + from: "registry.access.redhat.com/ubi8/openjdk-17:1.19" + version: "0.0.0" + description: "Kogito Serverless Workflow development mode with Quarkus extensions libraries preinstalled" + + labels: + - name: "io.quarkus.platform.version" + value: "### SET ME DURING BUILD PROCESS ###" + - name: "org.kie.kogito.version" + value: "### SET ME DURING BUILD PROCESS ###" + - name: "maintainer" + value: "Apache KIE " + - name: "io.k8s.description" + value: "Kogito Serverless Workflow base builder with Quarkus extensions libraries preinstalled." + - name: "io.k8s.display-name" + value: "Kogito SWF Builder" + - name: "io.openshift.tags" + value: "kogito,development,serverless,workflow" + - name: "io.openshift.expose-services" + value: "8080:http,5005:http" + + packages: + manager: microdnf + + modules: + repositories: + - path: modules + install: + - name: org.kie.kogito.system.user + - name: org.kie.kogito.logging + - name: org.kie.kogito.launch.scripts + - name: org.kie.kogito.dynamic.resources + - name: org.kie.kogito.maven.common + - name: org.kie.kogito.project.versions + - name: org.kie.kogito.swf.common.scripts + - name: org.kie.kogito.swf.devmode.runtime.common + - name: org.kie.kogito.swf.devmode.runtime.community + + ports: + - value: 8080 + - value: 5005 + + run: + workdir: "/home/kogito/${PROJECT_ARTIFACT_ID}" + user: 1001 + cmd: + - "/home/kogito/launch/run-app-devmode.sh" diff --git a/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/build-config/configure b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/build-config/configure new file mode 100644 index 00000000000..8c27f782926 --- /dev/null +++ b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/build-config/configure @@ -0,0 +1,38 @@ +#!/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 + +# mvn install:install-file \ +# -Dfile=/tmp/artifacts/sonataflow-quarkus-devui.jar \ +# -DgroupId=org.apache.kie.sonataflow \ +# -DartifactId=sonataflow-quarkus-devui \ +# -Dversion=$SONATAFLOW_QUARKUS_DEVUI_VERSION \ +# -Dpackaging=jar \ +# -DgeneratePom=true + +ls -la /tmp/artifacts + +mkdir -p "${KOGITO_HOME}"/.m2/repository/org/apache/kie/ +mkdir -p "${KOGITO_HOME}"/.m2/repository/org/kie/ +tar xf /tmp/artifacts/sonataflow-quarkus-devui-maven-repo.tar -C "${KOGITO_HOME}"/.m2/repository/org/apache/kie/ +tar xf /tmp/artifacts/kie-tools-maven-base-maven-repo.tar -C "${KOGITO_HOME}"/.m2/repository/org/kie/ + +find "${KOGITO_HOME}"/.m2/repository -name _remote.repositories | xargs rm + diff --git a/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/build-config/module.yaml b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/build-config/module.yaml new file mode 100644 index 00000000000..18670f32409 --- /dev/null +++ b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/build-config/module.yaml @@ -0,0 +1,39 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: org.kie.kogito.swf.devmode.build-config +version: "0.0.0" +description: "Kogito Serverless Workflow devmode image build configuration" + +envs: + - name: "SCRIPT_DEBUG" + value: "false" + - name: QUARKUS_EXTENSIONS + # NOTE: If you change the QUARKUS_EXTENSIONS value remember to update the scripts/logic/build-quarkus-app.sh too! + # Follow up issue to remove KOGITO_VERSION: https://issues.redhat.com/browse/KOGITO-9270 + value: org.apache.kie.sonataflow:sonataflow-quarkus:${KOGITO_VERSION},org.kie:kie-addons-quarkus-knative-eventing:${KOGITO_VERSION},smallrye-health,org.apache.kie.sonataflow:sonataflow-quarkus-devui:${SONATAFLOW_QUARKUS_DEVUI_VERSION},org.kie:kie-addons-quarkus-source-files:${KOGITO_VERSION},org.kie:kie-addons-quarkus-process-management:${KOGITO_VERSION},org.kie:kogito-addons-quarkus-jobs-service-embedded:${KOGITO_VERSION},org.kie:kogito-addons-quarkus-data-index-inmemory:${KOGITO_VERSION},org.kie:kogito-addons-quarkus-microprofile-config-service-catalog:${KOGITO_VERSION},org.kie:kie-addons-quarkus-kubernetes:${KOGITO_VERSION},org.kie:kogito-addons-quarkus-knative-serving:${KOGITO_VERSION} + +artifacts: + - name: sonataflow-quarkus-devui-maven-repo.tar + path: ./sonataflow-quarkus-devui-maven-repo.tar + - name: kie-tools-maven-base-maven-repo.tar + path: ./kie-tools-maven-base-maven-repo.tar + +execute: + - script: configure diff --git a/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/common/added/run-app-devmode.sh b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/common/added/run-app-devmode.sh new file mode 100755 index 00000000000..6f5ec36109e --- /dev/null +++ b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/common/added/run-app-devmode.sh @@ -0,0 +1,53 @@ +#!/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. +# + +set -e + +script_dir_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# shellcheck source=/dev/null +source "${script_dir_path}"/logging.sh + +if [ "${SCRIPT_DEBUG}" = "true" ] ; then + set -x + export MAVEN_ARGS_APPEND="${MAVEN_ARGS_APPEND} -X --batch-mode" + log_info "Script debugging is enabled, allowing bash commands and their arguments to be printed as they are executed" + printenv +fi + +# copy .mvn/jvm-config from resources to project's base dir. +find . -maxdepth 5 -name 'jvm.config' -exec echo "--> found {}" \; -exec mkdir -p .mvn \; -exec cp -v {} .mvn/ \; +source "${script_dir_path}"/configure-jvm-mvn.sh + +# `-o` means offline mode +offline_param="-o" +if [ ! -z "${QUARKUS_EXTENSIONS}" ]; then + ${KOGITO_HOME}/launch/add-extension.sh "${QUARKUS_EXTENSIONS}" "true" + offline_param="" +fi + +"${MAVEN_HOME}"/bin/mvn -B ${MAVEN_ARGS_APPEND} \ + ${offline_param} \ + -s "${MAVEN_SETTINGS_PATH}" \ + -DskipTests \ + -Dquarkus.http.host=0.0.0.0 \ + -Dquarkus.test.continuous-testing=${QUARKUS_CONTINUOUS_TESTING:-disabled} \ + -Dquarkus.analytics.disabled=${QUARKUS_ANALYTICS_DISABLED:true} \ + clean compile quarkus:dev \ No newline at end of file diff --git a/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/common/configure.sh b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/common/configure.sh new file mode 100644 index 00000000000..582997ada49 --- /dev/null +++ b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/common/configure.sh @@ -0,0 +1,30 @@ +#!/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. +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ADDED_DIR="${SCRIPT_DIR}"/added +LAUNCH_DIR="${KOGITO_HOME}"/launch + +cp -v "${ADDED_DIR}"/* "${LAUNCH_DIR}" + +chown -R 1001:0 "${KOGITO_HOME}" +chmod -R ug+rwX "${KOGITO_HOME}" diff --git a/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/common/module.yaml b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/common/module.yaml new file mode 100644 index 00000000000..c74e51f4a1b --- /dev/null +++ b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/common/module.yaml @@ -0,0 +1,25 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: org.kie.kogito.swf.devmode.runtime.common +version: "0.0.0" +description: "Kogito Serverless Workflow devmode common module" + +execute: + - script: configure.sh diff --git a/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/community/configure.sh b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/community/configure.sh new file mode 100644 index 00000000000..7404a5c1e5f --- /dev/null +++ b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/community/configure.sh @@ -0,0 +1,34 @@ +#!/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. +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SOURCES_DIR=/tmp/artifacts + +mkdir -p "${KOGITO_HOME}/${PROJECT_ARTIFACT_ID}" +mkdir -p "${KOGITO_HOME}"/.m2/repository + +# Unzip Quarkus app and Maven repository +tar xf "${SOURCES_DIR}"/kogito-swf-quarkus-app.tar -C "${KOGITO_HOME}/${PROJECT_ARTIFACT_ID}" +tar xf "${SOURCES_DIR}"/kogito-swf-maven-repo.tar -C "${KOGITO_HOME}"/.m2/repository + +chown -R 1001:0 "${KOGITO_HOME}" +chmod -R ug+rwX "${KOGITO_HOME}" diff --git a/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/community/module.yaml b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/community/module.yaml new file mode 100644 index 00000000000..e13ecc5e9c5 --- /dev/null +++ b/packages/kogito-swf-devmode/resources/modules/kogito-swf/devmode/runtime/community/module.yaml @@ -0,0 +1,51 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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: org.kie.kogito.swf.devmode.runtime.community +version: "0.0.0" +description: "Kogito Serverless Workflow devmode with required extensions" + +envs: + - name: QUARKUS_KOGITO_DEVSERVICES_ENABLED + description: Whether to enable Kogito Devservices or not. Default to "false" since Data Index needs Docker. + value: "false" + - name: QUARKUS_DEVSERVICES_ENABLED + description: Whether to enable Quarkus Devservices or not. Default to "false" since the Kafka broker needs Docker. + value: "false" + - name: QUARKUS_KUBERNETES_CLIENT_DEVSERVICES_ENABLED + description: Whether to enable Kogito Devservices or not. Default to "false" since Kubernetes objects are managed by the Kogito Serverless Operator. + value: "false" + - name: QUARKUS_CONTINUOUS_TESTING + description: Whether to enable Quarkus continous testing on DevMode or not. Default to "disabled". + value: "disabled" + - name: QUARKUS_ANALYTICS_DISABLED + description: Whether to disable the Quarkus analytics data collecting on DevMode or not. Default to "true". + value: "true" + - name: KOGITO_CODEGEN_PROCESS_FAILONERROR + description: Boolean flag that will prevent Dev Mode to crash if the provided workflow is wrong. + value: "false" + +artifacts: + - image: builder + path: /home/kogito/build_output/kogito-swf-quarkus-app.tar + - image: builder + path: /home/kogito/build_output/kogito-swf-maven-repo.tar + +execute: + - script: configure.sh diff --git a/packages/kogito-swf-devmode/test-resources/tests/features/kogito-swf-devmode-2.feature b/packages/kogito-swf-devmode/test-resources/tests/features/kogito-swf-devmode-2.feature new file mode 100644 index 00000000000..4dae1df1cc1 --- /dev/null +++ b/packages/kogito-swf-devmode/test-resources/tests/features/kogito-swf-devmode-2.feature @@ -0,0 +1,14 @@ +@quay.io/kiegroup/kogito-swf-devmode +Feature: Serverless Workflow images common + + Scenario: Verify if the swf and quarkus files are under /home/kogito/.m2/repository + When container is started with command bash + Then file /home/kogito/.m2/repository/io/quarkus/platform/quarkus-bom should exist and be a directory + And file /home/kogito/.m2/repository/org/apache/kie/sonataflow/sonataflow-quarkus/ should exist and be a directory + + # This check should be enabled again once a similar check is done on runtimes + # to make sure we only have one version of quarkus bom ... + # See https://issues.redhat.com/browse/KOGITO-8555 to enable again + # Scenario: verify if there is no dependencies with multiple versions in /home/kogito/.m2/repository + # When container is started with command bash + # Then run sh -c 'ls /home/kogito/.m2/repository/io/quarkus/quarkus-bom | wc -l' in container and immediately check its output for 1 diff --git a/packages/kogito-swf-devmode/test-resources/tests/features/kogito-swf-devmode.feature b/packages/kogito-swf-devmode/test-resources/tests/features/kogito-swf-devmode.feature new file mode 100644 index 00000000000..c17ff1f9e69 --- /dev/null +++ b/packages/kogito-swf-devmode/test-resources/tests/features/kogito-swf-devmode.feature @@ -0,0 +1,144 @@ +@quay.io/kiegroup/kogito-swf-devmode +Feature: Serverless Workflow devmode images + + Scenario: Verify if container starts in devmode by default + When container is started with env + | variable | value | + | SCRIPT_DEBUG | true | + Then check that page is served + | property | value | + | port | 8080 | + | path | /q/health/ready | + | wait | 480 | + | request_method | GET | + | expected_status_code | 200 | + And container log should contain --no-transfer-progress + And container log should contain -Duser.home=/home/kogito -o + And container log should contain -Dquarkus.test.continuous-testing=disabled + And container log should match regex Installed features:.*kogito-serverless-workflow + And container log should match regex Installed features:.*kie-addon-knative-eventing-extension + And container log should match regex Installed features:.*smallrye-health + And container log should match regex Installed features:.*sonataflow-quarkus-devui + And container log should match regex Installed features:.*kie-addon-source-files-extension + And container log should match regex Installed features:.*kogito-addons-quarkus-jobs-service-embedded + And container log should match regex Installed features:.*kogito-addons-quarkus-data-index-inmemory + + Scenario: Verify if container starts correctly when continuous testing is enabled + When container is started with env + | variable | value | + | SCRIPT_DEBUG | true | + | QUARKUS_CONTINUOUS_TESTING | enabled | + Then check that page is served + | property | value | + | port | 8080 | + | path | /q/health/ready | + | wait | 480 | + | request_method | GET | + | expected_status_code | 200 | + And container log should contain -Duser.home=/home/kogito + And container log should not contain /bin/mvn -B -X --batch-mode -o + And container log should contain -Dquarkus.test.continuous-testing=enabled + + Scenario: Verify if container starts correctly when QUARKUS_EXTENSIONS env is used + When container is started with env + | variable | value | + | SCRIPT_DEBUG | true | + | QUARKUS_EXTENSIONS | io.quarkus:quarkus-elytron-security-jdbc | + Then check that page is served + | property | value | + | port | 8080 | + | path | /q/health/ready | + | wait | 480 | + | request_method | GET | + | expected_status_code | 200 | + And container log should contain -Duser.home=/home/kogito + And container log should not contain /bin/mvn -B -X --batch-mode -o + And container log should contain Extension io.quarkus:quarkus-elytron-security-jdbc has been installed + And container log should match regex Installed features:.*kogito-serverless-workflow + And container log should match regex Installed features:.*kie-addon-knative-eventing-extension + And container log should match regex Installed features:.*smallrye-health + And container log should match regex Installed features:.*sonataflow-quarkus-devui + And container log should match regex Installed features:.*kie-addon-source-files-extension + And container log should match regex Installed features:.*kogito-addons-quarkus-jobs-service-embedded + And container log should match regex Installed features:.*kogito-addons-quarkus-data-index-inmemory + And container log should match regex Installed features:.*security-jdbc + + Scenario: verify that the embedded jobs-service is running + When container is started with env + | variable | value | + | QUARKUS_DEVSERVICES_ENABLED | false | + Then check that page is served + | property | value | + | port | 8080 | + | path | /q/health/ready | + | wait | 480 | + | request_method | GET | + | expected_status_code | 200 | + And container log should contain Embedded Postgres started at port + And container log should contain SET Leader + And check that page is served + | property | value | + | port | 8080 | + | path | /v2/jobs/1234 | + | wait | 480 | + | request_method | GET | + | expected_status_code | 404 | + | expected_phrase | Job not found | + + Scenario: verify that the embedded data-index service is running + When container is started with env + | variable | value | + | QUARKUS_DEVSERVICES_ENABLED | false | + Then check that page is served + | property | value | + | port | 8080 | + | path | /q/health/ready | + | request_method | GET | + | wait | 480 | + | expected_status_code | 200 | + And container log should contain Embedded Postgres started at port + And check that page is served + | property | value | + | port | 8080 | + | path | /graphql | + | request_method | POST | + | request_body | { "query": "{ProcessInstances{ id } }" } | + | wait | 480 | + | expected_status_code | 200 | + | expected_phrase | {"data":{"ProcessInstances":[]}} | + + Scenario: verify that the serverless workflow devui is running + When container is started with env + | variable | value | + | QUARKUS_DEVSERVICES_ENABLED | false | + Then check that page is served + | property | value | + | port | 8080 | + | path | /q/dev-v1/org.kie.kogito-addons-quarkus-data-index-inmemory/dataindex | + | request_method | GET | + | wait | 480 | + | expected_status_code | 200 | + And check that page is served + | property | value | + | port | 8080 | + | path | /q/dev-ui/org.apache.kie.sonataflow.sonataflow-quarkus-devui/workflows | + | request_method | GET | + | wait | 480 | + | expected_status_code | 200 | + + Scenario: Verify if container starts in devmode with service discovery enabled + When container is started with env + | variable | value | + | QUARKUS_DEVSERVICES_ENABLED | false | + Then check that page is served + | property | value | + | port | 8080 | + | path | /q/health/ready | + | wait | 480 | + | request_method | GET | + | expected_status_code | 200 | + And container log should contain kogito-addon-microprofile-config-service-catalog-extension + + Scenario: Verify if container have the KOGITO_CODEGEN_PROCESS_FAILONERROR env set to false + When container is started with command bash + Then run sh -c 'echo $KOGITO_CODEGEN_PROCESS_FAILONERROR' in container and immediately check its output for false diff --git a/packages/kogito-swf-devmode/test-resources/tests/shell/kogito-swf-devmode/.vscode/launch.json b/packages/kogito-swf-devmode/test-resources/tests/shell/kogito-swf-devmode/.vscode/launch.json new file mode 100644 index 00000000000..82cbbc6179c --- /dev/null +++ b/packages/kogito-swf-devmode/test-resources/tests/shell/kogito-swf-devmode/.vscode/launch.json @@ -0,0 +1,22 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "RunTests-port-4004", + "request": "attach", + "hostName": "localhost", + "port": 4004 + }, + { + "type": "java", + "name": "Debug (Launch) - RunTests", + "request": "launch", + "mainClass": "RunTests", + "projectName": "RunTests" + } + ] +} diff --git a/packages/kogito-swf-devmode/test-resources/tests/shell/kogito-swf-devmode/.vscode/settings.json b/packages/kogito-swf-devmode/test-resources/tests/shell/kogito-swf-devmode/.vscode/settings.json new file mode 100644 index 00000000000..b57ea44670f --- /dev/null +++ b/packages/kogito-swf-devmode/test-resources/tests/shell/kogito-swf-devmode/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "java.import.gradle.enabled": false, + "java.import.maven.enabled": false, + "java.eclipse.downloadSources": true, + "files.exclude": { + "bin/": true, + ".eclipse/": true, + ".project": true, + ".classpath": true, + "build.gradle": true + }, + "java.completion.importOrder": ["", "javax", "java", "#"] +} diff --git a/packages/kogito-swf-devmode/test-resources/tests/shell/kogito-swf-devmode/resources/greet.sw.json b/packages/kogito-swf-devmode/test-resources/tests/shell/kogito-swf-devmode/resources/greet.sw.json new file mode 100644 index 00000000000..a619b3b8bc7 --- /dev/null +++ b/packages/kogito-swf-devmode/test-resources/tests/shell/kogito-swf-devmode/resources/greet.sw.json @@ -0,0 +1,67 @@ +{ + "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/packages/kogito-swf-devmode/test-resources/tests/shell/kogito-swf-devmode/src/RunTests.java b/packages/kogito-swf-devmode/test-resources/tests/shell/kogito-swf-devmode/src/RunTests.java new file mode 100644 index 00000000000..9971e8229cf --- /dev/null +++ b/packages/kogito-swf-devmode/test-resources/tests/shell/kogito-swf-devmode/src/RunTests.java @@ -0,0 +1,86 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? + +//DEPS org.slf4j:slf4j-simple:2.0.9 + +// Junit console to start the test engine: +//DEPS org.junit.platform:junit-platform-console:1.10.1 + +// engine to run the tests (tests are written with Junit5): +//DEPS org.junit.jupiter:junit-jupiter-engine:5.10.1 + +// testcontainers +//DEPS org.testcontainers:testcontainers:1.19.3 +//DEPS org.testcontainers:junit-jupiter:1.19.3 + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.nio.file.Paths; +import java.time.Duration; +import org.junit.jupiter.api.Test; +import org.junit.platform.console.ConsoleLauncher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.BindMode; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@Testcontainers +public class RunTests { + + private static Logger LOGGER = LoggerFactory.getLogger(RunTests.class); + + private Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(LOGGER); + + @Container + private GenericContainer devModeImage = new GenericContainer(getTestImage()) + .withEnv("MAVEN_ARGS_APPEND", "-Ddebug=false -Dquarkus.devservices.enabled=false") + .withFileSystemBind(getScriptDirPath() + "/resources", + "/home/kogito/serverless-workflow-project/src/main/resources", BindMode.READ_ONLY) + .withExposedPorts(8080) + .waitingFor(Wait.forHttp("/jsongreet")) + .withStartupTimeout(Duration.ofMinutes(2)) + .withLogConsumer(logConsumer); + + @Test + public void testBuiltContainerAnswerCorrectly() throws URISyntaxException, IOException, InterruptedException { + devModeImage.start(); + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI( + "http://" + devModeImage.getHost() + ":" + devModeImage.getFirstMappedPort() + "/jsongreet")) + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .timeout(Duration.ofSeconds(10)) + .POST(HttpRequest.BodyPublishers + .ofString("{\"workflowdata\" : {\"name\": \"John\", \"language\": \"English\"}}")) + .build(); + HttpResponse response = HttpClient.newHttpClient().send(request, BodyHandlers.ofString()); + assertEquals(201, response.statusCode()); + } + + public static void main(String... args) throws Exception { + ConsoleLauncher.main("--select-class=" + RunTests.class.getName(), + "--reports-dir=" + Paths.get(getOutputDir()).toString()); + } + + static String getTestImage() { + return System.getenv("TEST_IMAGE"); + } + + static String getOutputDir() { + return System.getenv("OUTPUT_DIR"); + } + + static String getScriptDirPath() { + return System.getenv("TESTS_SCRIPT_DIR_PATH"); + } +} \ No newline at end of file diff --git a/packages/kogito-task-console/Containerfile b/packages/kogito-task-console/Containerfile index 46667b772f0..93ffaba876a 100644 --- a/packages/kogito-task-console/Containerfile +++ b/packages/kogito-task-console/Containerfile @@ -23,7 +23,7 @@ ENV RUNTIME_TOOLS_TASK_CONSOLE_KOGITO_ENV_MODE="PROD" COPY entrypoint.sh dist-dev/image-env-to-json-standalone dist-dev/EnvJson.schema.json /tmp/ -RUN microdnf --disableplugin=subscription-manager -y install httpd-2.4.57-5.el9.x86_64 \ +RUN microdnf --disableplugin=subscription-manager -y install httpd \ && microdnf --disableplugin=subscription-manager clean all \ && echo "Mutex posixsem" >> /etc/httpd/conf/httpd.conf \ && sed -i -e "/#ServerName www.example.com:80/aHeader set Content-Security-Policy \"frame-ancestors 'self';\"" /etc/httpd/conf/httpd.conf \ diff --git a/packages/kogito-task-console/package.json b/packages/kogito-task-console/package.json index 45ccd06b199..20a0a936ce9 100644 --- a/packages/kogito-task-console/package.json +++ b/packages/kogito-task-console/package.json @@ -18,11 +18,11 @@ "cleanup": "rimraf dist-dev && mkdir dist-dev", "copy:assets": "pnpm copy:webapp-assets && pnpm copy:image-env-to-json", "copy:image-env-to-json": "run-script-os", - "copy:image-env-to-json:linux:darwin": "cp ../image-env-to-json/dist/linux/image-env-to-json-standalone ./dist-dev/", - "copy:image-env-to-json:win32": "pnpm powershell \"Copy-Item ../image-env-to-json/dist/linux/image-env-to-json-standalone ./dist-dev/\"", + "copy:image-env-to-json:linux:darwin": "cp ./node_modules/@kie-tools/image-env-to-json/dist/linux/image-env-to-json-standalone ./dist-dev/", + "copy:image-env-to-json:win32": "pnpm powershell \"Copy-Item ./node_modules/@kie-tools/image-env-to-json/dist/linux/image-env-to-json-standalone ./dist-dev/\"", "copy:webapp-assets": "run-script-os", - "copy:webapp-assets:linux:darwin": "cp -R ../runtime-tools-task-console-webapp/dist ./dist-dev/runtime-tools-task-console-webapp", - "copy:webapp-assets:win32": "pnpm powershell \"Copy-Item -R ../runtime-tools-task-console-webapp/dist ./dist-dev/runtime-tools-task-console-webapp\"", + "copy:webapp-assets:linux:darwin": "cp -R ./node_modules/@kie-tools/runtime-tools-task-console-webapp/dist/ ./dist-dev/runtime-tools-task-console-webapp", + "copy:webapp-assets:win32": "pnpm powershell \"Copy-Item -R ./node_modules/@kie-tools/runtime-tools-task-console-webapp/dist/ ./dist-dev/runtime-tools-task-console-webapp\"", "env-json:schema:generate": "ts-json-schema-generator --tsconfig ./node_modules/@kie-tools/runtime-tools-task-console-webapp/tsconfig.json --path ./node_modules/@kie-tools/runtime-tools-task-console-webapp/src/env/EnvJson.ts --type EnvJson --id EnvJson --out ./dist-dev/EnvJson.schema.json", "image:docker:build": "kie-tools--image-builder build -r \"$(build-env kogitoTaskConsole.registry)\" -a \"$(build-env kogitoTaskConsole.account)\" -n \"$(build-env kogitoTaskConsole.name)\" -t \"$(build-env kogitoTaskConsole.tags)\" --build-arg KOGITO_TASK_CONSOLE_PORT=\"$(build-env kogitoTaskConsole.port)\"", "image:podman:build": "kie-tools--image-builder build -r \"$(build-env kogitoTaskConsole.registry)\" -a \"$(build-env kogitoTaskConsole.account)\" -n \"$(build-env kogitoTaskConsole.name)\" -t \"$(build-env kogitoTaskConsole.tags)\" --build-arg KOGITO_TASK_CONSOLE_PORT=\"$(build-env kogitoTaskConsole.port)\" -e podman" diff --git a/packages/maven-base/env/index.js b/packages/maven-base/env/index.js index eb80c4dbd97..7cba7bac345 100644 --- a/packages/maven-base/env/index.js +++ b/packages/maven-base/env/index.js @@ -17,15 +17,25 @@ * under the License. */ -const { varsWithName, composeEnv } = require("@kie-tools-scripts/build-env"); +const { varsWithName, composeEnv, getOrDefault } = require("@kie-tools-scripts/build-env"); module.exports = composeEnv([require("@kie-tools/root-env/env")], { - vars: varsWithName({}), + vars: varsWithName({ + KIE_TOOLS_BUILD__mavenDeploySkip: { + default: "true", + description: "Determines if a Maven build skips a deploy", + }, + }), get env() { return { mavenBase: { version: require("../package.json").version, }, + maven: { + deploy: { + skip: getOrDefault(this.vars.KIE_TOOLS_BUILD__mavenDeploySkip), + }, + }, }; }, }); diff --git a/packages/maven-base/install.js b/packages/maven-base/install.js index 84abd5b5001..a34033bc954 100644 --- a/packages/maven-base/install.js +++ b/packages/maven-base/install.js @@ -22,6 +22,4 @@ const { setup } = require("@kie-tools/maven-config-setup-helper"); setup(` -Drevision=${buildEnv.env.mavenBase.version} - -Dquarkus.platform.version=${buildEnv.env.quarkusPlatform.version} - -Dversion.org.kie.kogito=${buildEnv.env.kogitoRuntime.version} `); diff --git a/packages/maven-base/package.json b/packages/maven-base/package.json index ab18e994e1d..a55001d910e 100644 --- a/packages/maven-base/package.json +++ b/packages/maven-base/package.json @@ -17,11 +17,17 @@ "build:dev:darwin:linux": "mvn clean install -DskipTests", "build:dev:win32": "pnpm powershell \"mvn clean install -DskipTests \"", "build:prod": "pnpm lint && run-script-os", - "build:prod:darwin:linux": "mvn clean install -DskipTests=$(build-env tests.run --not) -Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)", - "build:prod:win32": "pnpm powershell \"mvn clean install `-DskipTests `-Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures)\"", - "install": "node install.js", + "build:prod:darwin:linux": "mvn clean deploy -DdeployAtEnd -DskipTests=$(build-env tests.run --not) -Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures) -Dmaven.deploy.skip=$(build-env maven.deploy.skip)", + "build:prod:win32": "pnpm powershell \"mvn clean deploy `-DdeployAtEnd `-DskipTests `-Dmaven.test.failure.ignore=$(build-env tests.ignoreFailures) `-Dmaven.deploy.skip=$(build-env maven.deploy.skip)\"", + "install": "pnpm set-quarkus-version && pnpm set-kogito-version && node install.js", "lint": "echo 'Linting'", - "powershell": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command" + "powershell": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command", + "set-kogito-version": "run-script-os", + "set-kogito-version:darwin:linux": "mvn versions:set-property -Dproperty=version.org.kie.kogito -DnewVersion=$(build-env kogitoRuntime.version)", + "set-kogito-version:win32": "pnpm powershell \"mvn versions:set-property `-Dproperty=version.org.kie.kogito `-DnewVersion=$(build-env kogitoRuntime.version)\"", + "set-quarkus-version": "run-script-os", + "set-quarkus-version:darwin:linux": "mvn versions:set-property -Dproperty=quarkus.platform.version -DnewVersion=$(build-env quarkusPlatform.version)", + "set-quarkus-version:win32": "pnpm powershell \"mvn versions:set-property `-Dproperty=quarkus.platform.version `-DnewVersion=$(build-env quarkusPlatform.version)\"" }, "devDependencies": { "@kie-tools/maven-config-setup-helper": "workspace:*", diff --git a/packages/maven-base/pom.xml b/packages/maven-base/pom.xml index 24f9ecc8b91..d43d16222de 100644 --- a/packages/maven-base/pom.xml +++ b/packages/maven-base/pom.xml @@ -23,6 +23,12 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > + + org.apache + apache + 32 + + org.kie kie-tools-maven-base ${revision} @@ -32,51 +38,57 @@ pom + + The Apache Software Foundation + https://apache.org/ + + + + + Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + scm:git:git@github.com:apache/incubator-kie-tools.git + scm:git:git@github.com:apache/incubator-kie-tools.git + scm:git:git@github.com:apache/incubator-kie-tools.git + HEAD + + + + github-issues + https://github.com/apache/incubator-kie-issues/issues + + - 3.12.1 + 2024-01-12T00:00:00Z + 3.4.1 17 17 + true UTF-8 + UTF-8 + 3.12.1 3.2.0 1.3.0 + 4.13.2 + 3.2.5 + 3.2.10.Final + 999-20240417-SNAPSHOT + ${quarkus.platform.version} + io.quarkus + 3.0.0-M7 - - - - central - Central Repository - https://repo.maven.apache.org/maven2 - default - - false - - - - apache-public-repository-group - Apache Public Repository Group - https://repository.apache.org/content/groups/public/ - - true - never - - - true - daily - - - - io.quarkus quarkus-bom - ${quarkus.platform.version} + ${quarkus.platform.version} pom import @@ -94,10 +106,34 @@ pom import + + org.drools + drools-bom + ${version.org.kie.kogito} + pom + import + + + org.kie.kogito + kogito-quarkus-test-utils + ${version.org.kie.kogito} + + + + + org.apache.maven.plugins + maven-artifact-plugin + ${version.maven.artifact.plugin} + + ${project.build.outputTimestamp} + + + + org.codehaus.mojo diff --git a/packages/online-editor/package.json b/packages/online-editor/package.json index 49056af570a..4ddd298dea1 100644 --- a/packages/online-editor/package.json +++ b/packages/online-editor/package.json @@ -23,8 +23,8 @@ "test:e2e": "run-script-if --ignore-errors \"$(build-env endToEndTests.ignoreFailures)\" --bool \"$(build-env endToEndTests.run)\" --then \"pnpm rimraf ./dist-e2e-tests\" \"pnpm test:e2e:run\"", "test:e2e:open": "pnpm exec playwright show-report dist-e2e-tests/reports", "test:e2e:run": "ONLINE_EDITOR_DEV__https=false pnpm exec playwright test", - "test:e2e:start:cors-proxy": "npm --prefix ../cors-proxy run start", - "test:e2e:start:extended-services": "npm --prefix ../extended-services run start" + "test:e2e:start:cors-proxy": "npm --prefix ./node_modules/@kie-tools/cors-proxy run start", + "test:e2e:start:extended-services": "npm --prefix ./node_modules/@kie-tools/extended-services run start" }, "dependencies": { "@kie-tools-core/editor": "workspace:*", diff --git a/packages/python-venv/README.md b/packages/python-venv/README.md new file mode 100644 index 00000000000..1a256845a93 --- /dev/null +++ b/packages/python-venv/README.md @@ -0,0 +1,5 @@ +# @kie-tools/python-venv + +This package manages the Python venv to be used by all other packages when running python scripts. + +It will install all packages necessary using `pip3`. diff --git a/packages/python-venv/package.json b/packages/python-venv/package.json new file mode 100644 index 00000000000..bbb6d198908 --- /dev/null +++ b/packages/python-venv/package.json @@ -0,0 +1,17 @@ +{ + "private": true, + "name": "@kie-tools/python-venv", + "version": "0.0.0", + "description": "", + "license": "Apache-2.0", + "keywords": [], + "scripts": { + "install": "python3 -m venv ./venv && run-script-os", + "install:linux:darwin": ". ./venv/bin/activate && pnpm install:pip", + "install:pip": "pip3 install cekit==4.11.0 behave==1.2.6 lxml==5.2.1 docker==7.0.0 docker-squash==1.2.0 elementpath==4.4.0 pyyaml==6.0.1 ruamel.yaml==0.18.6 python-dateutil==2.9.0.post0 Jinja2==3.1.3 pykwalify==1.8.0 colorlog==6.8.2 click==8.1.7", + "install:win32": ".\\venv\\Scripts\\Activate.bat && pnpm install:pip" + }, + "devDependencies": { + "run-script-os": "^1.1.6" + } +} \ No newline at end of file diff --git a/packages/runtime-tools-management-console-webapp/package.json b/packages/runtime-tools-management-console-webapp/package.json index 5ce657c2950..eaf25034db6 100644 --- a/packages/runtime-tools-management-console-webapp/package.json +++ b/packages/runtime-tools-management-console-webapp/package.json @@ -72,9 +72,11 @@ "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "apollo-server-express": "^3.13.0", "babel-jest": "^25.5.1", + "body-parser": "^1.20.2", "concurrently": "^8.2.2", "copy-webpack-plugin": "^11.0.0", "core-js": "3.6.5", + "cors": "^2.8.5", "css-loader": "^5.2.6", "css-minimizer-webpack-plugin": "^5.0.1", "enzyme": "^3.11.0", @@ -86,6 +88,7 @@ "identity-obj-proxy": "^3.0.0", "jest": "^26.6.3", "jest-junit": "^14.0.0", + "lodash": "^4.17.21", "mini-css-extract-plugin": "^2.7.6", "nodemon": "^2.0.22", "rimraf": "^3.0.2", diff --git a/packages/scesim-editor/.storybook/main.ts b/packages/scesim-editor/.storybook/main.ts index b8169c7262a..5b60b650813 100644 --- a/packages/scesim-editor/.storybook/main.ts +++ b/packages/scesim-editor/.storybook/main.ts @@ -18,6 +18,7 @@ */ import { baseConfig } from "@kie-tools/storybook-base/dist/config/baseConfig"; +import common from "@kie-tools-core/webpack-base/webpack.common.config"; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore @@ -25,7 +26,7 @@ import { env } from "../env"; const buildEnv: any = env; // build-env is not typed const config = { - ...baseConfig(buildEnv.webpack.dev), + ...baseConfig(buildEnv.webpack.dev, common(buildEnv.webpack)), }; export default config; diff --git a/packages/serverless-logic-web-tools-swf-builder-image/Containerfile b/packages/serverless-logic-web-tools-swf-builder-image/Containerfile index a88d528f7c7..84aef54cfef 100644 --- a/packages/serverless-logic-web-tools-swf-builder-image/Containerfile +++ b/packages/serverless-logic-web-tools-swf-builder-image/Containerfile @@ -15,9 +15,9 @@ # specific language governing permissions and limitations # under the License. -ARG KOGITO_IMAGE_TAG +ARG BASE_IMAGE_URL -FROM --platform=linux/amd64 quay.io/kiegroup/kogito-swf-builder-nightly:$KOGITO_IMAGE_TAG +FROM --platform=linux/amd64 $BASE_IMAGE_URL ENV PATH="${PATH}:/usr/share/maven/bin" @@ -26,6 +26,6 @@ COPY dist-dev/webapp/ src/main/resources/META-INF/resources/ RUN rm .dockerignore .gitignore README.md \ && rm -rf .mvn/ src/main/java/ \ && mvn quarkus:add-extension -Dextensions="quarkus-jsonp,quarkus-smallrye-openapi,quarkus-resteasy,smallrye-health" \ - && echo -e '\nquarkus.http.enable-compression=true\nquarkus.swagger-ui.always-include=true\nquarkus.http.host=0.0.0.0\nquarkus.http.cors=true\nquarkus.http.cors.origins=*' >> src/main/resources/application.properties \ + && echo -e '\nquarkus.http.enable-compression=true\nquarkus.swagger-ui.always-include=true\nquarkus.http.host=0.0.0.0\nquarkus.http.cors=true\nquarkus.http.cors.origins=*\nkogito.service.url=http://localhost:8080' >> src/main/resources/application.properties \ && mvn clean package -B -ntp \ && rm -rf target/ diff --git a/packages/serverless-logic-web-tools-swf-builder-image/env/index.js b/packages/serverless-logic-web-tools-swf-builder-image/env/index.js index f49f80de185..afa3a2f7ee0 100644 --- a/packages/serverless-logic-web-tools-swf-builder-image/env/index.js +++ b/packages/serverless-logic-web-tools-swf-builder-image/env/index.js @@ -19,26 +19,27 @@ const { varsWithName, getOrDefault, composeEnv } = require("@kie-tools-scripts/build-env"); -module.exports = composeEnv( - [require("@kie-tools/root-env/env"), require("@kie-tools/serverless-logic-web-tools-swf-builder-image-env/env")], - { - vars: varsWithName({ - SERVERLESS_LOGIC_WEB_TOOLS__swfBuilderImageBuildTags: { - default: "latest", - description: "", - }, - SERVERLESS_LOGIC_WEB_TOOLS__swfBuilderKogitoImageTag: { - default: "999-20240417", - description: "", - }, - }), - get env() { - return { - swfBuilderImage: { - buildTags: getOrDefault(this.vars.SERVERLESS_LOGIC_WEB_TOOLS__swfBuilderImageBuildTags), - kogitoImageTag: getOrDefault(this.vars.SERVERLESS_LOGIC_WEB_TOOLS__swfBuilderKogitoImageTag), - }, - }; +const rootEnv = require("@kie-tools/root-env/env"); +const serverlessLogicWebToolsSwfBuilderImageEnv = require("@kie-tools/serverless-logic-web-tools-swf-builder-image-env/env"); +const kogitoSwfBuilderEnv = require("@kie-tools/kogito-swf-builder/env"); + +module.exports = composeEnv([rootEnv, serverlessLogicWebToolsSwfBuilderImageEnv, kogitoSwfBuilderEnv], { + vars: varsWithName({ + SERVERLESS_LOGIC_WEB_TOOLS__swfBuilderImageBuildTags: { + default: "latest", + description: "", }, - } -); + SERVERLESS_LOGIC_WEB_TOOLS_SWF_BUILDER_IMAGE__baseImageUrl: { + default: `${kogitoSwfBuilderEnv.env.kogitoSwfBuilder.registry}/${kogitoSwfBuilderEnv.env.kogitoSwfBuilder.account}/${kogitoSwfBuilderEnv.env.kogitoSwfBuilder.name}:${kogitoSwfBuilderEnv.env.kogitoSwfBuilder.tag}`, + description: "The image used in the FROM import.", + }, + }), + get env() { + return { + swfBuilderImage: { + buildTags: getOrDefault(this.vars.SERVERLESS_LOGIC_WEB_TOOLS__swfBuilderImageBuildTags), + baseImageUrl: getOrDefault(this.vars.SERVERLESS_LOGIC_WEB_TOOLS_SWF_BUILDER_IMAGE__baseImageUrl), + }, + }; + }, +}); diff --git a/packages/serverless-logic-web-tools-swf-builder-image/package.json b/packages/serverless-logic-web-tools-swf-builder-image/package.json index fa2b5c41676..239e71d6c4a 100644 --- a/packages/serverless-logic-web-tools-swf-builder-image/package.json +++ b/packages/serverless-logic-web-tools-swf-builder-image/package.json @@ -21,11 +21,12 @@ "build:prod:win32": "echo \"Build not supported on Windows\"", "cleanup": "rimraf dist-dev && mkdir dist-dev", "copy:assets": "pnpm copy:webapp", - "copy:webapp": "cp -r ../sonataflow-deployment-webapp/dist dist-dev/webapp", - "image:docker:build": "run-script-if --bool $([ $(command -v docker) ] && echo true || echo false) --then \"docker build --ulimit nofile=5000:5000 $(echo $(build-env swfBuilderImage.buildTags) | xargs printf -- \"-t $(build-env swfBuilderImageEnv.registry)/$(build-env swfBuilderImageEnv.account)/$(build-env swfBuilderImageEnv.name):%s\n\" | xargs echo) --build-arg KOGITO_IMAGE_TAG=$(build-env swfBuilderImage.kogitoImageTag) .\" --else \"echo Docker not found, skipping image build.\"", - "image:podman:build": "run-script-if --bool $([ $(command -v podman) ] && echo true || echo false) --then \"podman build --ulimit nofile=5000:5000 $(echo $(build-env swfBuilderImage.buildTags) | xargs printf -- \"-t $(build-env swfBuilderImageEnv.registry)/$(build-env swfBuilderImageEnv.account)/$(build-env swfBuilderImageEnv.name):%s\n\" | xargs echo) --build-arg KOGITO_IMAGE_TAG=$(build-env swfBuilderImage.kogitoImageTag) -f Containerfile\" --else \"echo Podman not found, skipping image build.\"" + "copy:webapp": "cp -r ./node_modules/sonataflow-deployment-webapp/dist dist-dev/webapp", + "image:docker:build": "run-script-if --bool $([ $(command -v docker) ] && echo true || echo false) --then \"docker build --ulimit nofile=5000:5000 $(echo $(build-env swfBuilderImage.buildTags) | xargs printf -- \"-t $(build-env swfBuilderImageEnv.registry)/$(build-env swfBuilderImageEnv.account)/$(build-env swfBuilderImageEnv.name):%s\n\" | xargs echo) --build-arg BASE_IMAGE_URL=$(build-env swfBuilderImage.baseImageUrl) .\" --else \"echo Docker not found, skipping image build.\"", + "image:podman:build": "run-script-if --bool $([ $(command -v podman) ] && echo true || echo false) --then \"podman build --ulimit nofile=5000:5000 $(echo $(build-env swfBuilderImage.buildTags) | xargs printf -- \"-t $(build-env swfBuilderImageEnv.registry)/$(build-env swfBuilderImageEnv.account)/$(build-env swfBuilderImageEnv.name):%s\n\" | xargs echo) --build-arg BASE_IMAGE_URL=$(build-env swfBuilderImage.baseImageUrl) -f Containerfile\" --else \"echo Podman not found, skipping image build.\"" }, "devDependencies": { + "@kie-tools/kogito-swf-builder": "workspace:*", "@kie-tools/root-env": "workspace:*", "@kie-tools/serverless-logic-web-tools-swf-builder-image-env": "workspace:*", "rimraf": "^3.0.2", diff --git a/packages/serverless-logic-web-tools-swf-deployment-quarkus-app/package.json b/packages/serverless-logic-web-tools-swf-deployment-quarkus-app/package.json index 692c4d3da2e..0729c5ac20c 100644 --- a/packages/serverless-logic-web-tools-swf-deployment-quarkus-app/package.json +++ b/packages/serverless-logic-web-tools-swf-deployment-quarkus-app/package.json @@ -26,6 +26,9 @@ "quarkus:dev:darwin:linux": "mvn clean package quarkus:dev -DskipTests", "quarkus:dev:win32": "mvn clean package quarkus:dev `-DskipTests" }, + "dependencies": { + "@kie-tools/sonataflow-quarkus-devui": "workspace:*" + }, "devDependencies": { "@kie-tools/maven-config-setup-helper": "workspace:*", "@kie-tools/root-env": "workspace:*", diff --git a/packages/serverless-logic-web-tools-swf-deployment-quarkus-app/pom.xml b/packages/serverless-logic-web-tools-swf-deployment-quarkus-app/pom.xml index 8f1bee12f64..f65cd96d0b9 100644 --- a/packages/serverless-logic-web-tools-swf-deployment-quarkus-app/pom.xml +++ b/packages/serverless-logic-web-tools-swf-deployment-quarkus-app/pom.xml @@ -22,6 +22,15 @@ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > + + + + + org.apache + apache + 32 + + 4.0.0 org.kie.kogito serverless-logic-web-tools-swf-deployment-quarkus-app @@ -43,50 +52,6 @@ 3.2.5 - - - - central - Central Repository - https://repo.maven.apache.org/maven2 - default - - false - - - - apache-public-repository-group - Apache Public Repository Group - https://repository.apache.org/content/groups/public/ - - true - never - - - true - daily - - - - jboss-public-repository-group - JBoss Public Repository Group - https://repository.jboss.org/nexus/content/groups/public/ - default - - true - never - - - true - never - - - - @@ -146,6 +111,7 @@ org.apache.kie.sonataflow sonataflow-quarkus-devui + ${project.version} org.kie diff --git a/packages/serverless-logic-web-tools-swf-dev-mode-image/Containerfile b/packages/serverless-logic-web-tools-swf-dev-mode-image/Containerfile index 3dd710cbaff..bc6f04f280c 100644 --- a/packages/serverless-logic-web-tools-swf-dev-mode-image/Containerfile +++ b/packages/serverless-logic-web-tools-swf-dev-mode-image/Containerfile @@ -25,7 +25,8 @@ USER root RUN chown kogito /home/kogito/.m2 USER kogito -COPY --chown=kogito:root dist-dev/serverless-logic-web-tools-swf-deployment-quarkus-app/ /home/kogito/serverless-logic-web-tools-swf-deployment-quarkus-app/ +COPY --chown=kogito:root dist-dev/quarkus-app/ /home/kogito/serverless-logic-web-tools-swf-deployment-quarkus-app/ +COPY --chown=kogito:root dist-dev/quarkus-app-m2/ /home/kogito/.m2/repository WORKDIR /home/kogito/serverless-logic-web-tools-swf-deployment-quarkus-app/ diff --git a/packages/serverless-logic-web-tools-swf-dev-mode-image/env/index.js b/packages/serverless-logic-web-tools-swf-dev-mode-image/env/index.js index 01498c063bc..658917fa701 100644 --- a/packages/serverless-logic-web-tools-swf-dev-mode-image/env/index.js +++ b/packages/serverless-logic-web-tools-swf-dev-mode-image/env/index.js @@ -27,7 +27,7 @@ module.exports = composeEnv( default: "latest", description: "", }, - SERVERLESS_LOGIC_WEB_TOOLS__swfDevModeKogitoImageTag: { + SERVERLESS_LOGIC_WEB_TOOLS_DEVMODE_IMAGE__kogitoBaseBuilderImageTag: { default: "999-20240417", description: "", }, @@ -35,8 +35,9 @@ module.exports = composeEnv( get env() { return { swfDevModeImage: { + version: require("../package.json").version, buildTags: getOrDefault(this.vars.SERVERLESS_LOGIC_WEB_TOOLS__swfDevModeImageBuildTags), - kogitoImageTag: getOrDefault(this.vars.SERVERLESS_LOGIC_WEB_TOOLS__swfDevModeKogitoImageTag), + kogitoImageTag: getOrDefault(this.vars.SERVERLESS_LOGIC_WEB_TOOLS_DEVMODE_IMAGE__kogitoBaseBuilderImageTag), }, }; }, diff --git a/packages/serverless-logic-web-tools-swf-dev-mode-image/install.js b/packages/serverless-logic-web-tools-swf-dev-mode-image/install.js new file mode 100644 index 00000000000..94df8d4a2e8 --- /dev/null +++ b/packages/serverless-logic-web-tools-swf-dev-mode-image/install.js @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 buildEnv = require("./env"); +const { setup } = require("@kie-tools/maven-config-setup-helper"); + +setup(` + -Drevision=${buildEnv.env.swfDevModeImage.version} +`); diff --git a/packages/serverless-logic-web-tools-swf-dev-mode-image/package.json b/packages/serverless-logic-web-tools-swf-dev-mode-image/package.json index afeb25eb7b8..c4f624bd608 100644 --- a/packages/serverless-logic-web-tools-swf-dev-mode-image/package.json +++ b/packages/serverless-logic-web-tools-swf-dev-mode-image/package.json @@ -19,16 +19,21 @@ "build:prod:linux": "run-script-if --bool \"$(build-env containerImages.build)\" --then \"pnpm copy:assets\" \"pnpm image:podman:build\"", "build:prod:win32": "echo \"Build not supported on Windows\"", "cleanup": "rimraf dist-dev && mkdir dist-dev", - "copy:assets": "pnpm copy:serverless-logic-web-tools-swf-deployment-quarkus-app", - "copy:serverless-logic-web-tools-swf-deployment-quarkus-app": "cp -R ../serverless-logic-web-tools-swf-deployment-quarkus-app ./dist-dev/serverless-logic-web-tools-swf-deployment-quarkus-app", + "copy:assets": "pnpm copy:quarkus-app && pnpm copy:sonataflow-deployment-webapp && pnpm copy:m2-for-sonataflow-quarkus-devui", + "copy:m2-for-sonataflow-quarkus-devui": "mvn dependency:copy-dependencies -Dmdep.useRepositoryLayout=true -Dmdep.copyPom=true -DexcludeTransitive=true -DoutputDirectory=./dist-dev/quarkus-app-m2", + "copy:quarkus-app": "cp -R ./node_modules/@kie-tools/serverless-logic-web-tools-swf-deployment-quarkus-app/ ./dist-dev/quarkus-app && mkdir -p ./dist-dev/quarkus-app/src/main/resources/META-INF/resources/ && rm -rf ./dist-dev/quarkus-app/node_modules ./dist-dev/quarkus-app/install.js ./dist-dev/quarkus-app/env ./dist-dev/quarkus-app/package.json", + "copy:sonataflow-deployment-webapp": "cp -R ./node_modules/sonataflow-deployment-webapp/dist/* ./dist-dev/quarkus-app/src/main/resources/META-INF/resources", "image:docker:build": "run-script-if --bool $([ $(command -v docker) ] && echo true || echo false) --then \"docker build --ulimit nofile=5000:5000 $(echo $(build-env swfDevModeImage.buildTags) | xargs printf -- \"-t $(build-env swfDevModeImageEnv.registry)/$(build-env swfDevModeImageEnv.account)/$(build-env swfDevModeImageEnv.name):%s\n\" | xargs echo) --build-arg KOGITO_IMAGE_TAG=$(build-env swfDevModeImage.kogitoImageTag) .\" --else \"echo Docker not found, skipping image build.\"", - "image:podman:build": "run-script-if --bool $([ $(command -v podman) ] && echo true || echo false) --then \"podman build --ulimit nofile=5000:5000 $(echo $(build-env swfDevModeImage.buildTags) | xargs printf -- \"-t $(build-env swfDevModeImageEnv.registry)/$(build-env swfDevModeImageEnv.account)/$(build-env swfDevModeImageEnv.name):%s\n\" | xargs echo) --build-arg KOGITO_IMAGE_TAG=$(build-env swfDevModeImage.kogitoImageTag) -f Containerfile\" --else \"echo Podman not found, skipping image build.\"" + "image:podman:build": "run-script-if --bool $([ $(command -v podman) ] && echo true || echo false) --then \"podman build --ulimit nofile=5000:5000 $(echo $(build-env swfDevModeImage.buildTags) | xargs printf -- \"-t $(build-env swfDevModeImageEnv.registry)/$(build-env swfDevModeImageEnv.account)/$(build-env swfDevModeImageEnv.name):%s\n\" | xargs echo) --build-arg KOGITO_IMAGE_TAG=$(build-env swfDevModeImage.kogitoImageTag) -f Containerfile\" --else \"echo Podman not found, skipping image build.\"", + "install": "node install.js" }, "devDependencies": { + "@kie-tools/maven-config-setup-helper": "workspace:*", "@kie-tools/root-env": "workspace:*", "@kie-tools/serverless-logic-web-tools-swf-deployment-quarkus-app": "workspace:*", "@kie-tools/serverless-logic-web-tools-swf-dev-mode-image-env": "workspace:*", "rimraf": "^3.0.2", - "run-script-os": "^1.1.6" + "run-script-os": "^1.1.6", + "sonataflow-deployment-webapp": "workspace:*" } } \ No newline at end of file diff --git a/packages/serverless-logic-web-tools-swf-dev-mode-image/pom.xml b/packages/serverless-logic-web-tools-swf-dev-mode-image/pom.xml new file mode 100644 index 00000000000..bbdaba366f1 --- /dev/null +++ b/packages/serverless-logic-web-tools-swf-dev-mode-image/pom.xml @@ -0,0 +1,54 @@ + + + + 4.0.0 + org.kie.kogito + serverless-logic-web-tools-swf-deployment-quarkus-app-image + ${revision} + + + + org.apache.kie.sonataflow + sonataflow-quarkus-devui-deployment + ${project.version} + + + org.apache.kie.sonataflow + sonataflow-quarkus-devui + ${project.version} + + + org.apache.kie.sonataflow + sonataflow-quarkus-devui-parent + ${project.version} + pom + + + org.kie + kie-tools-maven-base + ${project.version} + pom + + + diff --git a/packages/serverless-logic-web-tools/src/editor/hooks/useDeployDropdownItems.tsx b/packages/serverless-logic-web-tools/src/editor/hooks/useDeployDropdownItems.tsx index 88b991e6aec..3ae57de0182 100644 --- a/packages/serverless-logic-web-tools/src/editor/hooks/useDeployDropdownItems.tsx +++ b/packages/serverless-logic-web-tools/src/editor/hooks/useDeployDropdownItems.tsx @@ -106,9 +106,7 @@ export function useDeployDropdownItems(props: Props) { data-testid="alert-dev-mode-ready" actionClose={} actionLinks={ - window.open(routeUrl, "_blank")}> - {"Go to Serverless Workflow Dev UI ↗"} - + window.open(routeUrl, "_blank")}>{"Go to Dev Mode ↗"} } > <> @@ -236,7 +234,7 @@ export function useDeployDropdownItems(props: Props) { return; } uploadToDevModeSuccessAlert.close(); - devModeReadyAlert.show({ routeUrl: devMode.endpoints!.swfDevUi, filePaths: result.uploadedPaths }); + devModeReadyAlert.show({ routeUrl: devMode.endpoints!.base, filePaths: result.uploadedPaths }); window.clearInterval(fetchDevModeDeploymentTask); }, FETCH_DEV_MODE_DEPLOYMENT_POLLING_TIME); } else { diff --git a/packages/serverless-logic-web-tools/src/openshift/deploy/strategies/KogitoProjectDeployment.ts b/packages/serverless-logic-web-tools/src/openshift/deploy/strategies/KogitoProjectDeployment.ts index f831e2cc92f..e2417520278 100644 --- a/packages/serverless-logic-web-tools/src/openshift/deploy/strategies/KogitoProjectDeployment.ts +++ b/packages/serverless-logic-web-tools/src/openshift/deploy/strategies/KogitoProjectDeployment.ts @@ -69,7 +69,7 @@ export class KogitoProjectDeployment extends DeploymentStrategy { importBaseImage: `FROM ${BaseBuilder.CONTAINER_IMAGE}`, setupEnvVars: `ENV ${BaseBuilder.ENV}`, createProjectFolder: `RUN mkdir ${projectPaths.folders.root}/`, - copyFilesIntoContainer: `COPY . ${projectPaths.folders.root}/`, + copyFilesIntoContainer: `COPY --chown=kogito:root . ${projectPaths.folders.root}/`, configCluster: { setServer: `${BaseBuilder.KUBECTL_PATH} config set-cluster ${clusterName} --server=${this.args.openShiftConnection.host}`, setCredentials: `${BaseBuilder.KUBECTL_PATH} config set-credentials ${clusterCredentialsName} --token=${this.args.openShiftConnection.token}`, diff --git a/packages/serverless-logic-web-tools/src/openshift/dropdown/OpenShiftDeploymentDropdownItem.tsx b/packages/serverless-logic-web-tools/src/openshift/dropdown/OpenShiftDeploymentDropdownItem.tsx index 4458befeafe..fbb1f72b03c 100644 --- a/packages/serverless-logic-web-tools/src/openshift/dropdown/OpenShiftDeploymentDropdownItem.tsx +++ b/packages/serverless-logic-web-tools/src/openshift/dropdown/OpenShiftDeploymentDropdownItem.tsx @@ -67,8 +67,8 @@ export function OpenShiftDeploymentDropdownItem(props: Props) { const onDeploymentClicked = useCallback(() => { const endpoints = buildEndpoints(props.deployment.routeUrl); - window.open(props.deployment.devMode ? endpoints.swfDevUi : endpoints.base, "_blank"); - }, [props.deployment.devMode, props.deployment.routeUrl]); + window.open(endpoints.base, "_blank"); + }, [props.deployment.routeUrl]); const onRestoreClicked = useCallback(async () => { if (isRestoring) { diff --git a/packages/serverless-logic-web-tools/src/openshift/swfDevMode/DevModeConstants.ts b/packages/serverless-logic-web-tools/src/openshift/swfDevMode/DevModeConstants.ts index a3f6427ac21..5e5cec51f04 100644 --- a/packages/serverless-logic-web-tools/src/openshift/swfDevMode/DevModeConstants.ts +++ b/packages/serverless-logic-web-tools/src/openshift/swfDevMode/DevModeConstants.ts @@ -76,7 +76,7 @@ export const buildEndpoints = (routeUrl: string): DevModeEndpoints => ({ base: routeUrl, upload: `${routeUrl}/upload`, quarkusDevUi: `${routeUrl}/q/dev`, - swfDevUi: `${routeUrl}/q/dev/org.kie.kogito.kogito-quarkus-serverless-workflow-devui/workflowInstances`, + swfDevUi: `${routeUrl}/q/dev-ui/org.apache.kie.sonataflow.sonataflow-quarkus-devui/workflows`, swaggerUi: `${routeUrl}/q/swagger-ui`, health: { live: `${routeUrl}/q/health/live`, diff --git a/packages/serverless-workflow-combined-editor/src/editor/ServerlessWorkflowCombinedEditor.tsx b/packages/serverless-workflow-combined-editor/src/editor/ServerlessWorkflowCombinedEditor.tsx index c1f42b1128b..84972622bf3 100644 --- a/packages/serverless-workflow-combined-editor/src/editor/ServerlessWorkflowCombinedEditor.tsx +++ b/packages/serverless-workflow-combined-editor/src/editor/ServerlessWorkflowCombinedEditor.tsx @@ -462,15 +462,17 @@ const RefForwardingServerlessWorkflowCombinedEditor: ForwardRefRenderFunction< } }, [editorEnvelopeCtx, isCombinedEditorReady]); + const themeStyle = getThemeStyle(theme!); + return ( -
    - +
    + {previewOptions?.editorMode === "diagram" ? ( renderDiagramEditor() ) : previewOptions?.editorMode === "text" ? ( renderTextEditor() ) : ( - + @@ -486,13 +488,27 @@ const RefForwardingServerlessWorkflowCombinedEditor: ForwardRefRenderFunction< ); }; -function getThemeStyle(theme: EditorTheme) { +interface ThemeStyleTag { + drawer: string; + loadScreen: string; + backgroundColor: string; +} + +function getThemeStyle(theme: EditorTheme): ThemeStyleTag { switch (theme) { case EditorTheme.DARK: { - return "dark"; + return { + drawer: "dark", + loadScreen: "vscode-dark", + backgroundColor: "black", + }; } default: { - return ""; + return { + drawer: "", + loadScreen: "", + backgroundColor: "", + }; } } } diff --git a/packages/serverless-workflow-diagram-editor-assets/package.json b/packages/serverless-workflow-diagram-editor-assets/package.json index b2ad1559793..cee071e5523 100644 --- a/packages/serverless-workflow-diagram-editor-assets/package.json +++ b/packages/serverless-workflow-diagram-editor-assets/package.json @@ -21,7 +21,7 @@ "build:dev": "pnpm dist", "build:prod": "pnpm lint && pnpm dist", "dist": "rimraf dist && mkdir dist && pnpm dist:sw", - "dist:sw": "mkdir \"dist/sw\" && cpr ../serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/target/sw-editor-kogito-app/org.kie.workbench.common.stunner.sw.KogitoSWEditor ./dist/sw/org.kie.workbench.common.stunner.sw.KogitoSWEditor", + "dist:sw": "mkdir \"dist/sw\" && cpr ./node_modules/@kie-tools/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/target/sw-editor-kogito-app/org.kie.workbench.common.stunner.sw.KogitoSWEditor ./dist/sw/org.kie.workbench.common.stunner.sw.KogitoSWEditor", "lint": "echo 'Linting'" }, "devDependencies": { diff --git a/packages/serverless-workflow-diagram-editor/appformer-bom/pom.xml b/packages/serverless-workflow-diagram-editor/appformer-bom/pom.xml index 15779060e8a..c896397d778 100644 --- a/packages/serverless-workflow-diagram-editor/appformer-bom/pom.xml +++ b/packages/serverless-workflow-diagram-editor/appformer-bom/pom.xml @@ -72,10 +72,20 @@ true + 0.1 + + + org.kie.j2cl.tools + bom + ${version.j2cl.tools} + pom + import + + org.kie.kogito.stunner.serverless.editor @@ -251,66 +261,12 @@ - - org.eclipse.jgit - org.eclipse.jgit - ${version.org.eclipse.jgit} - - - commons-logging - commons-logging - - - - - - org.eclipse.jgit - org.eclipse.jgit.http.server - ${version.org.eclipse.jgit} - - - commons-logging - commons-logging - - - javax.servlet - servlet-api - - - - com.google.jsinterop base ${version.com.google.jsinterop.base} - - com.allen-sauer.gwt.dnd - gwt-dnd - ${version.com.allen-sauer.gwt.dnd} - - - javax.servlet - javax.servlet-api - - - - - - org.scannotation - scannotation - ${version.org.scannotation} - - - - javassist - javassist - - - - com.google.gwt.gwtmockito gwtmockito @@ -323,89 +279,6 @@ - - - org.jboss.byteman - byteman - ${version.org.jboss.byteman} - test - - - org.jboss.byteman - byteman-submit - ${version.org.jboss.byteman} - test - - - org.jboss.byteman - byteman-install - ${version.org.jboss.byteman} - test - - - org.jboss.byteman - byteman-bmunit - ${version.org.jboss.byteman} - test - - - - org.infinispan - infinispan-client-hotrod - ${version.org.infinispan} - - - ch.qos.logback - logback-classic - - - org.jboss.marshalling - jboss-marshalling-osgi - - - - - org.infinispan - infinispan-commons - ${version.org.infinispan} - - - org.jboss.marshalling - jboss-marshalling-osgi - - - - - io.netty - netty-buffer - ${version.io.netty} - - - io.netty - netty-transport - ${version.io.netty} - - - io.netty - netty-handler - ${version.io.netty} - - - io.netty - netty-codec-http - ${version.io.netty} - - - ch.qos.logback - logback-classic - ${version.ch.qos.logback} - - - ch.qos.logback - logback-core - ${version.ch.qos.logback} - - org.kie.kogito.stunner.serverless.editor @@ -420,24 +293,6 @@ sources - - org.kie.kogito.stunner.serverless.editor.third_party.jakarta.jsonb - api - ${project.version} - - - - org.kie.kogito.stunner.serverless.editor.third_party.jakarta.jsonb - impl - ${project.version} - - - - org.kie.kogito.stunner.serverless.editor.third_party - stdlib - ${project.version} - - org.kie.kogito.stunner.serverless.editor.third_party gwtproject @@ -450,35 +305,6 @@ ${project.version} - - org.kie.kogito.stunner.serverless.editor.third_party.tooling.marshalling.json - common - ${project.version} - - - - org.kie.kogito.stunner.serverless.editor.third_party.tooling.marshalling.json - processor - ${project.version} - - - org.kie.kogito.stunner.serverless.editor.third_party.tooling.marshalling.yaml - common - ${project.version} - - - - org.kie.kogito.stunner.serverless.editor.third_party.tooling.marshalling.yaml - processor - ${project.version} - - - - org.kie.kogito.stunner.serverless.editor.third_party.tooling.marshalling.yaml - snakeyaml-engine - ${project.version} - - org.kie.kogito.stunner.serverless.editor.third_party.gwtbootstrap3 gwtbootstrap3 @@ -497,43 +323,6 @@ ${project.version} - - - - org.arquillian.cube - arquillian-cube-docker-junit-rule - ${version.org.arquillian.cube} - test - - - log4j - log4j - - - com.github.docker-java - docker-java - - - org.arquillian.cube - arquillian-cube-requirement-spi - - - - - - org.jboss.marshalling - marshalling-api - ${version.org.jboss.marshalling.api} - test - - - - org.jboss.shrinkwrap - shrinkwrap-impl-base - ${version.org.jboss.shrinkwrap} - test - - org.gwtproject gwt-dev diff --git a/packages/serverless-workflow-diagram-editor/appformer-client-api/pom.xml b/packages/serverless-workflow-diagram-editor/appformer-client-api/pom.xml index 8be5194768b..34706b55de5 100644 --- a/packages/serverless-workflow-diagram-editor/appformer-client-api/pom.xml +++ b/packages/serverless-workflow-diagram-editor/appformer-client-api/pom.xml @@ -24,7 +24,7 @@ > org.kie.kogito.stunner.serverless.editor - stunner-editors-parent + serverless-workflow-diagram-editor-parent ${revision} 4.0.0 @@ -41,8 +41,8 @@ - io.crysknife - crysknife-core + org.kie.j2cl.tools.di + core diff --git a/packages/serverless-workflow-diagram-editor/appformer-kogito-bridge/pom.xml b/packages/serverless-workflow-diagram-editor/appformer-kogito-bridge/pom.xml index cfa481267ac..5c782a2c712 100644 --- a/packages/serverless-workflow-diagram-editor/appformer-kogito-bridge/pom.xml +++ b/packages/serverless-workflow-diagram-editor/appformer-kogito-bridge/pom.xml @@ -26,7 +26,7 @@ 4.0.0 org.kie.kogito.stunner.serverless.editor - stunner-editors-parent + serverless-workflow-diagram-editor-parent ${revision} ../pom.xml diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-bom/pom.xml b/packages/serverless-workflow-diagram-editor/kie-wb-common-bom/pom.xml index 32774c64a0c..935edca317d 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-bom/pom.xml +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-bom/pom.xml @@ -72,6 +72,7 @@ true + 0.1 @@ -218,6 +219,14 @@ ${project.version} + + org.kie.j2cl.tools + bom + ${j2cl.tools.version} + pom + import + + diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/pom.xml b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/pom.xml index 071f6744e0f..b78d650a040 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/pom.xml +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/pom.xml @@ -104,7 +104,7 @@ - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors processors provided diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/StunnerLienzoCore.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/StunnerLienzoCore.java index 23f8886c284..9406ec4664c 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/StunnerLienzoCore.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/StunnerLienzoCore.java @@ -25,12 +25,12 @@ import com.ait.lienzo.client.core.config.LienzoCore; import com.ait.lienzo.shared.core.types.ImageSelectionMode; -import io.crysknife.ui.translation.client.annotation.Bundle; import org.gwtbootstrap3.extras.notify.client.NotifyClientBundle; +import org.kie.j2cl.tools.di.ui.translation.client.annotation.Bundle; +import org.kie.j2cl.tools.processors.common.injectors.ScriptInjector; +import org.kie.j2cl.tools.processors.common.injectors.StyleInjector; +import org.kie.j2cl.tools.processors.common.resources.TextResource; import org.kie.workbench.common.stunner.client.lienzo.resources.StunnerLienzoCoreResources; -import org.treblereel.j2cl.processors.common.injectors.ScriptInjector; -import org.treblereel.j2cl.processors.common.injectors.StyleInjector; -import org.treblereel.j2cl.processors.common.resources.TextResource; @Bundle("resources/i18n/StunnerLienzoConstants.properties") public class StunnerLienzoCore { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/canvas/command/LienzoCanvasCommandFactory.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/canvas/command/LienzoCanvasCommandFactory.java index 7d2ee747731..7cca2c4233e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/canvas/command/LienzoCanvasCommandFactory.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/canvas/command/LienzoCanvasCommandFactory.java @@ -20,10 +20,10 @@ package org.kie.workbench.common.stunner.client.lienzo.canvas.command; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.canvas.command.DefaultCanvasCommandFactory; import org.kie.workbench.common.stunner.core.client.command.CanvasCommand; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/alerts/Alerts.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/alerts/Alerts.java index 2cd5a423102..73b0c2a45e5 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/alerts/Alerts.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/alerts/Alerts.java @@ -23,11 +23,11 @@ import java.util.Objects; import elemental2.dom.HTMLElement; -import io.crysknife.client.IsElement; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.core.client.i18n.ClientTranslationService; import org.uberfire.client.mvp.UberView; import org.uberfire.mvp.Command; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/alerts/AlertsPresenter.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/alerts/AlertsPresenter.java index 72dec4b4f90..908d1a5c3bf 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/alerts/AlertsPresenter.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/alerts/AlertsPresenter.java @@ -29,7 +29,6 @@ import com.ait.lienzo.tools.client.event.MouseEventUtil; import elemental2.dom.Element; import elemental2.dom.EventListener; -import io.crysknife.client.IsElement; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; import org.gwtbootstrap3.client.ui.constants.IconType; @@ -39,6 +38,7 @@ import org.gwtbootstrap3.extras.notify.client.ui.NotifySettings; import org.gwtproject.safehtml.shared.SafeHtmlBuilder; import org.gwtproject.timer.client.Timer; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoCanvas; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoPanel; import org.kie.workbench.common.stunner.core.client.components.views.FloatingView; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/alerts/AlertsView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/alerts/AlertsView.java index da39067c9ce..cc1bfd2e884 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/alerts/AlertsView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/alerts/AlertsView.java @@ -23,14 +23,14 @@ import elemental2.dom.Event; import elemental2.dom.HTMLButtonElement; import elemental2.dom.HTMLElement; -import io.crysknife.ui.templates.client.annotation.DataField; -import io.crysknife.ui.templates.client.annotation.EventHandler; -import io.crysknife.ui.templates.client.annotation.ForEvent; -import io.crysknife.ui.templates.client.annotation.Templated; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; import jakarta.inject.Named; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.DataField; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.EventHandler; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.ForEvent; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.Templated; @Dependent @Templated diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/glyph/LienzoGlyphRenderers.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/glyph/LienzoGlyphRenderers.java index 23e60f51422..56df516c497 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/glyph/LienzoGlyphRenderers.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/glyph/LienzoGlyphRenderers.java @@ -24,12 +24,12 @@ import java.util.List; import com.ait.lienzo.client.core.shape.Group; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.components.glyph.GlyphRenderer; import org.kie.workbench.common.stunner.core.definition.shape.Glyph; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelector.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelector.java index efa9f7cb0d9..28ae09cbd6c 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelector.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelector.java @@ -23,11 +23,11 @@ import java.util.Objects; import elemental2.dom.HTMLElement; -import io.crysknife.client.IsElement; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.IsElement; import org.uberfire.client.mvp.UberView; import org.uberfire.mvp.Command; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorItem.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorItem.java index aa5de834577..aede53d0883 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorItem.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorItem.java @@ -24,15 +24,15 @@ import elemental2.dom.HTMLAnchorElement; import elemental2.dom.HTMLElement; import elemental2.dom.HTMLLIElement; -import io.crysknife.client.IsElement; -import io.crysknife.ui.templates.client.annotation.DataField; -import io.crysknife.ui.templates.client.annotation.EventHandler; -import io.crysknife.ui.templates.client.annotation.ForEvent; -import io.crysknife.ui.templates.client.annotation.Templated; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; import jakarta.inject.Named; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.DataField; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.EventHandler; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.ForEvent; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.Templated; import org.uberfire.mvp.Command; @Templated diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorPresenter.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorPresenter.java index 87be94e4104..9d46820c37e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorPresenter.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorPresenter.java @@ -30,11 +30,11 @@ import com.ait.lienzo.tools.client.event.MouseEventUtil; import elemental2.dom.Element; import elemental2.dom.EventListener; -import io.crysknife.client.IsElement; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.event.Event; import jakarta.inject.Inject; import org.gwtproject.timer.client.Timer; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoCanvas; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoCanvasView; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoPanel; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorView.java index fa2858da413..d540e0f836e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorView.java @@ -26,17 +26,17 @@ import elemental2.dom.HTMLElement; import elemental2.dom.HTMLUListElement; import elemental2.dom.KeyboardEvent; -import io.crysknife.client.ManagedInstance; -import io.crysknife.ui.templates.client.annotation.DataField; -import io.crysknife.ui.templates.client.annotation.EventHandler; -import io.crysknife.ui.templates.client.annotation.ForEvent; -import io.crysknife.ui.templates.client.annotation.Templated; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; import jakarta.inject.Named; import org.jboss.errai.common.client.dom.DOMUtil; +import org.kie.j2cl.tools.di.core.ManagedInstance; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.DataField; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.EventHandler; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.ForEvent; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.Templated; import org.kie.workbench.common.stunner.core.client.i18n.ClientTranslationService; import org.kie.workbench.common.stunner.core.client.theme.StunnerTheme; import org.kie.workbench.common.stunner.core.i18n.CoreTranslationMessages; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/views/AlertView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/views/AlertView.java index 0ed4f4b9003..1ce3f4846ce 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/views/AlertView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/views/AlertView.java @@ -21,12 +21,12 @@ package org.kie.workbench.common.stunner.client.lienzo.components.views; import elemental2.dom.HTMLElement; -import io.crysknife.client.IsElement; -import io.crysknife.ui.templates.client.annotation.DataField; -import io.crysknife.ui.templates.client.annotation.Templated; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; import jakarta.inject.Named; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.DataField; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.Templated; @Templated @Dependent diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/views/LienzoCanvasNotificationView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/views/LienzoCanvasNotificationView.java index c63dc2f8296..2e33f5088d4 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/views/LienzoCanvasNotificationView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/components/views/LienzoCanvasNotificationView.java @@ -20,11 +20,11 @@ package org.kie.workbench.common.stunner.client.lienzo.components.views; -import io.crysknife.client.IsElement; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.core.client.components.views.FloatingView; @Dependent diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/resources/StunnerLienzoCoreResources.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/resources/StunnerLienzoCoreResources.java index 48e3a99b3f0..0e297ca308e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/resources/StunnerLienzoCoreResources.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/main/java/org/kie/workbench/common/stunner/client/lienzo/resources/StunnerLienzoCoreResources.java @@ -19,9 +19,9 @@ package org.kie.workbench.common.stunner.client.lienzo.resources; -import org.treblereel.j2cl.processors.annotations.GWT3Resource; -import org.treblereel.j2cl.processors.common.resources.ClientBundle; -import org.treblereel.j2cl.processors.common.resources.TextResource; +import org.kie.j2cl.tools.processors.annotations.GWT3Resource; +import org.kie.j2cl.tools.processors.common.resources.ClientBundle; +import org.kie.j2cl.tools.processors.common.resources.TextResource; @GWT3Resource public interface StunnerLienzoCoreResources extends ClientBundle { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/LienzoImageStripsTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/LienzoImageStripsTest.java index d322de0415a..dbb02d31994 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/LienzoImageStripsTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/LienzoImageStripsTest.java @@ -27,6 +27,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; import org.kie.workbench.common.stunner.core.client.shape.ImageStrip; import org.mockito.ArgumentCaptor; import org.mockito.Mock; @@ -50,7 +51,7 @@ public class LienzoImageStripsTest { private static final String STRIP_NAME = Object.class.getName(); @Mock - private org.treblereel.j2cl.processors.common.resources.ImageResource imageResource; + private ImageResource imageResource; @Mock private SafeUri safeUri; @@ -186,7 +187,7 @@ public String getClassName() { @Override - public org.treblereel.j2cl.processors.common.resources.ImageResource getImage() { + public ImageResource getImage() { return imageResource; } diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/glyph/LienzoImageStripGlyphRendererTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/glyph/LienzoImageStripGlyphRendererTest.java index ad77a5911b3..49d4a560ae5 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/glyph/LienzoImageStripGlyphRendererTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/glyph/LienzoImageStripGlyphRendererTest.java @@ -28,11 +28,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; import org.kie.workbench.common.stunner.core.client.shape.ImageStrip; import org.kie.workbench.common.stunner.core.client.shape.ImageStripGlyph; import org.kie.workbench.common.stunner.core.client.shape.ImageStripRegistry; import org.mockito.Mock; -import org.treblereel.j2cl.processors.common.resources.ImageResource; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.anyInt; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorPresenterTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorPresenterTest.java index 16bb839cc66..5564a1ed15c 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorPresenterTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorPresenterTest.java @@ -32,13 +32,13 @@ import elemental2.dom.EventListener; import elemental2.dom.HTMLDivElement; import elemental2.dom.HTMLElement; -import io.crysknife.client.IsElement; -import io.crysknife.client.ManagedInstance; -import io.crysknife.ui.translation.client.TranslationService; import jakarta.enterprise.event.Event; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.core.ManagedInstance; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoCanvas; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoCanvasView; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoPanel; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorViewTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorViewTest.java index b4d3e67a7bd..05d22923020 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorViewTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-lienzo/src/test/java/org/kie/workbench/common/stunner/client/lienzo/components/mediators/ZoomLevelSelectorViewTest.java @@ -26,11 +26,11 @@ import elemental2.dom.HTMLLIElement; import elemental2.dom.HTMLUListElement; import elemental2.dom.KeyboardEvent; -import io.crysknife.client.ManagedInstance; -import io.crysknife.ui.translation.client.TranslationService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.api.SessionManager; import org.kie.workbench.common.stunner.core.client.i18n.ClientTranslationService; import org.kie.workbench.common.stunner.core.client.theme.StunnerColorTheme; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-shapes/kie-wb-common-stunner-shapes-client/src/main/java/org/kie/workbench/common/stunner/shapes/client/factory/PictureProvidersManager.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-shapes/kie-wb-common-stunner-shapes-client/src/main/java/org/kie/workbench/common/stunner/shapes/client/factory/PictureProvidersManager.java index 0504bbed1f0..2cbe969941f 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-shapes/kie-wb-common-stunner-shapes-client/src/main/java/org/kie/workbench/common/stunner/shapes/client/factory/PictureProvidersManager.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-shapes/kie-wb-common-stunner-shapes-client/src/main/java/org/kie/workbench/common/stunner/shapes/client/factory/PictureProvidersManager.java @@ -25,12 +25,12 @@ import java.util.logging.Level; import java.util.logging.Logger; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; import org.gwtproject.safehtml.shared.SafeUri; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.shapes.def.picture.PictureProvider; @Dependent diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/StunnerWidgetsEntryPoint.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/StunnerWidgetsEntryPoint.java index ff2846a33fa..bc0e1adeac0 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/StunnerWidgetsEntryPoint.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/StunnerWidgetsEntryPoint.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.client.widgets; -import io.crysknife.ui.translation.client.annotation.Bundle; +import org.kie.j2cl.tools.di.ui.translation.client.annotation.Bundle; @Bundle("resources/i18n/StunnerWidgetsConstants.properties") public class StunnerWidgetsEntryPoint { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/DOMGlyphRenderers.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/DOMGlyphRenderers.java index 6694c900f5f..bb3fdb0a104 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/DOMGlyphRenderers.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/DOMGlyphRenderers.java @@ -23,13 +23,13 @@ import java.util.ArrayList; import java.util.List; -import io.crysknife.client.IsElement; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.components.glyph.DOMGlyphRenderer; import org.kie.workbench.common.stunner.core.client.components.glyph.GlyphRenderer; import org.kie.workbench.common.stunner.core.definition.shape.Glyph; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ElementShapeGlyphRenderer.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ElementShapeGlyphRenderer.java index e1341c9e394..d5eb83c8364 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ElementShapeGlyphRenderer.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ElementShapeGlyphRenderer.java @@ -22,11 +22,11 @@ import java.util.function.Supplier; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.client.lienzo.components.glyph.LienzoGlyphRenderer; import org.kie.workbench.common.stunner.core.client.components.views.WidgetElementRendererView; import org.kie.workbench.common.stunner.core.definition.shape.ShapeGlyph; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ImageElementGlyphRenderer.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ImageElementGlyphRenderer.java index ec4fa65e669..757c524b7ec 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ImageElementGlyphRenderer.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ImageElementGlyphRenderer.java @@ -22,12 +22,12 @@ import java.util.function.Supplier; -import io.crysknife.client.IsElement; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.components.glyph.DOMGlyphRenderer; import org.kie.workbench.common.stunner.core.client.components.views.ImageElementRendererView; import org.kie.workbench.common.stunner.core.client.shape.ImageDataUriGlyph; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ImageStripDOMGlyphRenderer.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ImageStripDOMGlyphRenderer.java index 911355bd37f..5406d2f98a7 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ImageStripDOMGlyphRenderer.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ImageStripDOMGlyphRenderer.java @@ -24,12 +24,12 @@ import elemental2.dom.DomGlobal; import elemental2.dom.HTMLDivElement; -import io.crysknife.client.IsElement; -import io.crysknife.client.ManagedInstance; -import io.crysknife.ui.common.client.injectors.StyleInjector; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.core.ManagedInstance; +import org.kie.j2cl.tools.processors.common.injectors.StyleInjector; import org.kie.workbench.common.stunner.core.client.components.glyph.DOMGlyphRenderer; import org.kie.workbench.common.stunner.core.client.components.views.WidgetElementRendererView; import org.kie.workbench.common.stunner.core.client.shape.ImageStrip; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/LienzoElementGlyphRenderer.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/LienzoElementGlyphRenderer.java index 9d9d7945dfe..3b93c8ac997 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/LienzoElementGlyphRenderer.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/LienzoElementGlyphRenderer.java @@ -24,7 +24,7 @@ import com.ait.lienzo.client.core.shape.Group; import com.ait.lienzo.client.core.shape.Layer; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.client.lienzo.components.glyph.LienzoGlyphRenderer; import org.kie.workbench.common.stunner.client.lienzo.components.views.LienzoPanelWidget; import org.kie.workbench.common.stunner.core.client.components.glyph.DOMGlyphRenderer; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/SvgElementGlyphRenderer.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/SvgElementGlyphRenderer.java index 9231f7fed17..18089ee38d9 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/SvgElementGlyphRenderer.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/SvgElementGlyphRenderer.java @@ -22,12 +22,12 @@ import java.util.function.Supplier; -import io.crysknife.client.IsElement; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.components.glyph.DOMGlyphRenderer; import org.kie.workbench.common.stunner.core.client.components.views.ImageElementRendererView; import org.kie.workbench.common.stunner.core.client.shape.SvgDataUriGlyph; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/editor/PreviewWindow.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/editor/PreviewWindow.java index 9b8d0325426..963298b9d49 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/editor/PreviewWindow.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/editor/PreviewWindow.java @@ -23,13 +23,13 @@ import elemental2.dom.CSSProperties; import elemental2.dom.CSSStyleDeclaration; import elemental2.dom.DomGlobal; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; import org.gwtbootstrap3.extras.animate.client.ui.Animate; import org.gwtbootstrap3.extras.animate.client.ui.constants.Animation; import org.gwtproject.timer.client.Timer; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.client.lienzo.components.mediators.preview.TogglePreviewEvent; import org.kie.workbench.common.stunner.client.widgets.canvas.PreviewLienzoPanel; import org.kie.workbench.common.stunner.client.widgets.presenters.session.SessionDiagramPreview; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/editor/StunnerEditor.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/editor/StunnerEditor.java index b6aaa8a560e..214ca215fa2 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/editor/StunnerEditor.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/editor/StunnerEditor.java @@ -25,14 +25,15 @@ import com.ait.lienzo.client.core.types.JsCanvas; import com.ait.lienzo.client.widget.panel.LienzoBoundsPanel; +import com.ait.lienzo.client.widget.panel.impl.ScrollablePanel; import elemental2.dom.CSSStyleDeclaration; import elemental2.dom.DomGlobal; import elemental2.dom.HTMLDivElement; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; import jsinterop.base.Js; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoCanvas; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoPanel; import org.kie.workbench.common.stunner.client.lienzo.util.StunnerStateApplier; @@ -331,10 +332,10 @@ public void addError(String message) { } public void clearAlerts() { - hasErrors = false; - if (null != alertsControl) { - alertsControl.clear(); - } + hasErrors = false; + if (null != alertsControl) { + alertsControl.clear(); + } } private String buildErrorMessage(ClientRuntimeError error, Throwable throwable, String errorTitle) { @@ -351,6 +352,25 @@ private String buildErrorMessage(ClientRuntimeError error, Throwable throwable, return message; } + public void setScrollbarColors() { + if (null != getSession()) { + LienzoCanvas canvas = (LienzoCanvas) getSession().getCanvasHandler().getCanvas(); + LienzoPanel panel = (LienzoPanel) canvas.getView().getPanel(); + LienzoBoundsPanel lienzoPanel = panel.getView(); + + ((ScrollablePanel) lienzoPanel).setScrollbarColors(StunnerTheme.getTheme().getScrollbarColor(), + StunnerTheme.getTheme().getScrollbarBackgroundColor()); + } + } + + public void setCanvasBackgroundColor() { + if (null != getSession()) { + LienzoCanvas canvas = (LienzoCanvas) getSession().getCanvasHandler().getCanvas(); + + canvas.setBackgroundColor(StunnerTheme.getTheme().getCanvasBackgroundColor()); + } + } + @PreDestroy public void destroy() { close(); diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/inlineeditor/AbstractInlineTextEditorBoxView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/inlineeditor/AbstractInlineTextEditorBoxView.java index f669a09e9a7..7b4a81c1ed6 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/inlineeditor/AbstractInlineTextEditorBoxView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/inlineeditor/AbstractInlineTextEditorBoxView.java @@ -21,11 +21,11 @@ package org.kie.workbench.common.stunner.client.widgets.inlineeditor; import elemental2.dom.HTMLDivElement; -import io.crysknife.client.IsElement; -import io.crysknife.ui.templates.client.annotation.DataField; -import io.crysknife.ui.translation.client.TranslationService; import jakarta.inject.Inject; import org.gwtproject.core.client.Scheduler; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.DataField; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.uberfire.mvp.Command; public abstract class AbstractInlineTextEditorBoxView implements IsElement { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/inlineeditor/InlineTextEditorBoxViewImpl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/inlineeditor/InlineTextEditorBoxViewImpl.java index dc4354ab6fa..de642f26222 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/inlineeditor/InlineTextEditorBoxViewImpl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/inlineeditor/InlineTextEditorBoxViewImpl.java @@ -26,17 +26,17 @@ import elemental2.dom.HTMLDivElement; import elemental2.dom.HTMLElement; import elemental2.dom.KeyboardEvent; -import io.crysknife.client.IsElement; -import io.crysknife.ui.templates.client.annotation.DataField; -import io.crysknife.ui.templates.client.annotation.EventHandler; -import io.crysknife.ui.templates.client.annotation.ForEvent; -import io.crysknife.ui.templates.client.annotation.Templated; -import io.crysknife.ui.translation.client.TranslationService; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; import jsinterop.base.Js; import org.gwtproject.core.client.Scheduler; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.DataField; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.EventHandler; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.ForEvent; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.Templated; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.client.widgets.resources.i18n.StunnerWidgetsConstants; import org.kie.workbench.common.stunner.core.client.canvas.controls.inlineeditor.InlineTextEditorBox; import org.uberfire.mvp.Command; @@ -47,7 +47,7 @@ public class InlineTextEditorBoxViewImpl extends AbstractInlineTextEditorBoxView implements InlineEditorBoxView, - IsElement { + IsElement { @Inject @DataField diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/Editor.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/Editor.java index 29707ed37db..24a53689d40 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/Editor.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/Editor.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.client.widgets.presenters; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.core.client.canvas.CanvasHandler; import org.kie.workbench.common.stunner.core.client.command.CanvasCommandManager; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/Viewer.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/Viewer.java index b83594854fe..db103a74c9b 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/Viewer.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/Viewer.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.client.widgets.presenters; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.core.client.service.ClientRuntimeError; /** diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/canvas/CanvasViewer.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/canvas/CanvasViewer.java index beefc3b2b20..db5cf026098 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/canvas/CanvasViewer.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/canvas/CanvasViewer.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.client.widgets.presenters.canvas; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.client.widgets.presenters.Viewer; import org.kie.workbench.common.stunner.core.client.canvas.Canvas; import org.kie.workbench.common.stunner.core.client.canvas.CanvasHandler; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DefaultDiagramEditor.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DefaultDiagramEditor.java index 48598326feb..18e5bec2f7e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DefaultDiagramEditor.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DefaultDiagramEditor.java @@ -23,11 +23,11 @@ import java.lang.annotation.Annotation; import java.util.Arrays; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Typed; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.client.widgets.presenters.diagram.DiagramEditor; import org.kie.workbench.common.stunner.client.widgets.presenters.diagram.DiagramViewer; import org.kie.workbench.common.stunner.client.widgets.views.WidgetWrapperView; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DefaultDiagramViewer.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DefaultDiagramViewer.java index 02ecc272b20..98b84b5aa74 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DefaultDiagramViewer.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DefaultDiagramViewer.java @@ -25,10 +25,10 @@ import java.util.Collections; import elemental2.dom.CSSProperties; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoCanvas; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoCanvasView; import org.kie.workbench.common.stunner.client.widgets.views.WidgetWrapperView; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/SessionEditor.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/SessionEditor.java index 69a7349e4f0..f18b5b949ec 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/SessionEditor.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/SessionEditor.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.client.widgets.presenters.session; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.client.widgets.presenters.Editor; import org.kie.workbench.common.stunner.core.client.canvas.CanvasHandler; import org.kie.workbench.common.stunner.core.client.session.ClientSession; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/SessionPresenter.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/SessionPresenter.java index a10b3d1da7c..e5f1202168f 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/SessionPresenter.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/SessionPresenter.java @@ -22,7 +22,7 @@ import java.util.function.Predicate; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.client.widgets.notification.Notification; import org.kie.workbench.common.stunner.client.widgets.presenters.Viewer; import org.kie.workbench.common.stunner.client.widgets.presenters.diagram.DiagramViewer; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/SessionViewer.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/SessionViewer.java index c77a7386982..4d6c7b193d5 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/SessionViewer.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/SessionViewer.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.client.widgets.presenters.session; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.client.widgets.presenters.canvas.CanvasViewer; import org.kie.workbench.common.stunner.client.widgets.presenters.diagram.DiagramViewer; import org.kie.workbench.common.stunner.core.client.canvas.CanvasHandler; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/AbstractSessionViewer.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/AbstractSessionViewer.java index 3813befdedc..67f8fd132de 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/AbstractSessionViewer.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/AbstractSessionViewer.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.client.widgets.presenters.session.impl; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.client.widgets.presenters.diagram.DiagramViewer; import org.kie.workbench.common.stunner.client.widgets.presenters.session.SessionViewer; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvas; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionPresenterView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionPresenterView.java index 387a603274d..8613e5ac4e6 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionPresenterView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionPresenterView.java @@ -23,12 +23,12 @@ import elemental2.dom.CSSStyleDeclaration; import elemental2.dom.HTMLDivElement; import elemental2.dom.HTMLElement; -import io.crysknife.client.IsElement; -import io.crysknife.ui.templates.client.annotation.DataField; -import io.crysknife.ui.templates.client.annotation.Templated; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.DataField; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.Templated; import org.kie.workbench.common.stunner.client.widgets.presenters.session.SessionPresenter; import org.kie.workbench.common.stunner.core.client.canvas.event.selection.CanvasFocusedShapeEvent; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionPreviewImpl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionPreviewImpl.java index f22b7d2d723..e35f1a12dea 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionPreviewImpl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionPreviewImpl.java @@ -24,7 +24,6 @@ import java.util.Objects; import java.util.function.Predicate; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.event.Observes; @@ -32,6 +31,7 @@ import jakarta.enterprise.inject.Default; import jakarta.enterprise.inject.Typed; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoCanvasDecoratorFactory; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoCanvasView; import org.kie.workbench.common.stunner.client.lienzo.canvas.wires.WiresCanvas; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/resources/i18n/StunnerWidgetsConstants.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/resources/i18n/StunnerWidgetsConstants.java index 741218335cc..2ce01cb4ffa 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/resources/i18n/StunnerWidgetsConstants.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/resources/i18n/StunnerWidgetsConstants.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.client.widgets.resources.i18n; -import io.crysknife.ui.translation.client.annotation.TranslationKey; +import org.kie.j2cl.tools.di.ui.translation.client.annotation.TranslationKey; public interface StunnerWidgetsConstants { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/SelectorView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/SelectorView.java index f2d7cc4a1f5..3e9d254d4df 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/SelectorView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/SelectorView.java @@ -24,14 +24,14 @@ import elemental2.dom.HTMLDivElement; import elemental2.dom.HTMLOptionElement; import elemental2.dom.HTMLSelectElement; -import io.crysknife.client.IsElement; -import io.crysknife.ui.templates.client.annotation.DataField; -import io.crysknife.ui.templates.client.annotation.EventHandler; -import io.crysknife.ui.templates.client.annotation.ForEvent; -import io.crysknife.ui.templates.client.annotation.Templated; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.DataField; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.EventHandler; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.ForEvent; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.Templated; @Dependent @Templated diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/WidgetElementRendererViewImpl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/WidgetElementRendererViewImpl.java index 433dd785bd1..80ed617f99e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/WidgetElementRendererViewImpl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/WidgetElementRendererViewImpl.java @@ -22,17 +22,17 @@ import elemental2.dom.HTMLDivElement; import elemental2.dom.HTMLElement; -import io.crysknife.client.IsElement; -import io.crysknife.ui.templates.client.annotation.DataField; -import io.crysknife.ui.templates.client.annotation.Templated; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.DataField; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.Templated; import org.kie.workbench.common.stunner.core.client.components.views.WidgetElementRendererView; @Templated @Dependent public class WidgetElementRendererViewImpl implements WidgetElementRendererView, - IsElement { + IsElement { @Inject @DataField diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/WidgetWrapperView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/WidgetWrapperView.java index 578c5ff43e5..5e4c2e8184e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/WidgetWrapperView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/WidgetWrapperView.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.client.widgets.views; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; /** * Just a simple view that wraps any widget. diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/WidgetWrapperViewImpl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/WidgetWrapperViewImpl.java index 0d60b530641..96dcd9860c9 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/WidgetWrapperViewImpl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/WidgetWrapperViewImpl.java @@ -23,10 +23,10 @@ import elemental2.dom.DomGlobal; import elemental2.dom.HTMLDivElement; import elemental2.dom.HTMLElement; -import io.crysknife.client.IsElement; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.Dependent; import jsinterop.base.Js; +import org.kie.j2cl.tools.di.core.IsElement; import static org.jboss.errai.common.client.dom.DOMUtil.removeAllChildren; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/session/ScreenErrorView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/session/ScreenErrorView.java index 8c7a15ada61..e000f7db4a0 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/session/ScreenErrorView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/session/ScreenErrorView.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.client.widgets.views.session; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.core.client.service.ClientRuntimeError; public interface ScreenErrorView extends IsElement { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/session/ScreenErrorViewImpl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/session/ScreenErrorViewImpl.java index 08458743e0f..c861a874876 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/session/ScreenErrorViewImpl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/main/java/org/kie/workbench/common/stunner/client/widgets/views/session/ScreenErrorViewImpl.java @@ -21,17 +21,17 @@ package org.kie.workbench.common.stunner.client.widgets.views.session; import elemental2.dom.HTMLLabelElement; -import io.crysknife.client.IsElement; -import io.crysknife.ui.templates.client.annotation.DataField; -import io.crysknife.ui.templates.client.annotation.Templated; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.DataField; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.Templated; import org.kie.workbench.common.stunner.core.client.service.ClientRuntimeError; @Dependent @Templated public class ScreenErrorViewImpl implements ScreenErrorView, - IsElement { + IsElement { @Inject @DataField diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/DOMGlyphRenderersTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/DOMGlyphRenderersTest.java index ac0a2e7eb38..cbbe4722923 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/DOMGlyphRenderersTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/DOMGlyphRenderersTest.java @@ -20,10 +20,10 @@ package org.kie.workbench.common.stunner.client.widgets.components.glyph; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.components.glyph.DOMGlyphRenderer; import org.kie.workbench.common.stunner.core.definition.shape.Glyph; import org.kie.workbench.common.stunner.core.definition.shape.ShapeGlyph; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ImageStripDOMGlyphRendererTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ImageStripDOMGlyphRendererTest.java index 47472728220..1191422c218 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ImageStripDOMGlyphRendererTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/components/glyph/ImageStripDOMGlyphRendererTest.java @@ -23,11 +23,12 @@ import java.util.function.BiFunction; import elemental2.dom.HTMLDivElement; -import io.crysknife.client.IsElement; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.core.ManagedInstance; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; import org.kie.workbench.common.stunner.core.client.components.views.WidgetElementRendererView; import org.kie.workbench.common.stunner.core.client.shape.ImageStrip; import org.kie.workbench.common.stunner.core.client.shape.ImageStripGlyph; @@ -35,7 +36,6 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import org.treblereel.j2cl.processors.common.resources.ImageResource; import org.uberfire.stubs.ManagedInstanceStub; import static org.junit.Assert.assertEquals; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/editor/StunnerEditorTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/editor/StunnerEditorTest.java index a63276f2d88..2cb34ad202e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/editor/StunnerEditorTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/editor/StunnerEditorTest.java @@ -24,10 +24,11 @@ import com.ait.lienzo.client.core.shape.Layer; import com.ait.lienzo.client.widget.panel.LienzoBoundsPanel; -import io.crysknife.client.ManagedInstance; +import com.ait.lienzo.client.widget.panel.impl.ScrollablePanel; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoCanvas; import org.kie.workbench.common.stunner.client.lienzo.canvas.LienzoPanel; import org.kie.workbench.common.stunner.client.lienzo.canvas.wires.WiresCanvasView; @@ -61,6 +62,7 @@ import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -241,4 +243,42 @@ public void testGetSessionWhenPresenterDisplayerIsNull() { doCallRealMethod().when(sessionEditorPresenter).getInstance(); assertNull(sessionEditorPresenter.getInstance()); } + + @Test + public void testSetCanvasBackgroundColor() { + tested.setReadOnly(true); + openSuccess(); + tested.setCanvasBackgroundColor(); + + verify(canvas, times(1)).setBackgroundColor(any()); + } + + @Test + public void testSetCanvasBackgroundColorNoSession() { + tested.setCanvasBackgroundColor(); + + verify(canvas, times(0)).setBackgroundColor(any()); + } + + @Test + public void testSetScrollbarColors() { + ScrollablePanel scrollablePanel = mock(ScrollablePanel.class); + when(panel.getView()).thenReturn(scrollablePanel); + + tested.setReadOnly(true); + openSuccess(); + tested.setScrollbarColors(); + + verify(scrollablePanel, times(1)).setScrollbarColors(any(), any()); + } + + @Test + public void testSetScrollbarColorsNoSession() { + ScrollablePanel scrollablePanel = mock(ScrollablePanel.class); + lenient().when(panel.getView()).thenReturn(scrollablePanel); + + tested.setScrollbarColors(); + + verify(scrollablePanel, times(0)).setScrollbarColors(any(), any()); + } } diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DiagramEditorTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DiagramEditorTest.java index c71558e1a7e..fb37b01589c 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DiagramEditorTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DiagramEditorTest.java @@ -23,10 +23,10 @@ import java.util.Iterator; import com.google.gwtmockito.GwtMockitoTestRunner; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.client.widgets.canvas.ScrollableLienzoPanel; import org.kie.workbench.common.stunner.client.widgets.presenters.AbstractCanvasHandlerViewerTest; import org.kie.workbench.common.stunner.client.widgets.presenters.diagram.DiagramViewer; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DiagramViewerTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DiagramViewerTest.java index e9e8ef21209..bd0b5196aae 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DiagramViewerTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/diagram/impl/DiagramViewerTest.java @@ -23,11 +23,11 @@ import java.util.Iterator; import com.google.gwtmockito.GwtMockitoTestRunner; -import io.crysknife.client.IsElement; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.client.widgets.canvas.ScrollableLienzoPanel; import org.kie.workbench.common.stunner.client.widgets.presenters.AbstractCanvasHandlerViewerTest; import org.kie.workbench.common.stunner.client.widgets.presenters.diagram.DiagramViewer; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionEditorTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionEditorTest.java index 5d76147806a..cdd560583c1 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionEditorTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionEditorTest.java @@ -22,10 +22,10 @@ import com.ait.lienzo.client.widget.panel.impl.ScrollablePanel; import com.google.gwtmockito.GwtMockitoTestRunner; -import io.crysknife.client.IsElement; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.client.widgets.canvas.ScrollableLienzoPanel; import org.kie.workbench.common.stunner.client.widgets.presenters.AbstractCanvasHandlerViewerTest; import org.kie.workbench.common.stunner.client.widgets.presenters.session.SessionViewer; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionPreviewImplTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionPreviewImplTest.java index 746d4658409..06ebf371a14 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionPreviewImplTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionPreviewImplTest.java @@ -25,10 +25,10 @@ import java.util.function.Supplier; import com.ait.lienzo.test.LienzoMockitoTestRunner; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.client.lienzo.canvas.wires.WiresCanvas; import org.kie.workbench.common.stunner.client.lienzo.canvas.wires.WiresLayer; import org.kie.workbench.common.stunner.client.widgets.canvas.PreviewLienzoPanel; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionViewerTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionViewerTest.java index b37158f9bc2..aaa4f484bc1 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionViewerTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/kie/workbench/common/stunner/client/widgets/presenters/session/impl/SessionViewerTest.java @@ -22,10 +22,10 @@ import com.ait.lienzo.client.widget.panel.impl.ScrollablePanel; import com.google.gwtmockito.GwtMockitoTestRunner; -import io.crysknife.client.IsElement; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.client.widgets.canvas.ScrollableLienzoPanel; import org.kie.workbench.common.stunner.client.widgets.presenters.AbstractCanvasHandlerViewerTest; import org.kie.workbench.common.stunner.client.widgets.presenters.session.SessionViewer; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/uberfire/stubs/ManagedInstanceStub.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/uberfire/stubs/ManagedInstanceStub.java index 829dc9a4f75..cca4e4722bb 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/uberfire/stubs/ManagedInstanceStub.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-client/kie-wb-common-stunner-widgets/src/test/java/org/uberfire/stubs/ManagedInstanceStub.java @@ -24,7 +24,7 @@ import java.util.Arrays; import java.util.Iterator; -import io.crysknife.client.ManagedInstance; +import org.kie.j2cl.tools.di.core.ManagedInstance; public class ManagedInstanceStub implements ManagedInstance { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-api/kie-wb-common-stunner-client-api/src/main/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesEntryPoint.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-api/kie-wb-common-stunner-client-api/src/main/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesEntryPoint.java index 96ed4f008c8..089a4c4c170 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-api/kie-wb-common-stunner-client-api/src/main/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesEntryPoint.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-api/kie-wb-common-stunner-client-api/src/main/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesEntryPoint.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.core.client.preferences; -import io.crysknife.ui.translation.client.annotation.Bundle; +import org.kie.j2cl.tools.di.ui.translation.client.annotation.Bundle; @Bundle("resources/i18n/StunnerPreferencesConstants.properties") public class StunnerPreferencesEntryPoint { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/pom.xml b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/pom.xml index b12d86f9523..402ff280b66 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/pom.xml +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/pom.xml @@ -112,7 +112,7 @@ lienzo-core - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors processors provided @@ -148,21 +148,4 @@ - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - - - - - diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/StunnerCoreEntryPoint.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/StunnerCoreEntryPoint.java index a717c4a7d75..453050f2abe 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/StunnerCoreEntryPoint.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/StunnerCoreEntryPoint.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.core; -import io.crysknife.ui.translation.client.annotation.Bundle; +import org.kie.j2cl.tools.di.ui.translation.client.annotation.Bundle; @Bundle("resources/i18n/StunnerCoreConstants.properties") public class StunnerCoreEntryPoint { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ClientDefinitionManager.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ClientDefinitionManager.java index 76a8b659a5f..554e9b0414b 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ClientDefinitionManager.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ClientDefinitionManager.java @@ -22,12 +22,12 @@ import java.util.Collection; -import io.crysknife.annotation.CircularDependency; -import io.crysknife.client.BeanManager; -import io.crysknife.client.SyncBeanDef; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.annotation.CircularDependency; +import org.kie.j2cl.tools.di.core.BeanManager; +import org.kie.j2cl.tools.di.core.SyncBeanDef; import org.kie.workbench.common.stunner.core.api.AbstractDefinitionManager; import org.kie.workbench.common.stunner.core.definition.adapter.AdapterManager; import org.kie.workbench.common.stunner.core.definition.adapter.DefinitionAdapter; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ClientFactoryManager.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ClientFactoryManager.java index 3c3426b9d48..f584ed8bff8 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ClientFactoryManager.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ClientFactoryManager.java @@ -20,10 +20,10 @@ package org.kie.workbench.common.stunner.core.client.api; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.api.AbstractFactoryManager; import org.kie.workbench.common.stunner.core.api.DefinitionManager; import org.kie.workbench.common.stunner.core.api.FactoryManager; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ClientProfileManager.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ClientProfileManager.java index 20bd1b7dbc9..368ddaad2f6 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ClientProfileManager.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ClientProfileManager.java @@ -23,11 +23,11 @@ import java.lang.annotation.Annotation; import java.util.function.Function; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.profile.AbstractProfileManager; import org.kie.workbench.common.stunner.core.profile.Profile; import org.kie.workbench.common.stunner.core.util.DefinitionUtils; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/GlobalSessionManager.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/GlobalSessionManager.java index 3fef122cf59..4ac80a1eab9 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/GlobalSessionManager.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/GlobalSessionManager.java @@ -25,11 +25,11 @@ import java.util.function.Consumer; import java.util.function.Function; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Event; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.service.ClientRuntimeError; import org.kie.workbench.common.stunner.core.client.session.ClientSession; import org.kie.workbench.common.stunner.core.client.session.event.OnSessionErrorEvent; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsCanvasWrapper.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsCanvasWrapper.java index 5836d88050c..3cd9e8a08cf 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsCanvasWrapper.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsCanvasWrapper.java @@ -31,7 +31,7 @@ import elemental2.dom.DomGlobal; import elemental2.dom.HTMLCanvasElement; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsStunnerEditor.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsStunnerEditor.java index 2a2c3754dca..b4f5c6b4055 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsStunnerEditor.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsStunnerEditor.java @@ -22,8 +22,8 @@ import elemental2.core.Reflect; import elemental2.dom.DomGlobal; import jsinterop.base.Js; +import org.kie.j2cl.tools.utils.GwtIncompatible; import org.kie.workbench.common.stunner.core.api.JsDefinitionManager; -import org.treblereel.gwt.utils.GwtIncompatible; public class JsStunnerEditor { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsStunnerSession.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsStunnerSession.java index 44f53a463a6..62033a40f36 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsStunnerSession.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsStunnerSession.java @@ -25,6 +25,7 @@ import jsinterop.annotations.JsIgnore; import jsinterop.annotations.JsType; import jsinterop.base.Js; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.command.CanvasCommand; import org.kie.workbench.common.stunner.core.client.command.CanvasCommandManager; @@ -39,7 +40,6 @@ import org.kie.workbench.common.stunner.core.graph.content.definition.Definition; import org.kie.workbench.common.stunner.core.graph.content.view.View; import org.kie.workbench.common.stunner.core.graph.processing.index.Index; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsWindow.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsWindow.java index 1509548ca53..c5776e59d1e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsWindow.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/JsWindow.java @@ -22,7 +22,7 @@ import elemental2.core.Reflect; import elemental2.dom.DomGlobal; import jsinterop.base.Js; -import org.treblereel.gwt.utils.GwtIncompatible; +import org.kie.j2cl.tools.utils.GwtIncompatible; public class JsWindow { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ShapeManagerImpl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ShapeManagerImpl.java index 722984bca5c..83ecc812a8e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ShapeManagerImpl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/api/ShapeManagerImpl.java @@ -25,11 +25,11 @@ import java.util.List; import java.util.Objects; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.ShapeSet; import org.kie.workbench.common.stunner.core.client.ShapeSetThumbProvider; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/AbstractCanvas.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/AbstractCanvas.java index 6426bc460d5..1623351f31f 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/AbstractCanvas.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/AbstractCanvas.java @@ -27,8 +27,8 @@ import java.util.Map; import java.util.stream.Collectors; -import io.crysknife.client.IsElement; import jakarta.enterprise.event.Event; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.core.client.canvas.event.CanvasClearEvent; import org.kie.workbench.common.stunner.core.client.canvas.event.CanvasDrawnEvent; import org.kie.workbench.common.stunner.core.client.canvas.event.CanvasFocusedEvent; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/CanvasPanel.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/CanvasPanel.java index fa98babb515..3434cc2f3aa 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/CanvasPanel.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/CanvasPanel.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.core.client.canvas; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.core.graph.content.Bounds; public interface CanvasPanel extends IsElement { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/DeleteNodeConfirmationImpl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/DeleteNodeConfirmationImpl.java index ba191281964..435db1064b4 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/DeleteNodeConfirmationImpl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/DeleteNodeConfirmationImpl.java @@ -27,13 +27,13 @@ import java.util.Optional; import java.util.stream.StreamSupport; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Default; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.api.SessionManager; import org.kie.workbench.common.stunner.core.client.canvas.controls.DeleteNodeConfirmation; import org.kie.workbench.common.stunner.core.client.i18n.ClientTranslationService; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneCanvasNodeCommand.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneCanvasNodeCommand.java index 520afc9563f..edb46cc6d80 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneCanvasNodeCommand.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneCanvasNodeCommand.java @@ -23,7 +23,7 @@ import java.util.ArrayList; import java.util.List; -import io.crysknife.client.ManagedInstance; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.command.CanvasViolation; import org.kie.workbench.common.stunner.core.command.CommandResult; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneNodeCommand.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneNodeCommand.java index 75dd32b105d..ed9b76451a3 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneNodeCommand.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneNodeCommand.java @@ -23,7 +23,7 @@ import java.util.Optional; import java.util.function.Consumer; -import io.crysknife.client.ManagedInstance; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.command.CanvasViolation; import org.kie.workbench.common.stunner.core.command.Command; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/command/DefaultCanvasCommandFactory.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/command/DefaultCanvasCommandFactory.java index 95ed4ac9521..08639a28958 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/command/DefaultCanvasCommandFactory.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/command/DefaultCanvasCommandFactory.java @@ -23,7 +23,7 @@ import java.util.Collection; import java.util.function.Consumer; -import io.crysknife.client.ManagedInstance; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.command.CanvasCommand; import org.kie.workbench.common.stunner.core.client.command.CanvasCommandFactory; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/actions/TextPropertyProviderFactoryImpl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/actions/TextPropertyProviderFactoryImpl.java index c71c555b56f..881c6d8a31e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/actions/TextPropertyProviderFactoryImpl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/actions/TextPropertyProviderFactoryImpl.java @@ -22,9 +22,9 @@ import java.util.ArrayList; import java.util.List; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.graph.Element; import org.kie.workbench.common.stunner.core.graph.content.definition.Definition; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/AbstractCanvasInlineTextEditorControl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/AbstractCanvasInlineTextEditorControl.java index cc8614f1e8c..ac2c4ba2dc9 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/AbstractCanvasInlineTextEditorControl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/AbstractCanvasInlineTextEditorControl.java @@ -23,10 +23,10 @@ import elemental2.dom.DomGlobal; import elemental2.dom.Event; import elemental2.dom.HTMLElement; -import io.crysknife.client.IsElement; import jakarta.enterprise.event.Observes; import org.gwtproject.core.client.Scheduler; import org.gwtproject.touch.client.Point; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvas; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.canvas.Canvas; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/CanvasInlineTextEditorControl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/CanvasInlineTextEditorControl.java index bd2ee06a1bc..8023f15c840 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/CanvasInlineTextEditorControl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/CanvasInlineTextEditorControl.java @@ -20,11 +20,11 @@ package org.kie.workbench.common.stunner.core.client.canvas.controls.inlineeditor; -import io.crysknife.client.IsElement; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Default; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.components.views.FloatingView; import org.kie.workbench.common.stunner.core.graph.Element; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/FloatingWidgetView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/FloatingWidgetView.java index 3486da8c4e5..d032bbc5059 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/FloatingWidgetView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/FloatingWidgetView.java @@ -24,10 +24,10 @@ import elemental2.dom.CSSProperties; import elemental2.dom.DomGlobal; -import io.crysknife.client.IsElement; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Typed; import org.gwtproject.timer.client.Timer; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.core.client.components.views.FloatingView; import org.uberfire.mvp.Command; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/FlowPanel.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/FlowPanel.java index 252a9f33348..7f8274dbb8c 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/FlowPanel.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/FlowPanel.java @@ -6,7 +6,7 @@ import elemental2.dom.DomGlobal; import elemental2.dom.HTMLDivElement; import elemental2.dom.HTMLElement; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; public class FlowPanel implements IsElement { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/TextEditorBox.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/TextEditorBox.java index 09509a25228..2ee0e326394 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/TextEditorBox.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/inlineeditor/TextEditorBox.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.core.client.canvas.controls.inlineeditor; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.core.client.canvas.CanvasHandler; import org.kie.workbench.common.stunner.core.client.command.RequiresCommandManager; import org.kie.workbench.common.stunner.core.graph.Element; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/toolbox/DefaultToolboxControl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/toolbox/DefaultToolboxControl.java index 981d5ca24db..927f1c47391 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/toolbox/DefaultToolboxControl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/controls/toolbox/DefaultToolboxControl.java @@ -23,12 +23,12 @@ import java.util.Arrays; import java.util.List; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Default; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.components.toolbox.actions.ActionsToolboxFactory; import org.kie.workbench.common.stunner.core.client.components.toolbox.actions.CommonActionsToolbox; import org.kie.workbench.common.stunner.core.client.components.toolbox.actions.FlowActionsToolbox; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/resources/StunnerClientCommonConstants.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/resources/StunnerClientCommonConstants.java index b4d9002ee70..2892269ec13 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/resources/StunnerClientCommonConstants.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/canvas/resources/StunnerClientCommonConstants.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.core.client.canvas.resources; -import io.crysknife.ui.translation.client.annotation.TranslationKey; +import org.kie.j2cl.tools.di.ui.translation.client.annotation.TranslationKey; public class StunnerClientCommonConstants { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/command/ApplicationCommandManager.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/command/ApplicationCommandManager.java index ae751c8e3a4..71ab6f1f0bf 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/command/ApplicationCommandManager.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/command/ApplicationCommandManager.java @@ -25,7 +25,6 @@ import java.util.function.Consumer; import java.util.function.Supplier; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.ApplicationScoped; @@ -33,6 +32,7 @@ import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Typed; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.api.SessionManager; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.service.ClientRuntimeError; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/glyph/DOMGlyphRenderer.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/glyph/DOMGlyphRenderer.java index a78889791c4..e21b2434a5a 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/glyph/DOMGlyphRenderer.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/glyph/DOMGlyphRenderer.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.core.client.components.glyph; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.core.definition.shape.Glyph; /** diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/proxies/ElementProxy.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/proxies/ElementProxy.java index e7c3f23c969..ad4c62028f5 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/proxies/ElementProxy.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/proxies/ElementProxy.java @@ -23,12 +23,12 @@ import java.lang.annotation.Annotation; import java.util.function.Supplier; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.event.Event; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; import org.gwtproject.timer.client.Timer; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.api.SessionManager; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.canvas.Canvas; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/CommonActionsToolboxFactory.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/CommonActionsToolboxFactory.java index 23273375fad..c129850e8dd 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/CommonActionsToolboxFactory.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/CommonActionsToolboxFactory.java @@ -25,12 +25,12 @@ import java.util.Set; import java.util.function.Supplier; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Default; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.command.CanvasCommandFactory; import org.kie.workbench.common.stunner.core.client.command.CanvasCommandManager; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/CreateNodeToolboxAction.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/CreateNodeToolboxAction.java index 3a3a300ded0..b59813bf5bb 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/CreateNodeToolboxAction.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/CreateNodeToolboxAction.java @@ -22,12 +22,12 @@ import java.lang.annotation.Annotation; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Default; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.api.ClientFactoryManager; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.canvas.util.CanvasLayoutUtils; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/DeleteNodeToolboxAction.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/DeleteNodeToolboxAction.java index 283b7c9c276..2b54fb0b2fc 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/DeleteNodeToolboxAction.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/DeleteNodeToolboxAction.java @@ -23,13 +23,13 @@ import java.lang.annotation.Annotation; import java.util.function.Predicate; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.event.Event; import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Default; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.canvas.command.DefaultCanvasCommandFactory; import org.kie.workbench.common.stunner.core.client.canvas.event.selection.CanvasClearSelectionEvent; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/FlowActionsToolboxFactory.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/FlowActionsToolboxFactory.java index e8fccec493d..23e7f5948d1 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/FlowActionsToolboxFactory.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/FlowActionsToolboxFactory.java @@ -27,11 +27,11 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.diagram.Diagram; import org.kie.workbench.common.stunner.core.diagram.Metadata; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/GeneralCreateNodeAction.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/GeneralCreateNodeAction.java index 4c76b6c37bc..bf531cc4eb9 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/GeneralCreateNodeAction.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/GeneralCreateNodeAction.java @@ -23,13 +23,13 @@ import java.lang.annotation.Annotation; import java.util.concurrent.atomic.AtomicBoolean; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.event.Event; import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Default; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.api.ClientFactoryManager; import org.kie.workbench.common.stunner.core.client.api.JsWindow; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/GroupActionsToolboxFactory.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/GroupActionsToolboxFactory.java index 7721d3c7246..29b1c838ede 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/GroupActionsToolboxFactory.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/GroupActionsToolboxFactory.java @@ -27,11 +27,11 @@ import java.util.Set; import java.util.function.Predicate; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.components.toolbox.Toolbox; import org.kie.workbench.common.stunner.core.diagram.Diagram; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/MorphActionsToolboxFactory.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/MorphActionsToolboxFactory.java index 385c3d62035..ee2573513a0 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/MorphActionsToolboxFactory.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/MorphActionsToolboxFactory.java @@ -28,11 +28,11 @@ import java.util.function.Predicate; import java.util.function.Supplier; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.api.DefinitionManager; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.definition.adapter.MorphAdapter; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/ToolboxDomainLookups.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/ToolboxDomainLookups.java index ed89f520228..47ef7155aec 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/ToolboxDomainLookups.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/ToolboxDomainLookups.java @@ -23,10 +23,10 @@ import java.util.HashMap; import java.util.Map; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.lookup.domain.CommonDomainLookups; @ApplicationScoped diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/views/FloatingWidgetView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/views/FloatingWidgetView.java index b561c84de40..c19aa37462e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/views/FloatingWidgetView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/views/FloatingWidgetView.java @@ -25,9 +25,9 @@ import elemental2.dom.DomGlobal; import elemental2.dom.HTMLDivElement; import elemental2.dom.HTMLElement; -import io.crysknife.client.IsElement; import jakarta.enterprise.context.Dependent; import org.gwtproject.timer.client.Timer; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.core.client.shape.view.event.NativeHandler; import org.kie.workbench.common.stunner.core.client.shape.view.event.NativeHandlerRegistration; import org.uberfire.mvp.Command; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/views/ImageElementRendererView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/views/ImageElementRendererView.java index 15ae5e48182..5eb909b9cb4 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/views/ImageElementRendererView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/views/ImageElementRendererView.java @@ -20,8 +20,8 @@ package org.kie.workbench.common.stunner.core.client.components.views; -import io.crysknife.client.IsElement; import org.gwtproject.safehtml.shared.SafeUri; +import org.kie.j2cl.tools.di.core.IsElement; public interface ImageElementRendererView extends IsElement { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/views/WidgetElementRendererView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/views/WidgetElementRendererView.java index 40130ae5a49..7c589f6e19c 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/views/WidgetElementRendererView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/components/views/WidgetElementRendererView.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.core.client.components.views; import elemental2.dom.HTMLElement; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; public interface WidgetElementRendererView extends IsElement { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/definition/adapter/binding/ClientBindableMorphAdapter.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/definition/adapter/binding/ClientBindableMorphAdapter.java index b5c0612c116..54a18d43048 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/definition/adapter/binding/ClientBindableMorphAdapter.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/definition/adapter/binding/ClientBindableMorphAdapter.java @@ -22,11 +22,11 @@ import java.util.Collection; -import io.crysknife.client.BeanManager; -import io.crysknife.client.SyncBeanDef; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.BeanManager; +import org.kie.j2cl.tools.di.core.SyncBeanDef; import org.kie.workbench.common.stunner.core.api.FactoryManager; import org.kie.workbench.common.stunner.core.definition.adapter.BindableMorphAdapter; import org.kie.workbench.common.stunner.core.definition.clone.CloneManager; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/i18n/ClientTranslationService.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/i18n/ClientTranslationService.java index b5980184b26..463edb1fed1 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/i18n/ClientTranslationService.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/i18n/ClientTranslationService.java @@ -24,10 +24,10 @@ import java.util.Optional; import java.util.stream.StreamSupport; -import io.crysknife.client.ManagedInstance; -import io.crysknife.ui.translation.client.TranslationService; import jakarta.inject.Inject; import jakarta.inject.Singleton; +import org.kie.j2cl.tools.di.core.ManagedInstance; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.api.SessionManager; import org.kie.workbench.common.stunner.core.client.command.CanvasViolation; import org.kie.workbench.common.stunner.core.graph.Node; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistries.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistries.java index 98a71d523da..d9728d0711d 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistries.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistries.java @@ -22,10 +22,10 @@ import java.lang.annotation.Annotation; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.session.impl.InstanceUtils; import org.kie.workbench.common.stunner.core.util.DefinitionUtils; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistryLoader.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistryLoader.java index c08a5af853a..4ce6d00527c 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistryLoader.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistryLoader.java @@ -22,11 +22,11 @@ import java.lang.annotation.Annotation; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.session.impl.InstanceUtils; import org.kie.workbench.common.stunner.core.diagram.Metadata; import org.kie.workbench.common.stunner.core.preferences.StunnerPreferences; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/resources/StunnerCommonIconsStrip.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/resources/StunnerCommonIconsStrip.java index e862c04083b..76edbe95b15 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/resources/StunnerCommonIconsStrip.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/resources/StunnerCommonIconsStrip.java @@ -22,8 +22,8 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Default; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; import org.kie.workbench.common.stunner.core.client.shape.ImageStrip; -import org.treblereel.j2cl.processors.common.resources.ImageResource; @Default @ApplicationScoped diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/resources/StunnerCommonImageResources.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/resources/StunnerCommonImageResources.java index dccd859f7aa..c408922acce 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/resources/StunnerCommonImageResources.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/resources/StunnerCommonImageResources.java @@ -20,10 +20,10 @@ package org.kie.workbench.common.stunner.core.client.resources; -import org.treblereel.j2cl.processors.annotations.GWT3Resource; -import org.treblereel.j2cl.processors.common.resources.ClientBundle; -import org.treblereel.j2cl.processors.common.resources.ImageResource; -import org.treblereel.j2cl.processors.common.resources.TextResource; +import org.kie.j2cl.tools.processors.annotations.GWT3Resource; +import org.kie.j2cl.tools.processors.common.resources.ClientBundle; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; +import org.kie.j2cl.tools.processors.common.resources.TextResource; @GWT3Resource public interface StunnerCommonImageResources extends ClientBundle { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/rule/ClientRuleManager.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/rule/ClientRuleManager.java index 5f391980569..00b3f4cdda0 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/rule/ClientRuleManager.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/rule/ClientRuleManager.java @@ -20,11 +20,11 @@ package org.kie.workbench.common.stunner.core.client.rule; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.registry.rule.RuleHandlerRegistry; import org.kie.workbench.common.stunner.core.rule.CachedRuleManager; import org.kie.workbench.common.stunner.core.rule.RuleEvaluationContext; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/AbstractClientSessionCommand.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/AbstractClientSessionCommand.java index 997d2196862..14556a9f43c 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/AbstractClientSessionCommand.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/AbstractClientSessionCommand.java @@ -23,7 +23,7 @@ import java.util.logging.Level; import java.util.logging.Logger; -import io.crysknife.client.ManagedInstance; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.canvas.CanvasHandler; import org.kie.workbench.common.stunner.core.client.canvas.event.AbstractCanvasHandlerEvent; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/ManagedClientSessionCommands.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/ManagedClientSessionCommands.java index bb8b6c36e79..432f0eb6be3 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/ManagedClientSessionCommands.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/ManagedClientSessionCommands.java @@ -26,11 +26,11 @@ import java.util.function.BiConsumer; import java.util.stream.Collectors; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.session.ClientSession; import org.kie.workbench.common.stunner.core.client.session.impl.InstanceUtils; import org.kie.workbench.common.stunner.core.util.DefinitionUtils; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/ClearSessionCommand.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/ClearSessionCommand.java index e4be553052c..4237b19b25f 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/ClearSessionCommand.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/ClearSessionCommand.java @@ -23,12 +23,12 @@ import java.util.Objects; import java.util.logging.Logger; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.event.Event; import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Default; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.command.CanvasCommandFactory; import org.kie.workbench.common.stunner.core.client.command.CanvasViolation; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/DeleteSelectionSessionCommand.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/DeleteSelectionSessionCommand.java index 44c70029b50..e405ec1b175 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/DeleteSelectionSessionCommand.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/DeleteSelectionSessionCommand.java @@ -25,12 +25,12 @@ import java.util.Objects; import java.util.stream.Collectors; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.event.Event; import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Default; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.api.SessionManager; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvas; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/PasteSelectionSessionCommand.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/PasteSelectionSessionCommand.java index 2a81070eec0..c945cf18075 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/PasteSelectionSessionCommand.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/PasteSelectionSessionCommand.java @@ -33,7 +33,6 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.event.Event; import jakarta.enterprise.event.Observes; @@ -41,6 +40,7 @@ import jakarta.enterprise.inject.Default; import jakarta.inject.Inject; import org.appformer.client.stateControl.registry.Registry; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.api.SessionManager; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvas; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/SessionSingletonCommandsFactory.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/SessionSingletonCommandsFactory.java index 1edaff49f54..6e05da343ea 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/SessionSingletonCommandsFactory.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/command/impl/SessionSingletonCommandsFactory.java @@ -22,9 +22,9 @@ import java.util.HashMap; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.event.Event; import jakarta.inject.Singleton; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.api.SessionManager; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.canvas.controls.DeleteNodeConfirmation; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/impl/InstanceUtils.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/impl/InstanceUtils.java index 941a4cd5235..f2bb143c646 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/impl/InstanceUtils.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/impl/InstanceUtils.java @@ -24,7 +24,7 @@ import java.util.List; import java.util.function.Consumer; -import io.crysknife.client.ManagedInstance; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.api.DefinitionManager; public class InstanceUtils { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/impl/ManagedSession.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/impl/ManagedSession.java index 1036fa8102c..c3cac749323 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/impl/ManagedSession.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/impl/ManagedSession.java @@ -28,11 +28,11 @@ import java.util.logging.Level; import java.util.logging.Logger; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Default; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.api.DefinitionManager; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvas; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/impl/SessionLoader.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/impl/SessionLoader.java index a950db5cb11..ff2a87fa17a 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/impl/SessionLoader.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/session/impl/SessionLoader.java @@ -24,10 +24,10 @@ import java.util.LinkedList; import java.util.List; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.api.DefinitionManager; import org.kie.workbench.common.stunner.core.client.preferences.StunnerPreferencesRegistryLoader; import org.kie.workbench.common.stunner.core.diagram.Metadata; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/shape/ImageStrip.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/shape/ImageStrip.java index 38129b45aa1..aab23a75253 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/shape/ImageStrip.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/shape/ImageStrip.java @@ -19,7 +19,7 @@ package org.kie.workbench.common.stunner.core.client.shape; -import org.treblereel.j2cl.processors.common.resources.ImageResource; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; public interface ImageStrip { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/shape/ImageStripRegistry.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/shape/ImageStripRegistry.java index a1786af2c94..6f63c3948e7 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/shape/ImageStripRegistry.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/shape/ImageStripRegistry.java @@ -25,11 +25,11 @@ import java.util.List; import java.util.stream.StreamSupport; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; @ApplicationScoped public class ImageStripRegistry { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/theme/DefaultTheme.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/theme/DefaultTheme.java index aa73901ebb4..84a15d62c4e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/theme/DefaultTheme.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/theme/DefaultTheme.java @@ -32,6 +32,8 @@ public class DefaultTheme implements StunnerColorTheme { // Transition text box static final String EDGE_TEXT_FILL_COLOR = "white"; static final String EDGE_TEXT_STROKE_COLOR = "white"; + //Canvas + static final String CANVAS_BACKGROUND_COLOR = "white"; private DefaultTheme() { } @@ -79,6 +81,21 @@ public String getEdgeTextStrokeColor() { return EDGE_TEXT_STROKE_COLOR; } + @Override + public String getScrollbarColor() { + return null; + } + + @Override + public String getCanvasBackgroundColor() { + return null; + } + + @Override + public String getScrollbarBackgroundColor() { + return CANVAS_BACKGROUND_COLOR; + } + @Override public boolean isDarkTheme() { return false; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/theme/StunnerColorTheme.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/theme/StunnerColorTheme.java index ecbac7592f5..c4ffac0c3cd 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/theme/StunnerColorTheme.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/main/java/org/kie/workbench/common/stunner/core/client/theme/StunnerColorTheme.java @@ -35,5 +35,11 @@ public interface StunnerColorTheme { String getEdgeTextStrokeColor(); + String getScrollbarColor(); + + String getCanvasBackgroundColor(); + + String getScrollbarBackgroundColor(); + boolean isDarkTheme(); } diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/api/ClientProfileManagerTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/api/ClientProfileManagerTest.java index b0c5576c417..733cc64513e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/api/ClientProfileManagerTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/api/ClientProfileManagerTest.java @@ -23,10 +23,10 @@ import java.lang.annotation.Annotation; import java.util.Iterator; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.profile.Profile; import org.kie.workbench.common.stunner.core.util.DefinitionUtils; import org.mockito.Mock; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/api/DomainInitializerTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/api/DomainInitializerTest.java index 92d8f1278b6..f9d72420ae2 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/api/DomainInitializerTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/api/DomainInitializerTest.java @@ -29,14 +29,14 @@ import java.util.HashSet; import java.util.Optional; -import io.crysknife.client.BeanManager; -import io.crysknife.client.ManagedInstance; -import io.crysknife.ui.translation.client.TranslationService; import jakarta.inject.Qualifier; import jsinterop.base.JsPropertyMap; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.BeanManager; +import org.kie.j2cl.tools.di.core.ManagedInstance; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.api.JsDefinitionManager; import org.kie.workbench.common.stunner.core.client.i18n.ClientTranslationService; import org.kie.workbench.common.stunner.core.client.registry.impl.ClientRegistryFactoryImpl; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/DeleteNodeConfirmationImplTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/DeleteNodeConfirmationImplTest.java index b411661c140..3073165c659 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/DeleteNodeConfirmationImplTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/DeleteNodeConfirmationImplTest.java @@ -27,10 +27,10 @@ import java.util.List; import java.util.Optional; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.api.SessionManager; import org.kie.workbench.common.stunner.core.client.i18n.ClientTranslationService; import org.kie.workbench.common.stunner.core.client.session.ClientSession; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneCanvasNodeCommandTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneCanvasNodeCommandTest.java index dea3c98b4e0..21fdc694e0a 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneCanvasNodeCommandTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneCanvasNodeCommandTest.java @@ -22,10 +22,10 @@ import java.util.Objects; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.TestingGraphInstanceBuilder; import org.kie.workbench.common.stunner.core.TestingGraphMockHandler; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneNodeCommandTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneNodeCommandTest.java index ac69e1e0aae..fe4d00665fe 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneNodeCommandTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/command/CloneNodeCommandTest.java @@ -20,10 +20,10 @@ package org.kie.workbench.common.stunner.core.client.canvas.command; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.command.CanvasViolation; import org.kie.workbench.common.stunner.core.command.Command; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/controls/actions/TextPropertyProviderFactoryTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/controls/actions/TextPropertyProviderFactoryTest.java index a35a6f5d5b2..e971d378a25 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/controls/actions/TextPropertyProviderFactoryTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/canvas/controls/actions/TextPropertyProviderFactoryTest.java @@ -19,11 +19,11 @@ package org.kie.workbench.common.stunner.core.client.canvas.controls.actions; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.inject.Instance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.graph.Element; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/command/CanvasCommandFactoryStub.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/command/CanvasCommandFactoryStub.java index a04b6bc19ee..dcb61f1439a 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/command/CanvasCommandFactoryStub.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/command/CanvasCommandFactoryStub.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.core.client.command; -import io.crysknife.client.ManagedInstance; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.canvas.command.DefaultCanvasCommandFactory; import org.kie.workbench.common.stunner.core.client.shape.view.BoundingBox; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/CreateNodeToolboxActionTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/CreateNodeToolboxActionTest.java index fa44d310559..3e3dba6719b 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/CreateNodeToolboxActionTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/CreateNodeToolboxActionTest.java @@ -22,10 +22,10 @@ import java.lang.annotation.Annotation; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.api.ClientFactoryManager; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.components.proxies.ElementProxy; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/FlowActionsToolboxFactoryTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/FlowActionsToolboxFactoryTest.java index ab5e8b83917..ef2e2d5b778 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/FlowActionsToolboxFactoryTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/FlowActionsToolboxFactoryTest.java @@ -27,10 +27,10 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.components.toolbox.Toolbox; import org.kie.workbench.common.stunner.core.diagram.Diagram; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/GroupActionsToolboxFactoryTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/GroupActionsToolboxFactoryTest.java index dcb583304cc..be02aaafa24 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/GroupActionsToolboxFactoryTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/GroupActionsToolboxFactoryTest.java @@ -27,10 +27,10 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.components.toolbox.Toolbox; import org.kie.workbench.common.stunner.core.diagram.Diagram; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/ToolboxDomainLookupsTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/ToolboxDomainLookupsTest.java index b482581580a..b0e734de98e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/ToolboxDomainLookupsTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/components/toolbox/actions/ToolboxDomainLookupsTest.java @@ -20,10 +20,10 @@ package org.kie.workbench.common.stunner.core.client.components.toolbox.actions; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.lookup.domain.CommonDomainLookups; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/i18n/ClientStunnerTranslationServiceTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/i18n/ClientStunnerTranslationServiceTest.java index 40337c3c24d..b73024d6d5a 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/i18n/ClientStunnerTranslationServiceTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/i18n/ClientStunnerTranslationServiceTest.java @@ -20,11 +20,11 @@ package org.kie.workbench.common.stunner.core.client.i18n; -import io.crysknife.client.ManagedInstance; -import io.crysknife.ui.translation.client.TranslationService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.api.SessionManager; import org.kie.workbench.common.stunner.core.util.DefinitionUtils; import org.kie.workbench.common.stunner.core.validation.DiagramElementNameProvider; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/i18n/ClientTranslationServiceTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/i18n/ClientTranslationServiceTest.java index a3b34a4946b..8e1b99c3c0d 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/i18n/ClientTranslationServiceTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/i18n/ClientTranslationServiceTest.java @@ -22,11 +22,11 @@ import java.util.Optional; -import io.crysknife.client.ManagedInstance; -import io.crysknife.ui.translation.client.TranslationService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.api.SessionManager; import org.kie.workbench.common.stunner.core.client.canvas.CanvasHandler; import org.kie.workbench.common.stunner.core.client.session.ClientSession; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistriesTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistriesTest.java index 466e7e6e48c..eb7e73439c0 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistriesTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistriesTest.java @@ -22,10 +22,10 @@ import java.lang.annotation.Annotation; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.preferences.StunnerPreferences; import org.kie.workbench.common.stunner.core.util.DefinitionUtils; import org.mockito.Mock; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistryLoaderTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistryLoaderTest.java index e5630f85f2e..8d2dabbee4e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistryLoaderTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/preferences/StunnerPreferencesRegistryLoaderTest.java @@ -22,10 +22,10 @@ import java.lang.annotation.Annotation; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.diagram.Metadata; import org.kie.workbench.common.stunner.core.diagram.MetadataImpl; import org.kie.workbench.common.stunner.core.preferences.StunnerPreferences; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/rule/ClientRuleManagerTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/rule/ClientRuleManagerTest.java index 5f1f269dc09..b08b9ecba10 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/rule/ClientRuleManagerTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/rule/ClientRuleManagerTest.java @@ -20,10 +20,10 @@ package org.kie.workbench.common.stunner.core.client.rule; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.registry.rule.RuleHandlerRegistry; import org.kie.workbench.common.stunner.core.rule.CachedRuleManager; import org.kie.workbench.common.stunner.core.rule.RuleEvaluationContext; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/ManagedClientSessionCommandsTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/ManagedClientSessionCommandsTest.java index 82be84394fd..4633b2ad03f 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/ManagedClientSessionCommandsTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/ManagedClientSessionCommandsTest.java @@ -22,10 +22,10 @@ import java.lang.annotation.Annotation; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.CanvasHandler; import org.kie.workbench.common.stunner.core.client.session.ClientSession; import org.kie.workbench.common.stunner.core.diagram.Diagram; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/ClearSessionCommandTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/ClearSessionCommandTest.java index 3dd01487955..5700dfbdc6c 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/ClearSessionCommandTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/ClearSessionCommandTest.java @@ -22,11 +22,11 @@ import java.lang.annotation.Annotation; -import io.crysknife.client.ManagedInstance; import org.appformer.client.stateControl.registry.Registry; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.command.CanvasCommand; import org.kie.workbench.common.stunner.core.client.command.CanvasCommandFactory; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/CutSelectionSessionCommandTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/CutSelectionSessionCommandTest.java index 45ed7962be6..87fe2566309 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/CutSelectionSessionCommandTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/CutSelectionSessionCommandTest.java @@ -22,12 +22,12 @@ import java.lang.annotation.Annotation; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.event.Event; import org.appformer.client.stateControl.registry.Registry; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.api.SessionManager; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvas; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/DeleteSelectionSessionCommandTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/DeleteSelectionSessionCommandTest.java index 30759cb08fb..1a58bb3b312 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/DeleteSelectionSessionCommandTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/DeleteSelectionSessionCommandTest.java @@ -24,10 +24,10 @@ import java.util.Collection; import java.util.Collections; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.event.Event; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.api.SessionManager; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvas; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/PasteSelectionSessionCommandTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/PasteSelectionSessionCommandTest.java index 142811715aa..5bb4949d21b 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/PasteSelectionSessionCommandTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/command/impl/PasteSelectionSessionCommandTest.java @@ -28,12 +28,12 @@ import java.util.Objects; import java.util.function.Consumer; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.event.Event; import org.appformer.client.stateControl.registry.Registry; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.TestingGraphInstanceBuilder; import org.kie.workbench.common.stunner.core.TestingGraphMockHandler; import org.kie.workbench.common.stunner.core.client.api.SessionManager; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/impl/InstanceUtilsTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/impl/InstanceUtilsTest.java index f78500b4f8a..59412a48edb 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/impl/InstanceUtilsTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/impl/InstanceUtilsTest.java @@ -22,8 +22,8 @@ import java.util.function.Consumer; -import io.crysknife.client.ManagedInstance; import org.junit.Test; +import org.kie.j2cl.tools.di.core.ManagedInstance; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/impl/ManagedSessionTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/impl/ManagedSessionTest.java index 4bd2520a521..ea8002dee12 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/impl/ManagedSessionTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/impl/ManagedSessionTest.java @@ -23,10 +23,10 @@ import java.lang.annotation.Annotation; import java.util.function.Consumer; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvas; import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler; import org.kie.workbench.common.stunner.core.client.canvas.controls.CanvasControl; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/impl/SessionLoaderTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/impl/SessionLoaderTest.java index 2a8e2f35bdf..fadb5f6fffe 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/impl/SessionLoaderTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/session/impl/SessionLoaderTest.java @@ -22,10 +22,10 @@ import java.lang.annotation.Annotation; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.api.DefinitionManager; import org.kie.workbench.common.stunner.core.client.preferences.StunnerPreferencesRegistryLoader; import org.kie.workbench.common.stunner.core.diagram.Metadata; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/shape/ImageStripRegistryTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/shape/ImageStripRegistryTest.java index 24e2e9d468a..a0cb91a8d63 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/shape/ImageStripRegistryTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/kie/workbench/common/stunner/core/client/shape/ImageStripRegistryTest.java @@ -22,13 +22,13 @@ import java.lang.annotation.Annotation; -import io.crysknife.client.ManagedInstance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import org.treblereel.j2cl.processors.common.resources.ImageResource; import org.uberfire.stubs.ManagedInstanceStub; import static org.junit.Assert.assertEquals; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/uberfire/stubs/ManagedInstanceStub.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/uberfire/stubs/ManagedInstanceStub.java index 829dc9a4f75..cca4e4722bb 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/uberfire/stubs/ManagedInstanceStub.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-client-common/src/test/java/org/uberfire/stubs/ManagedInstanceStub.java @@ -24,7 +24,7 @@ import java.util.Arrays; import java.util.Iterator; -import io.crysknife.client.ManagedInstance; +import org.kie.j2cl.tools.di.core.ManagedInstance; public class ManagedInstanceStub implements ManagedInstance { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/pom.xml b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/pom.xml index 51aadd5a49f..2062df9c549 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/pom.xml +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/pom.xml @@ -41,8 +41,8 @@ - io.crysknife - crysknife-core + org.kie.j2cl.tools.di + core @@ -61,12 +61,12 @@ - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors annotations - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors processors provided @@ -92,21 +92,4 @@ - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - - - - - diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/definition/adapter/AdapterManagerImpl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/definition/adapter/AdapterManagerImpl.java index e96639e107a..b728f2b0f84 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/definition/adapter/AdapterManagerImpl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/definition/adapter/AdapterManagerImpl.java @@ -20,10 +20,10 @@ package org.kie.workbench.common.stunner.core.definition.adapter; -import io.crysknife.annotation.CircularDependency; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.annotation.CircularDependency; import org.kie.workbench.common.stunner.core.definition.adapter.bootstrap.BootstrapAdapterFactory; import org.kie.workbench.common.stunner.core.registry.definition.AdapterRegistry; import org.kie.workbench.common.stunner.core.registry.impl.AdapterRegistryImpl; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/command/impl/CloneNodeCommand.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/command/impl/CloneNodeCommand.java index 3ee58fb9d4a..ab768ba111b 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/command/impl/CloneNodeCommand.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/command/impl/CloneNodeCommand.java @@ -30,7 +30,7 @@ import java.util.logging.Logger; import java.util.stream.Collectors; -import io.crysknife.client.ManagedInstance; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.command.Command; import org.kie.workbench.common.stunner.core.command.CommandResult; import org.kie.workbench.common.stunner.core.command.impl.AbstractCompositeCommand; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/content/view/ViewConnectorImpl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/content/view/ViewConnectorImpl.java index fcc16ef9f07..08c8f22e8cb 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/content/view/ViewConnectorImpl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/content/view/ViewConnectorImpl.java @@ -25,9 +25,9 @@ import java.util.stream.Stream; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; import org.kie.workbench.common.stunner.core.graph.content.Bounds; import org.kie.workbench.common.stunner.core.util.HashUtil; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/content/view/ViewImpl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/content/view/ViewImpl.java index bea0906e166..0eca5f019ac 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/content/view/ViewImpl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/content/view/ViewImpl.java @@ -21,8 +21,8 @@ package org.kie.workbench.common.stunner.core.graph.content.view; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; import org.kie.workbench.common.stunner.core.graph.content.Bounds; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/impl/EdgeImpl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/impl/EdgeImpl.java index 55cd1ca75e0..4a3315587ce 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/impl/EdgeImpl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/impl/EdgeImpl.java @@ -21,9 +21,9 @@ package org.kie.workbench.common.stunner.core.graph.impl; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; import org.kie.workbench.common.stunner.core.graph.Edge; import org.kie.workbench.common.stunner.core.graph.Node; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/impl/NodeImpl.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/impl/NodeImpl.java index c765cb0334d..1a9997ec435 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/impl/NodeImpl.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/graph/impl/NodeImpl.java @@ -23,10 +23,10 @@ import java.util.ArrayList; import java.util.List; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; import org.kie.workbench.common.stunner.core.graph.Edge; import org.kie.workbench.common.stunner.core.graph.Node; import org.kie.workbench.common.stunner.core.graph.content.view.ViewConnector; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @GWT3Export public class NodeImpl extends AbstractElement implements Node { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/util/DefinitionUtils.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/util/DefinitionUtils.java index 20db982be51..000e7e66162 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/util/DefinitionUtils.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/util/DefinitionUtils.java @@ -28,9 +28,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import io.crysknife.annotation.CircularDependency; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.annotation.CircularDependency; import org.kie.workbench.common.stunner.core.api.DefinitionManager; import org.kie.workbench.common.stunner.core.definition.adapter.DefinitionAdapter; import org.kie.workbench.common.stunner.core.definition.adapter.HasInheritance; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/validation/impl/AbstractDiagramValidator.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/validation/impl/AbstractDiagramValidator.java index 75b1382aba5..6822cd5565a 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/validation/impl/AbstractDiagramValidator.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/main/java/org/kie/workbench/common/stunner/core/validation/impl/AbstractDiagramValidator.java @@ -33,7 +33,7 @@ import java.util.stream.Collectors; import java.util.stream.StreamSupport; -import io.crysknife.client.ManagedInstance; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.api.DefinitionManager; import org.kie.workbench.common.stunner.core.diagram.Diagram; import org.kie.workbench.common.stunner.core.graph.Element; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/test/java/org/kie/workbench/common/stunner/core/graph/command/impl/AbstractCloneCommandTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/test/java/org/kie/workbench/common/stunner/core/graph/command/impl/AbstractCloneCommandTest.java index 97bb6f9dfcc..2bbc3250b2b 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/test/java/org/kie/workbench/common/stunner/core/graph/command/impl/AbstractCloneCommandTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/test/java/org/kie/workbench/common/stunner/core/graph/command/impl/AbstractCloneCommandTest.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.core.graph.command.impl; -import io.crysknife.client.ManagedInstance; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.TestingGraphInstanceBuilder; import org.kie.workbench.common.stunner.core.definition.adapter.DefinitionId; import org.kie.workbench.common.stunner.core.definition.adapter.binding.BindableAdapterUtils; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/test/java/org/kie/workbench/common/stunner/core/validation/impl/DiagramValidatorTest.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/test/java/org/kie/workbench/common/stunner/core/validation/impl/DiagramValidatorTest.java index ca98df9f4bb..71ddfe75d3d 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/test/java/org/kie/workbench/common/stunner/core/validation/impl/DiagramValidatorTest.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-core/kie-wb-common-stunner-commons/kie-wb-common-stunner-core-common/src/test/java/org/kie/workbench/common/stunner/core/validation/impl/DiagramValidatorTest.java @@ -29,11 +29,11 @@ import java.util.Optional; import java.util.function.Consumer; -import io.crysknife.client.ManagedInstance; import jakarta.enterprise.inject.Instance; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.TestingGraphInstanceBuilder; import org.kie.workbench.common.stunner.core.TestingGraphMockHandler; import org.kie.workbench.common.stunner.core.diagram.Diagram; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/pom.xml b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/pom.xml index ff775ed5cd3..362266ca42b 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/pom.xml +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/pom.xml @@ -88,8 +88,8 @@ test - io.crysknife - crysknife-core + org.kie.j2cl.tools.di + core diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/src/main/java/org/kie/workbench/common/stunner/lienzo/flowpanel/FloatingWidgetView.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/src/main/java/org/kie/workbench/common/stunner/lienzo/flowpanel/FloatingWidgetView.java index e640a616091..aa325fa654c 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/src/main/java/org/kie/workbench/common/stunner/lienzo/flowpanel/FloatingWidgetView.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/src/main/java/org/kie/workbench/common/stunner/lienzo/flowpanel/FloatingWidgetView.java @@ -24,8 +24,8 @@ import elemental2.dom.CSSProperties; import elemental2.dom.DomGlobal; -import io.crysknife.client.IsElement; import org.gwtproject.timer.client.Timer; +import org.kie.j2cl.tools.di.core.IsElement; /** * Floating view implementation for generic J2CL Widgets. diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/src/main/java/org/kie/workbench/common/stunner/lienzo/flowpanel/FlowPanel.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/src/main/java/org/kie/workbench/common/stunner/lienzo/flowpanel/FlowPanel.java index d90b53feca6..5e4d05e72b5 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/src/main/java/org/kie/workbench/common/stunner/lienzo/flowpanel/FlowPanel.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/src/main/java/org/kie/workbench/common/stunner/lienzo/flowpanel/FlowPanel.java @@ -6,7 +6,7 @@ import elemental2.dom.DomGlobal; import elemental2.dom.HTMLDivElement; import elemental2.dom.HTMLElement; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; public class FlowPanel implements IsElement { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/src/main/java/org/kie/workbench/common/stunner/lienzo/primitive/PrimitivePopup.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/src/main/java/org/kie/workbench/common/stunner/lienzo/primitive/PrimitivePopup.java index bd44ffa930c..4f801ce6d5d 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/src/main/java/org/kie/workbench/common/stunner/lienzo/primitive/PrimitivePopup.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/kie-wb-common-stunner-extensions/kie-wb-common-stunner-lienzo-extensions/src/main/java/org/kie/workbench/common/stunner/lienzo/primitive/PrimitivePopup.java @@ -25,7 +25,7 @@ import com.ait.lienzo.client.widget.panel.LienzoPanel; import com.ait.lienzo.client.widget.panel.impl.LienzoFixedPanel; import elemental2.dom.HTMLElement; -import io.crysknife.client.IsElement; +import org.kie.j2cl.tools.di.core.IsElement; import org.kie.workbench.common.stunner.lienzo.flowpanel.FloatingWidgetView; import static elemental2.dom.CSSProperties.ZIndexUnionType; diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/pom.xml b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/pom.xml index cf617f9817d..a2132c8451b 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/pom.xml +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-stunner/pom.xml @@ -23,7 +23,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > - stunner-editors-parent + serverless-workflow-diagram-editor-parent org.kie.kogito.stunner.serverless.editor ${revision} diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/kie-wb-common-ui/pom.xml b/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/kie-wb-common-ui/pom.xml index 8ae15899210..c6402aa5d06 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/kie-wb-common-ui/pom.xml +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/kie-wb-common-ui/pom.xml @@ -43,8 +43,8 @@ uberfire-workbench-client - io.crysknife.ui - crysknife-ui-core + org.kie.j2cl.tools.di.ui + core diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/kie-wb-common-ui/src/main/java/org/kie/workbench/common/widgets/client/KieWorkbenchWidgetsCommonEntryPoint.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/kie-wb-common-ui/src/main/java/org/kie/workbench/common/widgets/client/KieWorkbenchWidgetsCommonEntryPoint.java index 0502db3f0ac..323ef48a54d 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/kie-wb-common-ui/src/main/java/org/kie/workbench/common/widgets/client/KieWorkbenchWidgetsCommonEntryPoint.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/kie-wb-common-ui/src/main/java/org/kie/workbench/common/widgets/client/KieWorkbenchWidgetsCommonEntryPoint.java @@ -19,7 +19,7 @@ package org.kie.workbench.common.widgets.client; -import io.crysknife.ui.translation.client.annotation.Bundle; +import org.kie.j2cl.tools.di.ui.translation.client.annotation.Bundle; @Bundle("resources/i18n/KieWorkbenchWidgetsConstants.properties") public class KieWorkbenchWidgetsCommonEntryPoint { diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/kie-wb-common-ui/src/main/java/org/kie/workbench/common/widgets/client/errorpage/ErrorPage.java b/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/kie-wb-common-ui/src/main/java/org/kie/workbench/common/widgets/client/errorpage/ErrorPage.java index ddb454a7f61..9e7d1e1c145 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/kie-wb-common-ui/src/main/java/org/kie/workbench/common/widgets/client/errorpage/ErrorPage.java +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/kie-wb-common-ui/src/main/java/org/kie/workbench/common/widgets/client/errorpage/ErrorPage.java @@ -21,11 +21,11 @@ package org.kie.workbench.common.widgets.client.errorpage; import elemental2.dom.HTMLDivElement; -import io.crysknife.client.IsElement; -import io.crysknife.ui.templates.client.annotation.DataField; -import io.crysknife.ui.templates.client.annotation.Templated; import jakarta.enterprise.context.Dependent; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.IsElement; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.DataField; +import org.kie.j2cl.tools.di.ui.templates.client.annotation.Templated; @Dependent @Templated diff --git a/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/pom.xml b/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/pom.xml index 9b3f91abd00..c0912a8b18e 100644 --- a/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/pom.xml +++ b/packages/serverless-workflow-diagram-editor/kie-wb-common-widgets/pom.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > - stunner-editors-parent + serverless-workflow-diagram-editor-parent org.kie.kogito.stunner.serverless.editor ${revision} diff --git a/packages/serverless-workflow-diagram-editor/lienzo-core/pom.xml b/packages/serverless-workflow-diagram-editor/lienzo-core/pom.xml index b4642c85255..10a1aa080ab 100644 --- a/packages/serverless-workflow-diagram-editor/lienzo-core/pom.xml +++ b/packages/serverless-workflow-diagram-editor/lienzo-core/pom.xml @@ -25,7 +25,7 @@ 4.0.0 org.kie.kogito.stunner.serverless.editor - stunner-editors-parent + serverless-workflow-diagram-editor-parent ${revision} @@ -107,11 +107,11 @@ elemental2-promise - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors annotations - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors processors provided diff --git a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageCache.java b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageCache.java index ba56a492ff7..bcbae6987f3 100644 --- a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageCache.java +++ b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageCache.java @@ -17,7 +17,7 @@ package com.ait.lienzo.client.core.image; import com.ait.lienzo.tools.client.collection.NFastStringMap; -import org.treblereel.j2cl.processors.common.resources.ImageResource; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; public final class ImageCache { diff --git a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageLoader.java b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageLoader.java index 8f373069fec..faa390abca4 100755 --- a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageLoader.java +++ b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageLoader.java @@ -21,7 +21,7 @@ import elemental2.dom.HTMLElement; import elemental2.dom.HTMLImageElement; import elemental2.dom.Image; -import org.treblereel.j2cl.processors.common.resources.ImageResource; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; public abstract class ImageLoader { diff --git a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageProxy.java b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageProxy.java index 1d2520ac45e..a2052a4d51d 100755 --- a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageProxy.java +++ b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageProxy.java @@ -30,7 +30,7 @@ import com.ait.lienzo.shared.core.types.ImageFilterType; import com.ait.lienzo.shared.core.types.ImageSelectionMode; import elemental2.dom.ImageData; -import org.treblereel.j2cl.processors.common.resources.ImageResource; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; /** * ImageProxy is used by {@link AbstractImageShape} to load and draw the image. diff --git a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageStrip.java b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageStrip.java index 2241e8af2ef..3d5eab8ba1c 100644 --- a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageStrip.java +++ b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/image/ImageStrip.java @@ -1,6 +1,6 @@ package com.ait.lienzo.client.core.image; -import org.treblereel.j2cl.processors.common.resources.ImageResource; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; public class ImageStrip { diff --git a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/shape/AbstractImageShape.java b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/shape/AbstractImageShape.java index 3159d4dc847..74ebde58885 100644 --- a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/shape/AbstractImageShape.java +++ b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/shape/AbstractImageShape.java @@ -26,7 +26,7 @@ import elemental2.dom.ImageData; import jsinterop.annotations.JsProperty; import org.gwtproject.safehtml.shared.UriUtils; -import org.treblereel.j2cl.processors.common.resources.ImageResource; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; public abstract class AbstractImageShape> extends Shape { diff --git a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/shape/Picture.java b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/shape/Picture.java index a8c0b9b0a14..eb2945fb4ee 100755 --- a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/shape/Picture.java +++ b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/shape/Picture.java @@ -30,7 +30,7 @@ import com.ait.lienzo.shared.core.types.ImageSelectionMode; import com.ait.lienzo.shared.core.types.ShapeType; import jsinterop.annotations.JsProperty; -import org.treblereel.j2cl.processors.common.resources.ImageResource; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; /** * Image Support for Canvas diff --git a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/shape/Sprite.java b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/shape/Sprite.java index 4f45deee3f2..710ea0bd167 100644 --- a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/shape/Sprite.java +++ b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/core/shape/Sprite.java @@ -32,7 +32,7 @@ import com.ait.lienzo.shared.core.types.ShapeType; import com.ait.lienzo.tools.client.Timer; import jsinterop.annotations.JsProperty; -import org.treblereel.j2cl.processors.common.resources.ImageResource; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; public class Sprite extends Shape { diff --git a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/widget/panel/impl/ScrollablePanel.java b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/widget/panel/impl/ScrollablePanel.java index 3adaf87e2b4..0cd486b08bb 100644 --- a/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/widget/panel/impl/ScrollablePanel.java +++ b/packages/serverless-workflow-diagram-editor/lienzo-core/src/main/java/com/ait/lienzo/client/widget/panel/impl/ScrollablePanel.java @@ -100,6 +100,23 @@ public LienzoBoundsPanel set(final Layer layer) { return this; } + public void setScrollbarColors(String color, String backgroundColor) { + final String attribute = "scrollbar-color:"; + String scrollbarStyle = scrollPanel.style.cssText; + + // scrollbar-color clean up + if (scrollbarStyle.contains(attribute)) { + scrollbarStyle = scrollbarStyle.replaceAll(attribute + "[^;]*?;", ""); + } + + // If no colors are provided "scrollbar-color" is set to "auto" by default + if (null != color && !color.isEmpty() && null != backgroundColor && !backgroundColor.isEmpty()) { + scrollbarStyle = attribute + color + " " + backgroundColor + "; " + scrollbarStyle; + } + + scrollPanel.style.cssText = scrollbarStyle; + } + public Bounds getVisibleBounds() { if (null != getViewport()) { final Viewport viewport = getViewport(); diff --git a/packages/serverless-workflow-diagram-editor/lienzo-tests/pom.xml b/packages/serverless-workflow-diagram-editor/lienzo-tests/pom.xml index 84f5baeb8c0..dc647e1d035 100644 --- a/packages/serverless-workflow-diagram-editor/lienzo-tests/pom.xml +++ b/packages/serverless-workflow-diagram-editor/lienzo-tests/pom.xml @@ -25,7 +25,7 @@ 4.0.0 org.kie.kogito.stunner.serverless.editor - stunner-editors-parent + serverless-workflow-diagram-editor-parent ${revision} ../pom.xml diff --git a/packages/serverless-workflow-diagram-editor/lienzo-tests/src/main/java/com/ait/lienzo/test/stub/overlays/ImageData.java b/packages/serverless-workflow-diagram-editor/lienzo-tests/src/main/java/com/ait/lienzo/test/stub/overlays/ImageData.java index a0324634295..a939fa16f91 100644 --- a/packages/serverless-workflow-diagram-editor/lienzo-tests/src/main/java/com/ait/lienzo/test/stub/overlays/ImageData.java +++ b/packages/serverless-workflow-diagram-editor/lienzo-tests/src/main/java/com/ait/lienzo/test/stub/overlays/ImageData.java @@ -3,10 +3,6 @@ import com.ait.lienzo.test.annotation.StubClass; import elemental2.core.Uint8ClampedArray; -/** - * @author Dmitrii Tikhomirov - * Created by treblereel 10/30/19 - */ @StubClass("elemental2.dom.ImageData") public class ImageData { diff --git a/packages/serverless-workflow-diagram-editor/pom.xml b/packages/serverless-workflow-diagram-editor/pom.xml index fb4420383e2..0a790931694 100644 --- a/packages/serverless-workflow-diagram-editor/pom.xml +++ b/packages/serverless-workflow-diagram-editor/pom.xml @@ -22,10 +22,12 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" > + + 4.0.0 org.kie.kogito.stunner.serverless.editor - stunner-editors-parent + serverless-workflow-diagram-editor-parent ${revision} pom @@ -98,19 +100,24 @@ - jboss - JBoss Public Repo - https://repository.jboss.org/nexus/content/groups/public + jboss-public-repository-group + JBoss Public Repository Group + https://repository.jboss.org/nexus/content/groups/public/ + + + jboss-snapshots-repository + JBoss Snapshot Repository + https://repository.jboss.org/nexus/content/repositories/snapshots/ + + + sonatype-releases-repository + Sonatype Release Repository + https://oss.sonatype.org/content/repositories/releases/ - public-snapshots-repo - https://oss.sonatype.org/content/repositories/public/ - - true - - - true - + sonatype-snapshots-repository + Sonatype Snapshot Repository + https://oss.sonatype.org/content/repositories/snapshots/ @@ -135,11 +142,6 @@ - - - -Dgwt.args="${gwtArgs}" - false - 3.18.1 1.10.0 @@ -241,17 +243,13 @@ 3.2.5 3.2.2 2.3.0 - 0.21.0 1.3.12 1.1.0 2.0.0 - 32.1.3-jre - 1.1 2.10.0 1.0.0 - 1.4.20 1.3 1.3.4 1.7.4 @@ -259,16 +257,10 @@ 2.0.SP1 1.14.12 0.9.21 - 4.8.2 - 1.1.12 1.8.2 1.4 2.3 1.0 - 2.9.0 - 2.3.32 - 3.0.0 - 4.0 3.26.0-GA 4.18.1 2.3.5 @@ -280,13 +272,9 @@ 1.3 7.74.1.Final - 0.6 - 0.6.4 + 0.11.0-9336533b6 - 0.21.0 - - 0.4 - 0.4.1 + 0.23.0 5.7.0 @@ -297,9 +285,6 @@ 2.0.9 2.9.0 2.35.0 - 1.0.1 - 1.2.1 - 3.24.4 2.0.1 @@ -396,106 +381,6 @@ ${version.jsinterop.annotations} - - com.google.guava - guava - ${version.com.google.guava} - - - - com.google.guava - guava-gwt - ${version.com.google.guava} - - - - org.treblereel.gwt.nio - gwt-nio - ${version.gwt.nio} - - - - io.crysknife - crysknife-core - ${version.io.crysknife} - - - - io.crysknife - crysknife-processor - ${version.io.crysknife} - - - - io.crysknife.ui - crysknife-ui-core - ${version.io.crysknife} - - - - io.crysknife.ui - crysknife-ui-generator - ${version.io.crysknife} - - - - org.treblereel.j2cl.processors - annotations - ${version.org.gwt3.processors} - - - - org.treblereel.j2cl.processors - common - ${version.org.gwt3.processors} - - - - org.treblereel.j2cl.processors - processors - ${version.org.gwt3.processors} - - - - - - - org.treblereel.gwt.yaml.mapper - common - ${version.org.treblereel.gwt.yaml.mapper} - - - - org.treblereel.gwt.yaml.mapper - processor - ${version.org.treblereel.gwt.yaml.mapper} - - - - org.treblereel.gwt.json.mapper - common - ${version.org.treblereel.gwt.yaml.mapper} - - - - org.treblereel.gwt.json.mapper - processor - ${version.org.treblereel.gwt.json.mapper} - - - - com.google.inject - guice - ${version.com.google.inject.guice} - - - - com.google.inject - guice - ${version.com.google.inject.guice} - no_aop - - org.glassfish jakarta.json @@ -525,30 +410,6 @@ - - org.antlr - antlr4gwt-runtime - ${version.org.antlrgwt} - - - - org.hisrc.jsonix - jsonix-scripts - ${version.org.hisrc.jsonix.jsonix-scripts} - - - - org.rikkola.gwt - antlr4-c3-gwt - ${version.org.antlr4c3gwt} - - - - com.thoughtworks.xstream - xstream - ${version.com.thoughtworks.xstream} - - net.bytebuddy byte-buddy @@ -561,24 +422,6 @@ ${version.net.sourceforge.cssparser} - - org.eclipselabs - org.eclipse.emf.gwt.ecore - ${version.org.eclipse.emf.gwt} - - - - org.eclipselabs - org.eclipse.emf.gwt.common - ${version.org.eclipse.emf.gwt} - - - - org.freemarker - freemarker - ${version.org.freemarker} - - org.javassist javassist @@ -715,25 +558,6 @@ ${version.net.javacrumbs.json-unit} - - - com.google.auto - auto-common - ${version.google.auto.common} - - - - com.google.auto.service - auto-service - ${version.google.auto.service} - - - - com.github.javaparser - javaparser-core - ${version.javaparser.core} - - org.uberfire uberfire-workbench-client-views-patternfly @@ -921,9 +745,9 @@ - com.vertispan.j2cl + org.kie.j2cl.tools j2cl-maven-plugin - ${version.j2cl.plugin} + ${version.j2cl.maven.plugin} ${project.build.directory}/j2cl-watch @@ -1223,7 +1047,7 @@ jakarta.json.* jsinterop.* elemental2.* - org.treblereel.* + org.kie.j2cl.tools.* org.apache.* @@ -1285,7 +1109,7 @@ - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors processors jar diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/pom.xml b/packages/serverless-workflow-diagram-editor/sw-editor/pom.xml index b5a76232abf..e958436b91f 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/pom.xml +++ b/packages/serverless-workflow-diagram-editor/sw-editor/pom.xml @@ -25,7 +25,7 @@ 4.0.0 - stunner-editors-parent + serverless-workflow-diagram-editor-parent org.kie.kogito.stunner.serverless.editor ${revision} diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/pom.xml b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/pom.xml index 764832f3a43..43e94d7f26a 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/pom.xml +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/pom.xml @@ -59,7 +59,6 @@ kie-wb-common-stunner-core-common - com.google.jsinterop jsinterop-annotations @@ -85,29 +84,29 @@ - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors processors provided - org.treblereel.gwt.json.mapper + org.kie.j2cl.tools.json.mapper common - org.treblereel.gwt.json.mapper + org.kie.j2cl.tools.json.mapper processor provided - org.treblereel.gwt.yaml.mapper + org.kie.j2cl.tools.yaml.mapper common - org.treblereel.gwt.yaml.mapper + org.kie.j2cl.tools.yaml.mapper processor provided diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionDataFilters.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionDataFilters.java index c84e29d696a..b503328634f 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionDataFilters.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionDataFilters.java @@ -22,7 +22,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionEventRef.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionEventRef.java index b08453f4933..c435b414655 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionEventRef.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionEventRef.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionNode.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionNode.java index 148dd35f87c..8a3c859476e 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionNode.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionNode.java @@ -23,14 +23,14 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlPropertyOrder; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.FunctionRefJsonSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.SubFlowRefJsonSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.FunctionRefYamlSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.SubFlowRefYamlSerializer; -import org.treblereel.gwt.yaml.api.annotation.YamlPropertyOrder; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JsType @YamlPropertyOrder({"name", "id", "functionRef", "eventRef", "subFlowRef", "retryRef", "sleep", "retryableErrors", "nonRetryableErrors", "actionDataFilter", "condition"}) diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionTransition.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionTransition.java index c886add2ddf..e2a2666b44a 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionTransition.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionTransition.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionsContainer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionsContainer.java index 81a1430ca35..f5b10a54de5 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionsContainer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ActionsContainer.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallEventAction.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallEventAction.java index aabe5ee6189..de8a6e61e53 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallEventAction.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallEventAction.java @@ -1,7 +1,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallFunctionAction.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallFunctionAction.java index 506294643e5..3cc0602ee03 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallFunctionAction.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallFunctionAction.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallSubflowAction.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallSubflowAction.java index c6403168eab..d709c837b87 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallSubflowAction.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallSubflowAction.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallbackState.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallbackState.java index ff7564c633e..5914c927784 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallbackState.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CallbackState.java @@ -23,18 +23,18 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlPropertyOrder; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateEndDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateTransitionDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.WorkflowTimeoutsJsonSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateEndDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateTransitionDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.WorkflowTimeoutsYamlSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlPropertyOrder; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CompensationTransition.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CompensationTransition.java index 29b1ac8daca..03b0214a2b3 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CompensationTransition.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/CompensationTransition.java @@ -23,11 +23,11 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateTransitionDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateTransitionDefinitionYamlTypeSerializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ContinueAs.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ContinueAs.java index 5e4cb4e82d8..30431ff4258 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ContinueAs.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ContinueAs.java @@ -21,9 +21,9 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Correlation.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Correlation.java index 1b5a0681dfa..0cedaa3dc3d 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Correlation.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Correlation.java @@ -22,7 +22,7 @@ import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Data.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Data.java index 0e0f3c2787c..5c332d97c36 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Data.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Data.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/DataConditionTransition.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/DataConditionTransition.java index 064d04f429c..bf3bf46be3b 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/DataConditionTransition.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/DataConditionTransition.java @@ -23,13 +23,13 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateEndDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateTransitionDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateEndDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateTransitionDefinitionYamlTypeSerializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/DefaultConditionTransition.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/DefaultConditionTransition.java index 9f9a8cf230f..0eea28020a0 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/DefaultConditionTransition.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/DefaultConditionTransition.java @@ -23,13 +23,13 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateEndDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateTransitionDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateEndDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateTransitionDefinitionYamlTypeSerializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/End.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/End.java index dcf0cbf073b..d356b655e53 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/End.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/End.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Error.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Error.java index 3564cd3d6ac..468cfc94e52 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Error.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Error.java @@ -21,9 +21,9 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ErrorTransition.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ErrorTransition.java index c9694cc38a9..870ba69535a 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ErrorTransition.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ErrorTransition.java @@ -23,13 +23,13 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateEndDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateTransitionDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateEndDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateTransitionDefinitionYamlTypeSerializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Event.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Event.java index 499f7245dbd..e60929c78eb 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Event.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Event.java @@ -23,13 +23,13 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.WorkflowFunctionsJsonSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.WorkflowFunctionsYamlSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventConditionTransition.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventConditionTransition.java index 304e95ed24c..ed5ff9440bf 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventConditionTransition.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventConditionTransition.java @@ -23,13 +23,13 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateEndDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateTransitionDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateEndDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateTransitionDefinitionYamlTypeSerializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventDataFilter.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventDataFilter.java index 4769df2c28e..cdf03a2f746 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventDataFilter.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventDataFilter.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventRef.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventRef.java index 834bce2d2bd..753aea010b1 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventRef.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventRef.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventState.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventState.java index 0adcc8bbf38..2511ae384cf 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventState.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventState.java @@ -23,18 +23,18 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlPropertyOrder; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateEndDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateTransitionDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.WorkflowTimeoutsJsonSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateEndDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateTransitionDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.WorkflowTimeoutsYamlSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlPropertyOrder; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventTimeout.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventTimeout.java index 077cc5f4827..77d0afdcdeb 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventTimeout.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/EventTimeout.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ForEachState.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ForEachState.java index e8b6ebe7149..15da1f1205a 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ForEachState.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ForEachState.java @@ -23,6 +23,12 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlPropertyOrder; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.BatchSizeJsonTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateEndDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateTransitionDefinitionJsonbTypeSerializer; @@ -31,12 +37,6 @@ import org.kie.workbench.common.stunner.sw.marshall.yaml.StateTransitionDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StringNumberYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.WorkflowTimeoutsYamlSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlPropertyOrder; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Function.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Function.java index e1fcd3b64a0..a9058934bbe 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Function.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Function.java @@ -21,9 +21,9 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/FunctionRef.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/FunctionRef.java index 6c31fb332a6..c01dd47fa68 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/FunctionRef.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/FunctionRef.java @@ -23,14 +23,14 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlPropertyOrder; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StringOrValueHolderJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StringOrValueHolderYamlTypeSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlPropertyOrder; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/InjectState.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/InjectState.java index 2b9a531b5ee..4e2cb98e1ba 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/InjectState.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/InjectState.java @@ -23,18 +23,18 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlPropertyOrder; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateEndDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateTransitionDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StringOrValueHolderJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateEndDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateTransitionDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StringOrValueHolderYamlTypeSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlPropertyOrder; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Metadata.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Metadata.java index 6b0b1653fab..a0cc05c2c31 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Metadata.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Metadata.java @@ -3,12 +3,12 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.utils.GwtIncompatible; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.MetadataJsonSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.MetadataYamlSerializer; -import org.treblereel.gwt.utils.GwtIncompatible; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/OnEvent.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/OnEvent.java index a56f3dc2c48..a55003ef4f1 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/OnEvent.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/OnEvent.java @@ -21,8 +21,8 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.gwt.yaml.api.annotation.YamlPropertyOrder; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlPropertyOrder; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/OperationState.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/OperationState.java index a2de0565296..f96ec71ba81 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/OperationState.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/OperationState.java @@ -23,18 +23,18 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlPropertyOrder; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateEndDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateTransitionDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.WorkflowTimeoutsJsonSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateEndDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateTransitionDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.WorkflowTimeoutsYamlSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlPropertyOrder; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ParallelState.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ParallelState.java index 0db61d5bc74..4ae93867911 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ParallelState.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ParallelState.java @@ -23,6 +23,12 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlPropertyOrder; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.NumCompletedJsonTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateEndDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateTransitionDefinitionJsonbTypeSerializer; @@ -31,12 +37,6 @@ import org.kie.workbench.common.stunner.sw.marshall.yaml.StateTransitionDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StringNumberYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.WorkflowTimeoutsYamlSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlPropertyOrder; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ParallelStateBranch.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ParallelStateBranch.java index 366cbe02afd..65cbe2cdb89 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ParallelStateBranch.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ParallelStateBranch.java @@ -23,11 +23,11 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.WorkflowTimeoutsJsonSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.WorkflowTimeoutsYamlSerializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ProducedEvent.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ProducedEvent.java index d30669962bc..11ab05e7ec6 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ProducedEvent.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/ProducedEvent.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Retry.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Retry.java index 4a5b1cf9ed5..2caf5d17d03 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Retry.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Retry.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Schedule.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Schedule.java index 7f178a83a4d..129e46bf7e3 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Schedule.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Schedule.java @@ -21,9 +21,9 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Sleep.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Sleep.java index a18700b74de..6cd811287fd 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Sleep.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Sleep.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/SleepState.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/SleepState.java index ea7925fd6c3..ded455eba28 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/SleepState.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/SleepState.java @@ -23,15 +23,15 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateEndDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateTransitionDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateEndDefinitionYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateTransitionDefinitionYamlTypeSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Start.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Start.java index a87045be2fd..e1bb65e46c8 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Start.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Start.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StartDefinition.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StartDefinition.java index eff7993f673..63b5da0b5fd 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StartDefinition.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StartDefinition.java @@ -23,13 +23,13 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.ScheduleJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.ScheduleYamlTypeSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StartTransition.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StartTransition.java index 45f20c3ddc1..e1d9b87c34e 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StartTransition.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StartTransition.java @@ -23,11 +23,11 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StateTransitionDefinitionJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.StateTransitionDefinitionYamlTypeSerializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/State.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/State.java index 126fce8a180..32e98c128a2 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/State.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/State.java @@ -21,10 +21,10 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlPropertyOrder; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlPropertyOrder; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StateDataFilter.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StateDataFilter.java index d5d3ec9411a..5dec5dec05b 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StateDataFilter.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StateDataFilter.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StateEnd.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StateEnd.java index b1838b0c5aa..de97f8ba149 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StateEnd.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StateEnd.java @@ -23,13 +23,13 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.ContinueAsJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.ContinueAsYamlTypeSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StateTransition.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StateTransition.java index b0d8934581a..6a172232c9c 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StateTransition.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/StateTransition.java @@ -21,9 +21,9 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/SubFlowRef.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/SubFlowRef.java index bd95bd5d333..363e6966ec0 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/SubFlowRef.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/SubFlowRef.java @@ -23,13 +23,13 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.SubflowExecutionTypeJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.SubflowExecutionTypeYamlTypeSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/SwitchState.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/SwitchState.java index 2fb48e4777e..f81f31aa2d8 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/SwitchState.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/SwitchState.java @@ -23,14 +23,14 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlPropertyOrder; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.WorkflowTimeoutsJsonSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.WorkflowTimeoutsYamlSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlPropertyOrder; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Timeout.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Timeout.java index 8c4541a99f4..10063f2d168 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Timeout.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Timeout.java @@ -21,7 +21,7 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; @JsType @GWT3Export diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Transition.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Transition.java index ef752143cd2..448fd429e35 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Transition.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Transition.java @@ -21,9 +21,9 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Workflow.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Workflow.java index ad2c892a2ee..aea86eee9ae 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Workflow.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/Workflow.java @@ -23,6 +23,12 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlPropertyOrder; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.ErrorJsonSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.EventJsonbTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.StartDefinitionJsonbTypeSerializer; @@ -37,12 +43,6 @@ import org.kie.workbench.common.stunner.sw.marshall.yaml.ValueHolderYamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.WorkflowFunctionsYamlSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.WorkflowTimeoutsYamlSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlPropertyOrder; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/WorkflowExecTimeout.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/WorkflowExecTimeout.java index b4947ee63eb..029e9714233 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/WorkflowExecTimeout.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/WorkflowExecTimeout.java @@ -21,9 +21,9 @@ package org.kie.workbench.common.stunner.sw.definition; import jsinterop.annotations.JsType; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.j2cl.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/WorkflowTimeouts.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/WorkflowTimeouts.java index bd766127f30..1f6f5fc806a 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/WorkflowTimeouts.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/definition/WorkflowTimeouts.java @@ -23,13 +23,13 @@ import jakarta.json.bind.annotation.JsonbTypeDeserializer; import jakarta.json.bind.annotation.JsonbTypeSerializer; import jsinterop.annotations.JsType; +import org.kie.j2cl.tools.json.mapper.annotation.JSONMapper; +import org.kie.j2cl.tools.processors.annotations.GWT3Export; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YAMLMapper; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.annotation.YamlTypeSerializer; import org.kie.workbench.common.stunner.sw.marshall.json.WorkflowExecTimeoutJsonSerializer; import org.kie.workbench.common.stunner.sw.marshall.yaml.WorkflowExecTimeoutYamlSerializer; -import org.treblereel.gwt.json.mapper.annotation.JSONMapper; -import org.treblereel.gwt.yaml.api.annotation.YAMLMapper; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeDeserializer; -import org.treblereel.gwt.yaml.api.annotation.YamlTypeSerializer; -import org.treblereel.j2cl.processors.annotations.GWT3Export; @JSONMapper @YAMLMapper diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/Message.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/Message.java index 818c35985b5..66884c97ecd 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/Message.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/Message.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.sw.marshall; -import io.crysknife.ui.translation.client.TranslationService; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; public class Message { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/BatchSizeJsonTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/BatchSizeJsonTypeSerializer.java index 126c6cda223..8b28a88a3c0 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/BatchSizeJsonTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/BatchSizeJsonTypeSerializer.java @@ -25,11 +25,11 @@ import jakarta.json.bind.serializer.JsonbSerializer; import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; -import org.treblereel.gwt.json.mapper.internal.deserializer.BaseNumberJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.deserializer.JsonbDeserializer; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.BaseNumberJsonSerializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.BaseNumberJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.JsonbDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.BaseNumberJsonSerializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; public class BatchSizeJsonTypeSerializer extends JsonbDeserializer implements JsonbSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/ContinueAsJsonbTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/ContinueAsJsonbTypeSerializer.java index 9295f04e2b4..60c15091ca8 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/ContinueAsJsonbTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/ContinueAsJsonbTypeSerializer.java @@ -29,11 +29,12 @@ import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; import org.kie.workbench.common.stunner.sw.definition.ContinueAs; import org.kie.workbench.common.stunner.sw.definition.ContinueAs_JsonDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.ContinueAs_JsonSerializerImpl; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; + public class ContinueAsJsonbTypeSerializer implements JsonbDeserializer, JsonbSerializer { private static final ContinueAs_JsonSerializerImpl serializer = diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/ErrorJsonSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/ErrorJsonSerializer.java index 2103aaf2321..5e9e52c6360 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/ErrorJsonSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/ErrorJsonSerializer.java @@ -29,12 +29,12 @@ import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.array.ArrayJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.array.ArrayBeanJsonSerializer; import org.kie.workbench.common.stunner.sw.definition.Error_JsonDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.Error_JsonSerializerImpl; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.deserializer.array.ArrayJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; -import org.treblereel.gwt.json.mapper.internal.serializer.array.ArrayBeanJsonSerializer; public class ErrorJsonSerializer implements JsonbDeserializer, JsonbSerializer { private static final Error_JsonSerializerImpl serializer = diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/EventJsonbTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/EventJsonbTypeSerializer.java index 7f7aafbc761..2aaf70cf93c 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/EventJsonbTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/EventJsonbTypeSerializer.java @@ -29,13 +29,13 @@ import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.array.ArrayJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.array.ArrayBeanJsonSerializer; import org.kie.workbench.common.stunner.sw.definition.Event; import org.kie.workbench.common.stunner.sw.definition.Event_JsonDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.Event_JsonSerializerImpl; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.deserializer.array.ArrayJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; -import org.treblereel.gwt.json.mapper.internal.serializer.array.ArrayBeanJsonSerializer; public class EventJsonbTypeSerializer implements JsonbDeserializer, JsonbSerializer { private static final Event_JsonSerializerImpl serializer = diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/FunctionRefJsonSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/FunctionRefJsonSerializer.java index 95adc168f56..e89e6671f2e 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/FunctionRefJsonSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/FunctionRefJsonSerializer.java @@ -29,11 +29,11 @@ import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; import org.kie.workbench.common.stunner.sw.definition.FunctionRef; import org.kie.workbench.common.stunner.sw.definition.FunctionRef_JsonDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.FunctionRef_JsonSerializerImpl; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; public class FunctionRefJsonSerializer implements JsonbDeserializer, JsonbSerializer { private static final FunctionRef_JsonSerializerImpl serializer = diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/NumCompletedJsonTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/NumCompletedJsonTypeSerializer.java index 99989c100bf..7aa14343081 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/NumCompletedJsonTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/NumCompletedJsonTypeSerializer.java @@ -24,11 +24,11 @@ import jakarta.json.bind.serializer.JsonbSerializer; import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; -import org.treblereel.gwt.json.mapper.internal.deserializer.BaseNumberJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.deserializer.JsonbDeserializer; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.BaseNumberJsonSerializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.BaseNumberJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.JsonbDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.BaseNumberJsonSerializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; public class NumCompletedJsonTypeSerializer extends JsonbDeserializer implements JsonbSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/ScheduleJsonbTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/ScheduleJsonbTypeSerializer.java index fa8fa78c7bc..994353850b5 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/ScheduleJsonbTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/ScheduleJsonbTypeSerializer.java @@ -29,11 +29,11 @@ import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; import org.kie.workbench.common.stunner.sw.definition.Schedule; import org.kie.workbench.common.stunner.sw.definition.Schedule_JsonDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.Schedule_JsonSerializerImpl; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; public class ScheduleJsonbTypeSerializer implements JsonbDeserializer, JsonbSerializer { private static final Schedule_JsonSerializerImpl serializerSchedule = diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/StartDefinitionJsonbTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/StartDefinitionJsonbTypeSerializer.java index c4c9f9b740e..61447fc91b4 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/StartDefinitionJsonbTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/StartDefinitionJsonbTypeSerializer.java @@ -29,11 +29,11 @@ import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; import org.kie.workbench.common.stunner.sw.definition.StartDefinition; import org.kie.workbench.common.stunner.sw.definition.StartDefinition_JsonDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.StartDefinition_JsonSerializerImpl; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; public class StartDefinitionJsonbTypeSerializer implements JsonbDeserializer, JsonbSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/StateTransitionDefinitionJsonbTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/StateTransitionDefinitionJsonbTypeSerializer.java index cb600e26d35..cf28188460f 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/StateTransitionDefinitionJsonbTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/StateTransitionDefinitionJsonbTypeSerializer.java @@ -29,11 +29,11 @@ import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; import org.kie.workbench.common.stunner.sw.definition.StateTransition; import org.kie.workbench.common.stunner.sw.definition.StateTransition_JsonDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.StateTransition_JsonSerializerImpl; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; public class StateTransitionDefinitionJsonbTypeSerializer implements JsonbDeserializer, JsonbSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/StringOrValueHolderJsonbTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/StringOrValueHolderJsonbTypeSerializer.java index 3b5feff7a77..51b5c07872c 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/StringOrValueHolderJsonbTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/StringOrValueHolderJsonbTypeSerializer.java @@ -29,9 +29,9 @@ import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; import org.kie.workbench.common.stunner.sw.definition.ValueHolder; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; public class StringOrValueHolderJsonbTypeSerializer implements JsonbDeserializer, JsonbSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/SubFlowRefJsonSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/SubFlowRefJsonSerializer.java index 857a11f64cb..6197143d720 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/SubFlowRefJsonSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/SubFlowRefJsonSerializer.java @@ -29,12 +29,11 @@ import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; import org.kie.workbench.common.stunner.sw.definition.SubFlowRef; import org.kie.workbench.common.stunner.sw.definition.SubFlowRef_JsonDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.SubFlowRef_JsonSerializerImpl; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; - public class SubFlowRefJsonSerializer implements JsonbDeserializer, JsonbSerializer { private static final SubFlowRef_JsonSerializerImpl serializerSubFlowRef = diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/SubflowExecutionTypeJsonbTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/SubflowExecutionTypeJsonbTypeSerializer.java index 7058d168d0f..99b1e829b8c 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/SubflowExecutionTypeJsonbTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/SubflowExecutionTypeJsonbTypeSerializer.java @@ -29,9 +29,9 @@ import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; import org.kie.workbench.common.stunner.sw.definition.SubflowExecutionType; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; public class SubflowExecutionTypeJsonbTypeSerializer implements JsonbDeserializer, JsonbSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/WorkflowExecTimeoutJsonSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/WorkflowExecTimeoutJsonSerializer.java index 8b60110a218..3158a440895 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/WorkflowExecTimeoutJsonSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/WorkflowExecTimeoutJsonSerializer.java @@ -29,11 +29,11 @@ import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; import org.kie.workbench.common.stunner.sw.definition.WorkflowExecTimeout; import org.kie.workbench.common.stunner.sw.definition.WorkflowExecTimeout_JsonDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.WorkflowExecTimeout_JsonSerializerImpl; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; public class WorkflowExecTimeoutJsonSerializer implements JsonbDeserializer, JsonbSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/WorkflowFunctionsJsonSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/WorkflowFunctionsJsonSerializer.java index 07e93f660e3..e94a1751d23 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/WorkflowFunctionsJsonSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/WorkflowFunctionsJsonSerializer.java @@ -29,13 +29,13 @@ import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.array.ArrayJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.array.ArrayBeanJsonSerializer; import org.kie.workbench.common.stunner.sw.definition.Function; import org.kie.workbench.common.stunner.sw.definition.Function_JsonDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.Function_JsonSerializerImpl; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.deserializer.array.ArrayJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; -import org.treblereel.gwt.json.mapper.internal.serializer.array.ArrayBeanJsonSerializer; public class WorkflowFunctionsJsonSerializer implements JsonbDeserializer, JsonbSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/WorkflowTimeoutsJsonSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/WorkflowTimeoutsJsonSerializer.java index f57c1cb8222..44792ed9cbd 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/WorkflowTimeoutsJsonSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/json/WorkflowTimeoutsJsonSerializer.java @@ -29,11 +29,11 @@ import jakarta.json.bind.serializer.SerializationContext; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; +import org.kie.j2cl.tools.json.mapper.internal.deserializer.StringJsonDeserializer; +import org.kie.j2cl.tools.json.mapper.internal.serializer.StringJsonSerializer; import org.kie.workbench.common.stunner.sw.definition.WorkflowTimeouts; import org.kie.workbench.common.stunner.sw.definition.WorkflowTimeouts_JsonDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.WorkflowTimeouts_JsonSerializerImpl; -import org.treblereel.gwt.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.treblereel.gwt.json.mapper.internal.serializer.StringJsonSerializer; public class WorkflowTimeoutsJsonSerializer implements JsonbDeserializer, JsonbSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ContinueAsYamlTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ContinueAsYamlTypeSerializer.java index 2d52c71bd2b..146148f7c5c 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ContinueAsYamlTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ContinueAsYamlTypeSerializer.java @@ -20,19 +20,19 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.ContinueAs; import org.kie.workbench.common.stunner.sw.definition.ContinueAs_YamlMapperImpl; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class ContinueAsYamlTypeSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ErrorYamlSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ErrorYamlSerializer.java index 77168b604bc..4541f8d4a8a 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ErrorYamlSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ErrorYamlSerializer.java @@ -20,21 +20,21 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.array.ArrayYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.array.ArrayYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.Error_YamlDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.Error_YamlSerializerImpl; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.deser.array.ArrayYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.array.ArrayYAMLSerializer; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class ErrorYamlSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/EventYamlTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/EventYamlTypeSerializer.java index 8722db3ff8b..a84ac3702c4 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/EventYamlTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/EventYamlTypeSerializer.java @@ -20,21 +20,21 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.array.ArrayYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.array.ArrayYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.Event; import org.kie.workbench.common.stunner.sw.definition.Event_YamlMapperImpl; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.deser.array.ArrayYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.array.ArrayYAMLSerializer; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class EventYamlTypeSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/FunctionRefYamlSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/FunctionRefYamlSerializer.java index 89dab3e0ea2..2486a421092 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/FunctionRefYamlSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/FunctionRefYamlSerializer.java @@ -20,19 +20,19 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.FunctionRef; import org.kie.workbench.common.stunner.sw.definition.FunctionRef_YamlMapperImpl; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class FunctionRefYamlSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/MetadataYamlSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/MetadataYamlSerializer.java index 44c7760e35e..49d04fc76bc 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/MetadataYamlSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/MetadataYamlSerializer.java @@ -23,18 +23,18 @@ import elemental2.core.JsArray; import elemental2.core.Reflect; import jsinterop.base.Js; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.Metadata; import org.kie.workbench.common.stunner.sw.definition.ValueHolder; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class MetadataYamlSerializer implements YAMLSerializer, YAMLDeserializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ScheduleYamlTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ScheduleYamlTypeSerializer.java index 0d099c751b7..5231f17ee22 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ScheduleYamlTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ScheduleYamlTypeSerializer.java @@ -20,19 +20,19 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.Schedule; import org.kie.workbench.common.stunner.sw.definition.Schedule_YamlMapperImpl; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class ScheduleYamlTypeSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StartDefinitionYamlTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StartDefinitionYamlTypeSerializer.java index 3c195f71d42..ea51af8a00e 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StartDefinitionYamlTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StartDefinitionYamlTypeSerializer.java @@ -1,18 +1,18 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.StartDefinition; import org.kie.workbench.common.stunner.sw.definition.StartDefinition_YamlMapperImpl; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class StartDefinitionYamlTypeSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StateEndDefinitionYamlTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StateEndDefinitionYamlTypeSerializer.java index 7e538345aa3..0693f19c4fa 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StateEndDefinitionYamlTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StateEndDefinitionYamlTypeSerializer.java @@ -1,18 +1,19 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.BooleanYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.BooleanYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.StateEnd; import org.kie.workbench.common.stunner.sw.definition.StateEnd_YamlMapperImpl; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.BooleanYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.BooleanYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; + public class StateEndDefinitionYamlTypeSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StateTransitionDefinitionYamlTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StateTransitionDefinitionYamlTypeSerializer.java index f76ae4581e5..a1c8adc5a9f 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StateTransitionDefinitionYamlTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StateTransitionDefinitionYamlTypeSerializer.java @@ -1,18 +1,18 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.StateTransition; import org.kie.workbench.common.stunner.sw.definition.StateTransition_YamlMapperImpl; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class StateTransitionDefinitionYamlTypeSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StateYamlSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StateYamlSerializer.java index 044790c5dce..af7ec619323 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StateYamlSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StateYamlSerializer.java @@ -1,5 +1,13 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.CallbackState; import org.kie.workbench.common.stunner.sw.definition.CallbackState_YamlMapperImpl; import org.kie.workbench.common.stunner.sw.definition.EventState; @@ -18,15 +26,6 @@ import org.kie.workbench.common.stunner.sw.definition.State_YamlMapperImpl; import org.kie.workbench.common.stunner.sw.definition.SwitchState; import org.kie.workbench.common.stunner.sw.definition.SwitchState_YamlMapperImpl; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; - public class StateYamlSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StringNumberYamlTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StringNumberYamlTypeSerializer.java index f4417c19696..51643b61a60 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StringNumberYamlTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StringNumberYamlTypeSerializer.java @@ -6,32 +6,32 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations - * under the License. + * under the License. */ package org.kie.workbench.common.stunner.sw.marshall.yaml; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.BaseNumberYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.BaseNumberYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; public class StringNumberYamlTypeSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StringOrValueHolderYamlTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StringOrValueHolderYamlTypeSerializer.java index a4e6b9c9704..ac5f1f37489 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StringOrValueHolderYamlTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/StringOrValueHolderYamlTypeSerializer.java @@ -21,18 +21,18 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; import jsinterop.base.Js; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.ValueHolder; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class StringOrValueHolderYamlTypeSerializer implements YAMLDeserializer, YAMLSerializer { private static final StringYAMLSerializer stringYAMLSerializer = new StringYAMLSerializer(); diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/SubFlowRefYamlSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/SubFlowRefYamlSerializer.java index d541c2b2c34..65404ca3ba4 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/SubFlowRefYamlSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/SubFlowRefYamlSerializer.java @@ -1,18 +1,18 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.SubFlowRef; import org.kie.workbench.common.stunner.sw.definition.SubFlowRef_YamlMapperImpl; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class SubFlowRefYamlSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/SubflowExecutionTypeYamlTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/SubflowExecutionTypeYamlTypeSerializer.java index 1e203ffa6a9..e16cb3e4589 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/SubflowExecutionTypeYamlTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/SubflowExecutionTypeYamlTypeSerializer.java @@ -1,17 +1,17 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.SubflowExecutionType; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class SubflowExecutionTypeYamlTypeSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ValueHolderYamlTypeSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ValueHolderYamlTypeSerializer.java index 9473002a3d8..dfdb1dfa695 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ValueHolderYamlTypeSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/ValueHolderYamlTypeSerializer.java @@ -7,20 +7,19 @@ import elemental2.core.Reflect; import jakarta.json.JsonObject; import jsinterop.base.Js; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.BaseNumberYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.BooleanYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.ValueHolder; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.BaseNumberYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.BooleanYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; - public class ValueHolderYamlTypeSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/WorkflowExecTimeoutYamlSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/WorkflowExecTimeoutYamlSerializer.java index a8034feafcd..3800b572a3a 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/WorkflowExecTimeoutYamlSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/WorkflowExecTimeoutYamlSerializer.java @@ -1,18 +1,18 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.WorkflowExecTimeout; import org.kie.workbench.common.stunner.sw.definition.WorkflowExecTimeout_YamlMapperImpl; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class WorkflowExecTimeoutYamlSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/WorkflowFunctionsYamlSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/WorkflowFunctionsYamlSerializer.java index 171f8feb951..14a0b72aafb 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/WorkflowFunctionsYamlSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/WorkflowFunctionsYamlSerializer.java @@ -1,21 +1,21 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.array.ArrayYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.array.ArrayYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.Function; import org.kie.workbench.common.stunner.sw.definition.Function_YamlDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.Function_YamlSerializerImpl; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.deser.array.ArrayYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.array.ArrayYAMLSerializer; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class WorkflowFunctionsYamlSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/WorkflowTimeoutsYamlSerializer.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/WorkflowTimeoutsYamlSerializer.java index ef301623435..7aea70be8f6 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/WorkflowTimeoutsYamlSerializer.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/marshall/yaml/WorkflowTimeoutsYamlSerializer.java @@ -1,19 +1,19 @@ package org.kie.workbench.common.stunner.sw.marshall.yaml; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.YAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.exception.YAMLDeserializationException; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.StringYAMLDeserializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.deser.YAMLDeserializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.StringYAMLSerializer; +import org.kie.j2cl.tools.yaml.mapper.api.internal.ser.YAMLSerializationContext; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlSequence; import org.kie.workbench.common.stunner.sw.definition.WorkflowTimeouts; import org.kie.workbench.common.stunner.sw.definition.WorkflowTimeouts_YamlDeserializerImpl; import org.kie.workbench.common.stunner.sw.definition.WorkflowTimeouts_YamlSerializerImpl; -import org.treblereel.gwt.yaml.api.YAMLDeserializer; -import org.treblereel.gwt.yaml.api.YAMLSerializer; -import org.treblereel.gwt.yaml.api.exception.YAMLDeserializationException; -import org.treblereel.gwt.yaml.api.internal.deser.StringYAMLDeserializer; -import org.treblereel.gwt.yaml.api.internal.deser.YAMLDeserializationContext; -import org.treblereel.gwt.yaml.api.internal.ser.StringYAMLSerializer; -import org.treblereel.gwt.yaml.api.internal.ser.YAMLSerializationContext; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.YamlSequence; public class WorkflowTimeoutsYamlSerializer implements YAMLDeserializer, YAMLSerializer { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/resources/i18n/SWConstants.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/resources/i18n/SWConstants.java index 80526990791..6c2f069d973 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/resources/i18n/SWConstants.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-api/src/main/java/org/kie/workbench/common/stunner/sw/resources/i18n/SWConstants.java @@ -19,7 +19,7 @@ package org.kie.workbench.common.stunner.sw.resources.i18n; -import io.crysknife.ui.translation.client.annotation.TranslationKey; +import org.kie.j2cl.tools.di.ui.translation.client.annotation.TranslationKey; public interface SWConstants { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/pom.xml b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/pom.xml index 54b2834152f..94c899a6911 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/pom.xml +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/pom.xml @@ -117,7 +117,7 @@ - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors processors provided diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/SWEntryPoint.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/SWEntryPoint.java index 13faebde071..08d30779102 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/SWEntryPoint.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/SWEntryPoint.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.sw; -import io.crysknife.ui.translation.client.annotation.Bundle; +import org.kie.j2cl.tools.di.ui.translation.client.annotation.Bundle; @Bundle("resources/i18n/SWConstants.properties") public class SWEntryPoint { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/ShapeFactory.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/ShapeFactory.java index 4c13cd384c6..e6ad4c3c1f5 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/ShapeFactory.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/ShapeFactory.java @@ -20,10 +20,10 @@ package org.kie.workbench.common.stunner.sw.client; -import io.crysknife.ui.translation.client.TranslationService; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import org.appformer.kogito.bridge.client.resource.ResourceContentService; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.shape.Shape; import org.kie.workbench.common.stunner.core.definition.shape.Glyph; import org.kie.workbench.common.stunner.sw.client.resources.GlyphFactory; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/config/ToolboxControl.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/config/ToolboxControl.java index 1f4ecbf0e68..eb46f519179 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/config/ToolboxControl.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/config/ToolboxControl.java @@ -23,11 +23,11 @@ import java.util.Arrays; import java.util.List; -import io.crysknife.client.ManagedInstance; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.core.ManagedInstance; import org.kie.workbench.common.stunner.core.client.canvas.controls.toolbox.AbstractToolboxControl; import org.kie.workbench.common.stunner.core.client.components.toolbox.actions.ActionsToolboxFactory; import org.kie.workbench.common.stunner.core.client.components.toolbox.actions.CommonActionsToolbox; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/resources/ImageResources.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/resources/ImageResources.java index 40d81783570..17b33b9c6b3 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/resources/ImageResources.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/resources/ImageResources.java @@ -20,9 +20,9 @@ package org.kie.workbench.common.stunner.sw.client.resources; -import org.treblereel.j2cl.processors.annotations.GWT3Resource; -import org.treblereel.j2cl.processors.common.resources.ClientBundle; -import org.treblereel.j2cl.processors.common.resources.ImageResource; +import org.kie.j2cl.tools.processors.annotations.GWT3Resource; +import org.kie.j2cl.tools.processors.common.resources.ClientBundle; +import org.kie.j2cl.tools.processors.common.resources.ImageResource; @GWT3Resource public interface ImageResources extends ClientBundle { diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/CallbackStateShape.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/CallbackStateShape.java index 80f23336370..97a774d07bb 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/CallbackStateShape.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/CallbackStateShape.java @@ -19,8 +19,8 @@ package org.kie.workbench.common.stunner.sw.client.shapes; -import io.crysknife.ui.translation.client.TranslationService; import org.appformer.kogito.bridge.client.resource.ResourceContentService; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.shape.MutationContext; import org.kie.workbench.common.stunner.core.client.theme.StunnerTheme; import org.kie.workbench.common.stunner.core.graph.Edge; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/EndShape.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/EndShape.java index 3af302f0b8f..d10e1578daf 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/EndShape.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/EndShape.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.sw.client.shapes; -import io.crysknife.ui.translation.client.TranslationService; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import static org.kie.workbench.common.stunner.sw.resources.i18n.SWConstants.SHAPE_END; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/EventStateShape.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/EventStateShape.java index e62e97f82ac..b12a2bc557d 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/EventStateShape.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/EventStateShape.java @@ -19,8 +19,8 @@ package org.kie.workbench.common.stunner.sw.client.shapes; -import io.crysknife.ui.translation.client.TranslationService; import org.appformer.kogito.bridge.client.resource.ResourceContentService; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.shape.MutationContext; import org.kie.workbench.common.stunner.core.client.theme.StunnerTheme; import org.kie.workbench.common.stunner.core.graph.Edge; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/ForEachStateShape.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/ForEachStateShape.java index cb657cfb082..e3e39176d84 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/ForEachStateShape.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/ForEachStateShape.java @@ -19,8 +19,8 @@ package org.kie.workbench.common.stunner.sw.client.shapes; -import io.crysknife.ui.translation.client.TranslationService; import org.appformer.kogito.bridge.client.resource.ResourceContentService; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.shape.MutationContext; import org.kie.workbench.common.stunner.core.client.theme.StunnerTheme; import org.kie.workbench.common.stunner.core.graph.Edge; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/InjectStateShape.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/InjectStateShape.java index e556f7e4444..c533b95eebd 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/InjectStateShape.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/InjectStateShape.java @@ -19,8 +19,8 @@ package org.kie.workbench.common.stunner.sw.client.shapes; -import io.crysknife.ui.translation.client.TranslationService; import org.appformer.kogito.bridge.client.resource.ResourceContentService; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.shape.MutationContext; import org.kie.workbench.common.stunner.core.client.theme.StunnerTheme; import org.kie.workbench.common.stunner.core.graph.Edge; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/OperationStateShape.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/OperationStateShape.java index f16fb0b6d36..48cd810b08d 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/OperationStateShape.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/OperationStateShape.java @@ -19,8 +19,8 @@ package org.kie.workbench.common.stunner.sw.client.shapes; -import io.crysknife.ui.translation.client.TranslationService; import org.appformer.kogito.bridge.client.resource.ResourceContentService; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.shape.MutationContext; import org.kie.workbench.common.stunner.core.client.theme.StunnerTheme; import org.kie.workbench.common.stunner.core.graph.Edge; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/ParallelStateShape.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/ParallelStateShape.java index 72d0d6f169d..68ea0f62958 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/ParallelStateShape.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/ParallelStateShape.java @@ -19,8 +19,8 @@ package org.kie.workbench.common.stunner.sw.client.shapes; -import io.crysknife.ui.translation.client.TranslationService; import org.appformer.kogito.bridge.client.resource.ResourceContentService; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.shape.MutationContext; import org.kie.workbench.common.stunner.core.client.theme.StunnerTheme; import org.kie.workbench.common.stunner.core.graph.Edge; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/ServerlessWorkflowShape.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/ServerlessWorkflowShape.java index ee2407697a9..42d5ccab3c0 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/ServerlessWorkflowShape.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/ServerlessWorkflowShape.java @@ -21,7 +21,7 @@ import com.ait.lienzo.client.core.event.NodeMouseEnterHandler; import com.ait.lienzo.client.core.event.NodeMouseExitHandler; -import io.crysknife.ui.translation.client.TranslationService; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.shape.impl.AbstractShape; import org.kie.workbench.common.stunner.core.client.shape.impl.NodeShapeImpl; import org.kie.workbench.common.stunner.sw.definition.State; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/SleepStateShape.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/SleepStateShape.java index 4eb7c5e1525..a6ab6bbd733 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/SleepStateShape.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/SleepStateShape.java @@ -19,8 +19,8 @@ package org.kie.workbench.common.stunner.sw.client.shapes; -import io.crysknife.ui.translation.client.TranslationService; import org.appformer.kogito.bridge.client.resource.ResourceContentService; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.shape.MutationContext; import org.kie.workbench.common.stunner.core.client.theme.StunnerTheme; import org.kie.workbench.common.stunner.core.graph.Edge; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/StartShape.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/StartShape.java index 0f9eca0cc3c..2139af45aba 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/StartShape.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/StartShape.java @@ -20,7 +20,7 @@ package org.kie.workbench.common.stunner.sw.client.shapes; -import io.crysknife.ui.translation.client.TranslationService; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import static org.kie.workbench.common.stunner.sw.resources.i18n.SWConstants.SHAPE_START; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/StateShape.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/StateShape.java index d28b02a329e..8485fb11f04 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/StateShape.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/StateShape.java @@ -23,9 +23,9 @@ import com.ait.lienzo.client.core.event.NodeMouseExitHandler; import com.ait.lienzo.client.core.shape.Picture; import com.ait.lienzo.client.core.types.Transform; -import io.crysknife.ui.translation.client.TranslationService; import org.appformer.kogito.bridge.client.resource.ResourceContentService; import org.appformer.kogito.bridge.client.resource.interop.ResourceContentOptions; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.shape.HasShapeState; import org.kie.workbench.common.stunner.core.client.shape.MutationContext; import org.kie.workbench.common.stunner.core.graph.Edge; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/SwitchStateShape.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/SwitchStateShape.java index d589efb2361..cd449d5d304 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/SwitchStateShape.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/SwitchStateShape.java @@ -19,8 +19,8 @@ package org.kie.workbench.common.stunner.sw.client.shapes; -import io.crysknife.ui.translation.client.TranslationService; import org.appformer.kogito.bridge.client.resource.ResourceContentService; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.shape.MutationContext; import org.kie.workbench.common.stunner.core.client.theme.StunnerTheme; import org.kie.workbench.common.stunner.core.graph.Edge; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/theme/DarkMode.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/theme/DarkMode.java index 2726f5237a3..17b6371b38f 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/theme/DarkMode.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/theme/DarkMode.java @@ -73,6 +73,9 @@ public class DarkMode implements ColorTheme { private static final String TRANSITION_BOX_COLOR = "gray"; private static final String ERROR_TRANSITION_BOX_COLOR = "#9F3A3A"; private static final String EVENT_CONDITION_TRANSITION_BOX_COLOR = "#C97330"; + // Canvas Scrollbars + private static final String SCROLLBAR_COLOR = "#4F4F4F"; + private static final String SCROLLBAR_BACKGROUND_COLOR = "#000"; private DarkMode() { } @@ -275,6 +278,16 @@ public String getEdgeTextStrokeColor() { return EDGE_TEXT_STROKE_COLOR; } + @Override + public String getScrollbarColor() { + return SCROLLBAR_COLOR; + } + + @Override + public String getScrollbarBackgroundColor() { + return SCROLLBAR_BACKGROUND_COLOR; + } + @Override public boolean isDarkTheme() { return true; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/theme/LightMode.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/theme/LightMode.java index ee1c33d734a..3eab31d596f 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/theme/LightMode.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/theme/LightMode.java @@ -275,6 +275,16 @@ public String getEdgeTextStrokeColor() { return EDGE_TEXT_STROKE_COLOR; } + @Override + public String getScrollbarColor() { + return null; + } + + @Override + public String getScrollbarBackgroundColor() { + return null; + } + @Override public boolean isDarkTheme() { return false; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/test/java/org/kie/workbench/common/stunner/sw/client/shapes/HasTranslationGeneralTest.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/test/java/org/kie/workbench/common/stunner/sw/client/shapes/HasTranslationGeneralTest.java index 81d5457cf0d..131da993b82 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/test/java/org/kie/workbench/common/stunner/sw/client/shapes/HasTranslationGeneralTest.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/test/java/org/kie/workbench/common/stunner/sw/client/shapes/HasTranslationGeneralTest.java @@ -22,8 +22,8 @@ import java.util.List; -import io.crysknife.ui.translation.client.TranslationService; import org.junit.Before; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.mockito.ArgumentCaptor; import static org.junit.Assert.assertEquals; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/test/java/org/kie/workbench/common/stunner/sw/client/shapes/StateShapeTest.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/test/java/org/kie/workbench/common/stunner/sw/client/shapes/StateShapeTest.java index 023bf733466..6f8370e72af 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/test/java/org/kie/workbench/common/stunner/sw/client/shapes/StateShapeTest.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/test/java/org/kie/workbench/common/stunner/sw/client/shapes/StateShapeTest.java @@ -24,11 +24,11 @@ import com.ait.lienzo.client.core.shape.Shape; import com.ait.lienzo.test.LienzoMockitoTestRunner; import elemental2.promise.Promise; -import io.crysknife.ui.translation.client.TranslationService; import org.appformer.kogito.bridge.client.resource.ResourceContentService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.core.client.shape.ShapeState; import org.kie.workbench.common.stunner.core.client.shape.impl.ShapeStateHandler; import org.kie.workbench.common.stunner.core.client.theme.StunnerTheme; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/README.md b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/README.md index 5a03188797f..9a558a7df8c 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/README.md +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/README.md @@ -28,9 +28,9 @@ Following commands assume the use of Widfly: Change to the `kie-tools/packages/serverless-workflow-diagram-editor/` root folder - set compilationLevel of j2cl-maven-plugin to `BUNDLE_JAR` in `kie-tools/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/pom.xml` -- run `mvn clean com.vertispan.j2cl:j2cl-maven-plugin:watch` in the `kie-tools/packages/serverless-workflow-diagram-editor` root folder +- run `mvn clean org.kie.j2cl.tools:j2cl-maven-plugin:watch` in the `kie-tools/packages/serverless-workflow-diagram-editor` root folder - once the build is finished (there will be `Build Complete: ready for browser refresh` in the terminal window), open another terminal in `kie-tools/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/target/sw-editor-kogito-app/org.kie.workbench.common.stunner.sw.KogitoSWEditor` folder -- start a local web server by: `python -m SimpleHTTPServer 8001` or `http-server -p 8001` or any other web server +- start a local web server by: `python3 -m SimpleHTTPServer 8001` or `http-server -p 8001` or any other web server - Navigate to `http://localhost:8001/test.html` In any question, please follow the j2cl-maven-plugin documentation diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/pom.xml b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/pom.xml index a87773b03c3..a6a23c47add 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/pom.xml +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/pom.xml @@ -167,26 +167,25 @@ - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors processors provided - io.crysknife.ui - crysknife-ui-core - ${version.io.crysknife} + org.kie.j2cl.tools.di + processor + provided - io.crysknife - crysknife-processor - provided + org.kie.j2cl.tools.di.ui + core - io.crysknife.ui - crysknife-ui-generator + org.kie.j2cl.tools.di.ui + generator provided @@ -269,7 +268,7 @@ - com.vertispan.j2cl + org.kie.j2cl.tools j2cl-maven-plugin diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/main/java/org/kie/workbench/common/stunner/sw/client/MainEntryPoint.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/main/java/org/kie/workbench/common/stunner/sw/client/MainEntryPoint.java index d847a379fad..48a52bfef87 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/main/java/org/kie/workbench/common/stunner/sw/client/MainEntryPoint.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/main/java/org/kie/workbench/common/stunner/sw/client/MainEntryPoint.java @@ -19,12 +19,12 @@ package org.kie.workbench.common.stunner.sw.client; -import io.crysknife.annotation.Application; import jakarta.annotation.PostConstruct; import jakarta.inject.Inject; +import org.kie.j2cl.tools.di.annotation.Application; +import org.kie.j2cl.tools.processors.annotations.GWT3EntryPoint; import org.kie.workbench.common.stunner.client.lienzo.StunnerLienzoCore; import org.kie.workbench.common.stunner.sw.client.editor.DiagramEditorActivity; -import org.treblereel.j2cl.processors.annotations.GWT3EntryPoint; import org.uberfire.client.workbench.WorkbenchEntryPoint; import org.uberfire.mvp.impl.DefaultPlaceRequest; diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/main/java/org/kie/workbench/common/stunner/sw/client/editor/DiagramEditor.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/main/java/org/kie/workbench/common/stunner/sw/client/editor/DiagramEditor.java index 325dddf2dfa..6fd85ba0090 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/main/java/org/kie/workbench/common/stunner/sw/client/editor/DiagramEditor.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/main/java/org/kie/workbench/common/stunner/sw/client/editor/DiagramEditor.java @@ -30,13 +30,13 @@ import elemental2.core.RegExpResult; import elemental2.dom.DomGlobal; import elemental2.promise.Promise; -import io.crysknife.ui.translation.client.TranslationService; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Event; import jakarta.inject.Inject; import jsinterop.annotations.JsType; import jsinterop.base.Js; import org.appformer.kogito.bridge.client.diagramApi.DiagramApi; +import org.kie.j2cl.tools.di.ui.translation.client.TranslationService; import org.kie.workbench.common.stunner.client.lienzo.canvas.wires.WiresCanvas; import org.kie.workbench.common.stunner.client.lienzo.components.mediators.preview.TogglePreviewEvent; import org.kie.workbench.common.stunner.client.widgets.canvas.ScrollableLienzoPanel; @@ -183,7 +183,7 @@ private ColorTheme getTheme(final String theme) { private void setTheme() { StunnerTheme.setTheme(themeToBeApplied); - setCanvasBackgroundColor(); + setCanvasColors(); themeToBeApplied = null; } @@ -193,11 +193,9 @@ void reloadEditorContent() { } } - void setCanvasBackgroundColor() { - if (null != stunnerEditor.getSession()) { - ((WiresCanvas) stunnerEditor.getCanvasHandler().getCanvas()) - .setBackgroundColor(((ColorTheme) StunnerTheme.getTheme()).getCanvasBackgroundColor()); - } + void setCanvasColors() { + stunnerEditor.setScrollbarColors(); + stunnerEditor.setCanvasBackgroundColor(); } public Promise setContent(final String path, final String value) { @@ -273,7 +271,7 @@ public void onError(ClientRuntimeError error) { @Override public void afterCanvasInitialized() { - setCanvasBackgroundColor(); + setCanvasColors(); } }); } diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/test/java/org/kie/workbench/common/stunner/sw/client/editor/DiagramEditorTest.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/test/java/org/kie/workbench/common/stunner/sw/client/editor/DiagramEditorTest.java index 78b350cbf35..879526f78fb 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/test/java/org/kie/workbench/common/stunner/sw/client/editor/DiagramEditorTest.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/test/java/org/kie/workbench/common/stunner/sw/client/editor/DiagramEditorTest.java @@ -269,7 +269,7 @@ public void testSetTheme() { tested.applyTheme(DarkMode.NAME); verify(tested, times(1)).reloadEditorContent(); - verify(tested, times(1)).setCanvasBackgroundColor(); + verify(tested, times(1)).setCanvasColors(); assertNull(tested.themeToBeApplied); assertTrue(StunnerTheme.getTheme() instanceof DarkMode); } @@ -288,7 +288,7 @@ public void testSetThemeBrokenDiagram() { tested.applyTheme(DarkMode.NAME); verify(tested, times(0)).reloadEditorContent(); - verify(tested, times(0)).setCanvasBackgroundColor(); + verify(tested, times(0)).setCanvasColors(); assertTrue(tested.themeToBeApplied instanceof DarkMode); } @@ -304,7 +304,7 @@ public void testSetThemeNull() { tested.applyTheme(null); verify(tested, times(0)).reloadEditorContent(); - verify(tested, times(0)).setCanvasBackgroundColor(); + verify(tested, times(0)).setCanvasColors(); assertNull(tested.themeToBeApplied); assertTrue(StunnerTheme.getTheme() instanceof LightMode); } @@ -321,7 +321,7 @@ public void testSetThemeSame() { tested.applyTheme(LightMode.NAME); verify(tested, times(0)).reloadEditorContent(); - verify(tested, times(0)).setCanvasBackgroundColor(); + verify(tested, times(0)).setCanvasColors(); assertNull(tested.themeToBeApplied); assertTrue(StunnerTheme.getTheme() instanceof LightMode); } diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/test/java/org/kie/workbench/common/stunner/sw/client/selenium/yaml/SWEditorYamlSeleniumIT.java b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/test/java/org/kie/workbench/common/stunner/sw/client/selenium/yaml/SWEditorYamlSeleniumIT.java index 54219296aca..3fcd1be9f36 100644 --- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/test/java/org/kie/workbench/common/stunner/sw/client/selenium/yaml/SWEditorYamlSeleniumIT.java +++ b/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-kogito-app/src/test/java/org/kie/workbench/common/stunner/sw/client/selenium/yaml/SWEditorYamlSeleniumIT.java @@ -28,13 +28,13 @@ import org.apache.commons.io.IOUtils; import org.junit.Test; +import org.kie.j2cl.tools.yaml.mapper.api.internal.utils.Pair; +import org.kie.j2cl.tools.yaml.mapper.api.node.NodeType; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlMapping; +import org.kie.j2cl.tools.yaml.mapper.api.node.YamlNode; +import org.kie.j2cl.tools.yaml.mapper.api.node.impl.Yaml; import org.kie.workbench.common.stunner.sw.client.selenium.SWEditorSeleniumBase; import org.openqa.selenium.JavascriptExecutor; -import org.treblereel.gwt.yaml.api.internal.utils.Pair; -import org.treblereel.gwt.yaml.api.node.NodeType; -import org.treblereel.gwt.yaml.api.node.YamlMapping; -import org.treblereel.gwt.yaml.api.node.YamlNode; -import org.treblereel.gwt.yaml.api.node.impl.Yaml; import static org.assertj.core.api.Assertions.assertThat; diff --git a/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/core/pom.xml b/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/core/pom.xml index 81a3ab4ad8d..ec6f5b54ae0 100644 --- a/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/core/pom.xml +++ b/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/core/pom.xml @@ -49,19 +49,19 @@ gwtproject - io.crysknife.ui - crysknife-ui-core + org.kie.j2cl.tools.di.ui + core - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors common - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors annotations - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors processors provided diff --git a/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/extras/pom.xml b/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/extras/pom.xml index 37db580fa86..277279d9dec 100644 --- a/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/extras/pom.xml +++ b/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/extras/pom.xml @@ -53,11 +53,11 @@ gwtproject - io.crysknife.ui - crysknife-ui-core + org.kie.j2cl.tools.di.ui + core - org.treblereel.j2cl.processors + org.kie.j2cl.tools.processors processors provided diff --git a/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/extras/src/main/java/org/gwtbootstrap3/extras/animate/client/ui/Animate.java b/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/extras/src/main/java/org/gwtbootstrap3/extras/animate/client/ui/Animate.java index ccfda9a084f..74ffac30c3b 100644 --- a/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/extras/src/main/java/org/gwtbootstrap3/extras/animate/client/ui/Animate.java +++ b/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/extras/src/main/java/org/gwtbootstrap3/extras/animate/client/ui/Animate.java @@ -26,7 +26,6 @@ import elemental2.core.JsObject; import elemental2.dom.Event; import elemental2.dom.HTMLElement; -import io.crysknife.ui.common.client.injectors.StyleInjector; import jsinterop.annotations.JsFunction; import jsinterop.annotations.JsMethod; import jsinterop.annotations.JsType; @@ -35,6 +34,7 @@ import org.gwtbootstrap3.client.shared.js.JQuery; import org.gwtbootstrap3.extras.animate.client.ui.constants.Animation; import org.gwtproject.core.client.Scheduler; +import org.kie.j2cl.tools.processors.common.injectors.StyleInjector; import static org.gwtbootstrap3.client.shared.js.JQuery.$; diff --git a/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/extras/src/main/java/org/gwtbootstrap3/extras/notify/client/NotifyClientBundle.java b/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/extras/src/main/java/org/gwtbootstrap3/extras/notify/client/NotifyClientBundle.java index 48f2bb0897f..c8ee3050b8c 100644 --- a/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/extras/src/main/java/org/gwtbootstrap3/extras/notify/client/NotifyClientBundle.java +++ b/packages/serverless-workflow-diagram-editor/third_party/gwtbootstrap3/extras/src/main/java/org/gwtbootstrap3/extras/notify/client/NotifyClientBundle.java @@ -20,9 +20,9 @@ * #L% */ -import org.treblereel.j2cl.processors.annotations.GWT3Resource; -import org.treblereel.j2cl.processors.common.resources.ClientBundle; -import org.treblereel.j2cl.processors.common.resources.TextResource; +import org.kie.j2cl.tools.processors.annotations.GWT3Resource; +import org.kie.j2cl.tools.processors.common.resources.ClientBundle; +import org.kie.j2cl.tools.processors.common.resources.TextResource; @GWT3Resource public interface NotifyClientBundle extends ClientBundle { diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/pom.xml b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/pom.xml deleted file mode 100644 index ec5965d6990..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - org.kie.kogito.stunner.serverless.editor.third_party.jakarta.jsonb - parent - ${revision} - - 4.0.0 - - api - jar - - GWT/J2CL compatible Jakarta JSON-B Specs API - GWT/J2CL compatible Jakarta JSON-B Specs API - - - - - src/main/java - - **/*.java - - - - src/main/resources - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - package - - jar - - - - - - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/EmptyArray.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/EmptyArray.java deleted file mode 100644 index 80f6a8cc7d9..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/EmptyArray.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json; - -import java.io.Serializable; -import java.util.AbstractList; -import java.util.Collections; -import java.util.List; -import java.util.RandomAccess; - -/** - * Private implementation of immutable {@link JsonArray}. - * - * @author Lukas Jungmann - */ -final class EmptyArray extends AbstractList - implements JsonArray, Serializable, RandomAccess { - - private static final long serialVersionUID = 7295439472061642859L; - - @Override - public JsonValue get(int index) { - throw new IndexOutOfBoundsException("Index: " + index); - } - - @Override - public int size() { - return 0; - } - - @Override - public JsonObject getJsonObject(int index) { - return (JsonObject) get(index); - } - - @Override - public JsonArray getJsonArray(int index) { - return (JsonArray) get(index); - } - - @Override - public JsonNumber getJsonNumber(int index) { - return (JsonNumber) get(index); - } - - @Override - public JsonString getJsonString(int index) { - return (JsonString) get(index); - } - - @Override - public List getValuesAs(Class clazz) { - return Collections.emptyList(); - } - - @Override - public String getString(int index) { - return getJsonString(index).getString(); - } - - @Override - public String getString(int index, String defaultValue) { - return defaultValue; - } - - @Override - public int getInt(int index) { - return getJsonNumber(index).intValue(); - } - - @Override - public int getInt(int index, int defaultValue) { - return defaultValue; - } - - @Override - public boolean getBoolean(int index) { - return get(index) == JsonValue.TRUE; - } - - @Override - public boolean getBoolean(int index, boolean defaultValue) { - return defaultValue; - } - - @Override - public boolean isNull(int index) { - return get(index) == JsonValue.NULL; - } - - @Override - public ValueType getValueType() { - return ValueType.ARRAY; - } - - // Preserves singleton property - private Object readResolve() { - return JsonValue.EMPTY_JSON_ARRAY; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/EmptyObject.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/EmptyObject.java deleted file mode 100644 index 4837a00928f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/EmptyObject.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json; - -import java.io.Serializable; -import java.util.AbstractMap; -import java.util.Collections; -import java.util.Set; - -/** - * Private implementation of immutable {@link JsonObject}. - * - * @author Lukas Jungmann - */ -final class EmptyObject extends AbstractMap implements JsonObject, Serializable { - - private static final long serialVersionUID = -1461653546889072583L; - - @Override - public Set> entrySet() { - return Collections.>emptySet(); - } - - @Override - public JsonArray getJsonArray(String name) { - return (JsonArray) get(name); - } - - @Override - public JsonObject getJsonObject(String name) { - return (JsonObject) get(name); - } - - @Override - public JsonNumber getJsonNumber(String name) { - return (JsonNumber) get(name); - } - - @Override - public JsonString getJsonString(String name) { - return (JsonString) get(name); - } - - @Override - public String getString(String name) { - return getJsonString(name).getString(); - } - - @Override - public String getString(String name, String defaultValue) { - return defaultValue; - } - - @Override - public int getInt(String name) { - return getJsonNumber(name).intValue(); - } - - @Override - public int getInt(String name, int defaultValue) { - return defaultValue; - } - - @Override - public boolean getBoolean(String name) { - throw new NullPointerException(); - } - - @Override - public boolean getBoolean(String name, boolean defaultValue) { - return defaultValue; - } - - @Override - public boolean isNull(String name) { - throw new NullPointerException(); - } - - @Override - public ValueType getValueType() { - return ValueType.OBJECT; - } - - // Preserves singleton property - private Object readResolve() { - return JsonValue.EMPTY_JSON_OBJECT; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/GwtIncompatible.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/GwtIncompatible.java deleted file mode 100644 index 6b7a2748892..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/GwtIncompatible.java +++ /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 jakarta.json; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD}) -@Documented -public @interface GwtIncompatible { - String value() default ""; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonArray.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonArray.java deleted file mode 100644 index 3e9f54b3499..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonArray.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json; - -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * {@code JsonArray} represents an immutable JSON array (an ordered sequence of zero or more - * values). It also provides an unmodifiable list view of the values in the array. - * - *

    A {@code JsonArray} object can be created by reading JSON data from an input source or it can - * be built from scratch using an array builder object. - * - *

    The following example demonstrates how to create a {@code JsonArray} object from an input - * source using the method {@link JsonReader#readArray()}: - * - *

    
    - * JsonReader jsonReader = Json.createReader(...);
    - * JsonArray array = jsonReader.readArray();
    - * jsonReader.close();
    - * 
    - * - *

    The following example demonstrates how to build an empty JSON array using the class {@link - * JsonArrayBuilder}: - * - *

    
    - * JsonArray array = Json.createArrayBuilder().build();
    - * 
    - * - *

    The example code below demonstrates how to create the following JSON array: - * - *

    
    - * [
    - *     { "type": "home", "number": "212 555-1234" },
    - *     { "type": "fax", "number": "646 555-4567" }
    - * ]
    - * 
    - * - *
    
    - * JsonArray value = Json.createArrayBuilder()
    - *     .add(Json.createObjectBuilder()
    - *         .add("type", "home")
    - *         .add("number", "212 555-1234"))
    - *     .add(Json.createObjectBuilder()
    - *         .add("type", "fax")
    - *         .add("number", "646 555-4567"))
    - *     .build();
    - * 
    - * - *

    The following example demonstrates how to write a {@code JsonArray} object as JSON data: - * - *

    
    - * JsonArray arr = ...;
    - * JsonWriter writer = Json.createWriter(...)
    - * writer.writeArray(arr);
    - * writer.close();
    - * 
    - * - *

    The values in a {@code JsonArray} can be of the following types: {@link JsonObject}, {@link - * JsonArray}, {@link JsonString}, {@link JsonNumber}, {@link JsonValue#TRUE}, {@link - * JsonValue#FALSE}, and {@link JsonValue#NULL}. {@code JsonArray} provides various accessor methods - * to access the values in an array. - * - *

    The following example shows how to obtain the home phone number "212 555-1234" from the array - * built in the previous example: - * - *

    
    - * JsonObject home = array.getJsonObject(0);
    - * String number = home.getString("number");
    - * 
    - * - *

    {@code JsonArray} instances are list objects that provide read-only access to the values in - * the JSON array. Any attempt to modify the list, whether directly or using its collection views, - * results in an {@code UnsupportedOperationException}. - */ -public interface JsonArray extends JsonStructure, List { - - /** - * Returns the object value at the specified position in this array. This is a convenience method - * for {@code (JsonObject)get(index)}. - * - * @param index index of the value to be returned - * @return the value at the specified position in this array - * @throws IndexOutOfBoundsException if the index is out of range - * @throws ClassCastException if the value at the specified position is not assignable to the - * JsonObject type - */ - JsonObject getJsonObject(int index); - - /** - * Returns the array value at the specified position in this array. This is a convenience method - * for {@code (JsonArray)get(index)}. - * - * @param index index of the value to be returned - * @return the value at the specified position in this array - * @throws IndexOutOfBoundsException if the index is out of range - * @throws ClassCastException if the value at the specified position is not assignable to the - * JsonArray type - */ - JsonArray getJsonArray(int index); - - /** - * Returns the number value at the specified position in this array. This is a convenience method - * for {@code (JsonNumber)get(index)}. - * - * @param index index of the value to be returned - * @return the value at the specified position in this array - * @throws IndexOutOfBoundsException if the index is out of range - * @throws ClassCastException if the value at the specified position is not assignable to the - * JsonNumber type - */ - JsonNumber getJsonNumber(int index); - - /** - * Returns the string value at ths specified position in this array. This is a convenience method - * for {@code (JsonString)get(index)}. - * - * @param index index of the value to be returned - * @return the value at the specified position in this array - * @throws IndexOutOfBoundsException if the index is out of range - * @throws ClassCastException if the value at the specified position is not assignable to the - * JsonString type - */ - JsonString getJsonString(int index); - - /** - * Returns a list view of the specified type for the array. This method does not verify if there - * is a value of wrong type in the array. Providing this typesafe view dynamically may cause a - * program fail with a {@code ClassCastException}, if there is a value of wrong type in this - * array. Unfortunately, the exception can occur at any time after this method returns. - * - * @param The type of the List for the array - * @param clazz a JsonValue type - * @return a list view of the specified type - */ - List getValuesAs(Class clazz); - - /** - * Returns a list view for the array. The value and the type of the elements in the list is - * specified by the {@code func} argument. - * - *

    This method can be used to obtain a list of the unwrapped types, such as - * - *

    {@code
    -   * List strings = ary1.getValuesAs(JsonString::getString);
    -   * List ints = ary2.getValuesAs(JsonNumber::intValue);
    -   * }
    - * - * or a list of simple projections, such as - * - *
    {@code
    -   * List stringsizes = ary1.getValueAs((JsonString v)->v.getString().length();
    -   * }
    - * - * @param The element type (must be a subtype of JsonValue) of this JsonArray. - * @param The element type of the returned List - * @param func The function that maps the elements of this JsonArray to the target elements. - * @return A List of the specified values and type. - * @throws ClassCastException if the {@code JsonArray} contains a value of wrong type - * @since 1.1 - */ - default List getValuesAs(Function func) { - @SuppressWarnings("unchecked") - Stream stream = (Stream) stream(); - return stream.map(func).collect(Collectors.toList()); - } - - /** - * A convenience method for {@code getJsonString(index).getString()}. - * - * @param index index of the {@code JsonString} value - * @return the String value at the specified position - * @throws IndexOutOfBoundsException if the index is out of range - * @throws ClassCastException if the value at the specified position is not assignable to {@code - * JsonString} - */ - String getString(int index); - - /** - * Returns the {@code String} value of {@code JsonString} at the specified position in this JSON - * array values. If {@code JsonString} is found, its {@link jakarta.json.JsonString#getString()} - * is returned. Otherwise, the specified default value is returned. - * - * @param index index of the {@code JsonString} value - * @param defaultValue the String to return if the {@code JsonValue} at the specified position is - * not a {@code JsonString} - * @return the String value at the specified position in this array, or the specified default - * value - */ - String getString(int index, String defaultValue); - - /** - * A convenience method for {@code getJsonNumber(index).intValue()}. - * - * @param index index of the {@code JsonNumber} value - * @return the int value at the specified position - * @throws IndexOutOfBoundsException if the index is out of range - * @throws ClassCastException if the value at the specified position is not assignable to {@code - * JsonNumber} - */ - int getInt(int index); - - /** - * Returns the int value of the {@code JsonNumber} at the specified position. If the value at that - * position is a {@code JsonNumber}, this method returns {@link - * jakarta.json.JsonNumber#intValue()}. Otherwise this method returns the specified default value. - * - * @param index index of the {@code JsonNumber} value - * @param defaultValue the int value to return if the {@code JsonValue} at the specified position - * is not a {@code JsonNumber} - * @return the int value at the specified position in this array, or the specified default value - */ - int getInt(int index, int defaultValue); - - /** - * Returns the boolean value at the specified position. If the value at the specified position is - * {@code JsonValue.TRUE} this method returns {@code true}. If the value at the specified position - * is {@code JsonValue.FALSE} this method returns {@code false}. - * - * @param index index of the JSON boolean value - * @return the boolean value at the specified position - * @throws IndexOutOfBoundsException if the index is out of range - * @throws ClassCastException if the value at the specified position is not assignable to {@code - * JsonValue.TRUE} or {@code JsonValue.FALSE} - */ - boolean getBoolean(int index); - - /** - * Returns the boolean value at the specified position. If the value at the specified position is - * {@code JsonValue.TRUE} this method returns {@code true}. If the value at the specified position - * is {@code JsonValue.FALSE} this method returns {@code false}. Otherwise this method returns the - * specified default value. - * - * @param index index of the JSON boolean value - * @param defaultValue the boolean value to return if the {@code JsonValue} at the specified - * position is neither TRUE nor FALSE - * @return the boolean value at the specified position, or the specified default value - */ - boolean getBoolean(int index, boolean defaultValue); - - /** - * Returns {@code true} if the value at the specified location in this array is {@code - * JsonValue.NULL}. - * - * @param index index of the JSON null value - * @return return true if the value at the specified location is {@code JsonValue.NULL}, otherwise - * false - * @throws IndexOutOfBoundsException if the index is out of range - */ - boolean isNull(int index); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonArrayBuilder.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonArrayBuilder.java deleted file mode 100644 index 7b12d39cf2b..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonArrayBuilder.java +++ /dev/null @@ -1,571 +0,0 @@ -/* - * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json; - -import java.math.BigDecimal; -import java.math.BigInteger; - -/** - * A builder for creating {@link JsonArray} models from scratch, and for modifying a existing {@code - * JsonArray}. - * - *

    A {@code JsonArrayBuilder} can start with an empty or a non-empty JSON array model. This - * interface provides methods to add, insert, remove and replace values in the JSON array model. - * - *

    Methods in this class can be chained to perform multiple values to the array. - * - *

    The class {@link jakarta.json.Json} contains methods to create the builder object. The example - * code below shows how to build an empty {@code JsonArray} instance. - * - *

    - * 
    - * JsonArray array = Json.createArrayBuilder().build();
    - * 
    - * 
    - * - *

    The class {@link JsonBuilderFactory} also contains methods to create {@code JsonArrayBuilder} - * instances. A factory instance can be used to create multiple builder instances with the same - * configuration. This the preferred way to create multiple instances. - * - *

    The example code below shows how to build a {@code JsonArray} object that represents the - * following JSON array: - * - *

    - * 
    - * [
    - *     { "type": "home", "number": "212 555-1234" },
    - *     { "type": "fax", "number": "646 555-4567" }
    - * ]
    - * 
    - * 
    - * - *

    The following code creates the JSON array above: - * - *

    - * 
    - * JsonBuilderFactory factory = Json.createBuilderFactory(config);
    - * JsonArray value = factory.createArrayBuilder()
    - *     .add(factory.createObjectBuilder()
    - *         .add("type", "home")
    - *         .add("number", "212 555-1234"))
    - *     .add(factory.createObjectBuilder()
    - *         .add("type", "fax")
    - *         .add("number", "646 555-4567"))
    - *     .build();
    - * 
    - * 
    - * - *

    This class does not allow null to be used as a value while building the - * JSON array - * - * @see JsonObjectBuilder - */ -public interface JsonArrayBuilder { - - /** - * Adds a value to the array. - * - * @param value the JSON value - * @return this array builder - * @throws NullPointerException if the specified value is null - */ - JsonArrayBuilder add(JsonValue value); - - /** - * Adds a value to the array as a {@link JsonString}. - * - * @param value the string value - * @return this array builder - * @throws NullPointerException if the specified value is null - */ - JsonArrayBuilder add(String value); - - /** - * Adds a value to the array as a {@link JsonNumber}. - * - * @param value the number value - * @return this array builder - * @throws NullPointerException if the specified value is null - * @see JsonNumber - */ - JsonArrayBuilder add(BigDecimal value); - - /** - * Adds a value to the array as a {@link JsonNumber}. - * - * @param value the number value - * @return this array builder - * @throws NullPointerException if the specified value is null - * @see JsonNumber - */ - JsonArrayBuilder add(BigInteger value); - - /** - * Adds a value to the array as a {@link JsonNumber}. - * - * @param value the number value - * @return this array builder - * @see JsonNumber - */ - JsonArrayBuilder add(int value); - - /** - * Adds a value to the array as a {@link JsonNumber}. - * - * @param value the number value - * @return this array builder - * @see JsonNumber - */ - JsonArrayBuilder add(long value); - - /** - * Adds a value to the array as a {@link JsonNumber}. - * - * @param value the number value - * @return this array builder - * @throws NumberFormatException if the value is Not-a-Number (NaN) or infinity - * @see JsonNumber - */ - JsonArrayBuilder add(double value); - - /** - * Adds a {@link JsonValue#TRUE} or {@link JsonValue#FALSE} value to the array. - * - * @param value the boolean value - * @return this array builder - */ - JsonArrayBuilder add(boolean value); - - /** - * Adds a {@link JsonValue#NULL} value to the array. - * - * @return this array builder - */ - JsonArrayBuilder addNull(); - - /** - * Adds a {@link JsonObject} from an object builder to the array. - * - * @param builder the object builder - * @return this array builder - * @throws NullPointerException if the specified builder is null - */ - JsonArrayBuilder add(JsonObjectBuilder builder); - - /** - * Adds a {@link JsonArray} from an array builder to the array. - * - * @param builder the array builder - * @return this array builder - * @throws NullPointerException if the specified builder is null - */ - JsonArrayBuilder add(JsonArrayBuilder builder); - - /** - * Adds all elements of the array in the specified array builder to the array. - * - * @param builder the array builder - * @return this array builder - * @throws NullPointerException if the specified builder is null - * @since 1.1 - */ - default JsonArrayBuilder addAll(JsonArrayBuilder builder) { - throw new UnsupportedOperationException(); - } - - /** - * Inserts a value to the array at the specified position. Shifts the value currently at that - * position (if any) and any subsequent values to the right (adds one to their indices). Index - * starts with 0. - * - * @param index the position in the array - * @param value the JSON value - * @return this array builder - * @throws NullPointerException if the specified value is null - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index > - * array size)} - * @since 1.1 - */ - default JsonArrayBuilder add(int index, JsonValue value) { - throw new UnsupportedOperationException(); - } - - /** - * Adds a value to the array as a {@link JsonString} at the specified position. Shifts the value - * currently at that position (if any) and any subsequent values to the right (adds one to their - * indices). Index starts with 0. - * - * @param index the position in the array - * @param value the string value - * @return this array builder - * @throws NullPointerException if the specified value is null - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index > - * array size)} - * @since 1.1 - */ - default JsonArrayBuilder add(int index, String value) { - throw new UnsupportedOperationException(); - } - - /** - * Adds a value to the array as a {@link JsonNumber} at the specified position. Shifts the value - * currently at that position (if any) and any subsequent values to the right (adds one to their - * indices). Index starts with 0. - * - * @param index the position in the array - * @param value the number value - * @return this array builder - * @throws NullPointerException if the specified value is null - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index > - * array size)} - * @see JsonNumber - * @since 1.1 - */ - default JsonArrayBuilder add(int index, BigDecimal value) { - throw new UnsupportedOperationException(); - } - - /** - * Adds a value to the array as a {@link JsonNumber} at the specified position. Shifts the value - * currently at that position (if any) and any subsequent values to the right (adds one to their - * indices). Index starts with 0. - * - * @param index the position in the array - * @param value the number value - * @return this array builder - * @throws NullPointerException if the specified value is null - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index > - * array size)} - * @see JsonNumber - * @since 1.1 - */ - default JsonArrayBuilder add(int index, BigInteger value) { - throw new UnsupportedOperationException(); - } - - /** - * Adds a value to the array as a {@link JsonNumber} at the specified position. Shifts the value - * currently at that position (if any) and any subsequent values to the right (adds one to their - * indices). Index starts with 0. - * - * @param index the position in the array - * @param value the number value - * @return this array builder - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index > - * array size)} - * @see JsonNumber - * @since 1.1 - */ - default JsonArrayBuilder add(int index, int value) { - throw new UnsupportedOperationException(); - } - - /** - * Adds a value to the array as a {@link JsonNumber} at the specified position. Shifts the value - * currently at that position (if any) and any subsequent values to the right (adds one to their - * indices). Index starts with 0. - * - * @param index the position in the array - * @param value the number value - * @return this array builder - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index > - * array size)} - * @see JsonNumber - * @since 1.1 - */ - default JsonArrayBuilder add(int index, long value) { - throw new UnsupportedOperationException(); - } - - /** - * Adds a value to the array as a {@link JsonNumber} at the specified position. Shifts the value - * currently at that position (if any) and any subsequent values to the right (adds one to their - * indices). Index starts with 0. - * - * @param index the position in the array - * @param value the number value - * @return this array builder - * @throws NumberFormatException if the value is Not-a-Number (NaN) or infinity - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index > - * array size)} - * @see JsonNumber - * @since 1.1 - */ - default JsonArrayBuilder add(int index, double value) { - throw new UnsupportedOperationException(); - } - - /** - * Adds a {@link JsonValue#TRUE} or {@link JsonValue#FALSE} value to the array at the specified - * position. Shifts the value currently at that position (if any) and any subsequent values to the - * right (adds one to their indices). Index starts with 0. - * - * @param index the position in the array - * @param value the boolean value - * @return this array builder - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index > - * array size)} - * @since 1.1 - */ - default JsonArrayBuilder add(int index, boolean value) { - throw new UnsupportedOperationException(); - } - - /** - * Adds a {@link JsonValue#NULL} value to the array at the specified position. Shifts the value - * currently at that position (if any) and any subsequent values to the right (adds one to their - * indices). Index starts with 0. - * - * @param index the position in the array - * @return this array builder - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index > - * array size)} - * @since 1.1 - */ - default JsonArrayBuilder addNull(int index) { - return add(index, JsonValue.NULL); - } - - /** - * Adds a {@link JsonObject} from an object builder to the array at the specified position. Shifts - * the value currently at that position (if any) and any subsequent values to the right (adds one - * to their indices). Index starts with 0. - * - * @param index the position in the array - * @param builder the object builder - * @return this array builder - * @throws NullPointerException if the specified builder is null - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index > - * array size)} - * @since 1.1 - */ - default JsonArrayBuilder add(int index, JsonObjectBuilder builder) { - throw new UnsupportedOperationException(); - } - - /** - * Adds a {@link JsonArray} from an array builder to the array at the specified position. Shifts - * the value currently at that position (if any) and any subsequent values to the right (adds one - * to their indices). Index starts with 0. - * - * @param index the position in the array - * @param builder the array builder - * @return this array builder - * @throws NullPointerException if the specified builder is null - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index > - * array size)} - * @since 1.1 - */ - default JsonArrayBuilder add(int index, JsonArrayBuilder builder) { - throw new UnsupportedOperationException(); - } - - /** - * Replaces a value in the array with the specified value at the specified position. - * - * @param index the position in the array - * @param value the JSON value - * @return this array builder - * @throws NullPointerException if the specified value is null - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index >= - * array size)} - * @since 1.1 - */ - default JsonArrayBuilder set(int index, JsonValue value) { - throw new UnsupportedOperationException(); - } - - /** - * Replaces a value in the array with the specified value as a {@link JsonString} at the specified - * position. - * - * @param index the position in the array - * @param value the string value - * @return this array builder - * @throws NullPointerException if the specified value is null - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index >= - * array size)} - * @since 1.1 - */ - default JsonArrayBuilder set(int index, String value) { - throw new UnsupportedOperationException(); - } - - /** - * Replaces a value in the array with the specified value as a {@link JsonNumber} at the specified - * position. - * - * @param index the position in the array - * @param value the number value - * @return this array builder - * @throws NullPointerException if the specified value is null - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index >= - * array size)} - * @see JsonNumber - * @since 1.1 - */ - default JsonArrayBuilder set(int index, BigDecimal value) { - throw new UnsupportedOperationException(); - } - - /** - * Replaces a value in the array with the specified value as a {@link JsonNumber} at the specified - * position. - * - * @param index the position in the array - * @param value the number value - * @return this array builder - * @throws NullPointerException if the specified value is null - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index >= - * array size)} - * @see JsonNumber - * @since 1.1 - */ - default JsonArrayBuilder set(int index, BigInteger value) { - throw new UnsupportedOperationException(); - } - - /** - * Replaces a value in the array with the specified value as a {@link JsonNumber} at the specified - * position. - * - * @param index the position in the array - * @param value the number value - * @return this array builder - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index >= - * array size)} - * @see JsonNumber - * @since 1.1 - */ - default JsonArrayBuilder set(int index, int value) { - throw new UnsupportedOperationException(); - } - - /** - * Replaces a value in the array with the specified value as a {@link JsonNumber} at the specified - * position. - * - * @param index the position in the array - * @param value the number value - * @return this array builder - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index >= - * array size)} - * @see JsonNumber - * @since 1.1 - */ - default JsonArrayBuilder set(int index, long value) { - throw new UnsupportedOperationException(); - } - - /** - * Replaces a value in the array with the specified value as a {@link JsonNumber} at the specified - * position. - * - * @param index the position in the array - * @param value the number value - * @return this array builder - * @throws NumberFormatException if the value is Not-a-Number (NaN) or infinity - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index >= - * array size)} - * @see JsonNumber - * @since 1.1 - */ - default JsonArrayBuilder set(int index, double value) { - throw new UnsupportedOperationException(); - } - - /** - * Replaces a value in the array with a {@link JsonValue#TRUE} or {@link JsonValue#FALSE} value at - * the specified position. - * - * @param index the position in the array - * @param value the boolean value - * @return this array builder - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index >= - * array size)} - * @since 1.1 - */ - default JsonArrayBuilder set(int index, boolean value) { - throw new UnsupportedOperationException(); - } - - /** - * Replaces a value in the array with a {@link JsonValue#NULL} value at the specified position. - * - * @param index the position in the array - * @return this array builder - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index >= - * array size)} - * @since 1.1 - */ - default JsonArrayBuilder setNull(int index) { - return set(index, JsonValue.NULL); - } - - /** - * Replaces a value in the array with the specified value as a {@link JsonObject} from an object - * builder at the specified position. - * - * @param index the position in the array - * @param builder the object builder - * @return this array builder - * @throws NullPointerException if the specified builder is null - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index >= - * array size)} - * @since 1.1 - */ - default JsonArrayBuilder set(int index, JsonObjectBuilder builder) { - throw new UnsupportedOperationException(); - } - - /** - * Replaces a value in the array with the specified value as a {@link JsonArray} from an array - * builder at the specified position. - * - * @param index the position in the array - * @param builder the array builder - * @return this array builder - * @throws NullPointerException if the specified builder is null - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index >= - * array size)} - * @since 1.1 - */ - default JsonArrayBuilder set(int index, JsonArrayBuilder builder) { - throw new UnsupportedOperationException(); - } - - /** - * Remove the value in the array at the specified position. Shift any subsequent values to the - * left (subtracts one from their indices. - * - * @param index the position in the array - * @return this array builder - * @throws IndexOutOfBoundsException if the index is out of range {@code (index < 0 || index >= - * array size)} - * @since 1.1 - */ - default JsonArrayBuilder remove(int index) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the current array. - * - * @return the current JSON array - */ - JsonArray build(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonException.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonException.java deleted file mode 100644 index 41201aaaf77..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonException.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json; - -/** JsonException indicates that some exception happened during JSON processing. */ -public class JsonException extends RuntimeException { - - /** - * Constructs a new runtime exception with the specified detail message. The cause is not - * initialized, and may subsequently be initialized by a call to {@link #initCause}. - * - * @param message the detail message. The detail message is saved for later retrieval by the - * {@link #getMessage()} method. - */ - public JsonException(String message) { - super(message); - } - - /** - * Constructs a new runtime exception with the specified detail message and cause. - * - *

    Note that the detail message associated with {@code cause} is not automatically - * incorporated in this runtime exception's detail message. - * - * @param message the detail message (which is saved for later retrieval by the {@link - * #getMessage()} method). - * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). - * (A null value is permitted, and indicates that the cause is nonexistent or - * unknown.) - */ - public JsonException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonNumber.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonNumber.java deleted file mode 100644 index bfe4bdf2f6f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonNumber.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json; - -import java.math.BigDecimal; -import java.math.BigInteger; - -/** - * An immutable JSON number value. - * - *

    Implementations may use a {@link BigDecimal} object to store the numeric value internally. The - * {@code BigDecimal} object can be constructed from the following types: int {@link - * BigDecimal#BigDecimal(int)}, long {@link BigDecimal#BigDecimal(long)}, - * BigInteger {@link BigDecimal#BigDecimal(BigInteger)}, double {@link - * BigDecimal#valueOf(double)}, and String {@link BigDecimal#BigDecimal(String)}. Some - * of the method semantics in this class are defined using the {@code BigDecimal} semantics. - */ -public interface JsonNumber extends JsonValue { - - /** - * Returns true if this JSON number is a integral number. This method semantics are defined using - * {@code bigDecimalValue().scale()}. If the scale is zero, then it is considered integral type. - * This integral type information can be used to invoke an appropriate accessor method to obtain a - * numeric value as in the following example: - * - *

    -   * 
    -   * JsonNumber num = ...
    -   * if (num.isIntegral()) {
    -   *     num.longValue();     // or other methods to get integral value
    -   * } else {
    -   *     num.doubleValue();   // or other methods to get decimal number value
    -   * }
    -   * 
    -   * 
    - * - * @return true if this number is a integral number, otherwise false - */ - boolean isIntegral(); - - /** - * Returns this JSON number as an {@code int}. Note that this conversion can lose information - * about the overall magnitude and precision of the number value as well as return a result with - * the opposite sign. - * - * @return an {@code int} representation of the JSON number - * @see java.math.BigDecimal#intValue() - */ - int intValue(); - - /** - * Returns this JSON number as an {@code int}. - * - * @return an {@code int} representation of the JSON number - * @throws ArithmeticException if the number has a nonzero fractional part or if it does not fit - * in an {@code int} - * @see java.math.BigDecimal#intValueExact() - */ - int intValueExact(); - - /** - * Returns this JSON number as a {@code long}. Note that this conversion can lose information - * about the overall magnitude and precision of the number value as well as return a result with - * the opposite sign. - * - * @return a {@code long} representation of the JSON number. - * @see java.math.BigDecimal#longValue() - */ - long longValue(); - - /** - * Returns this JSON number as a {@code long}. - * - * @return a {@code long} representation of the JSON number - * @throws ArithmeticException if the number has a non-zero fractional part or if it does not fit - * in a {@code long} - * @see java.math.BigDecimal#longValueExact() - */ - long longValueExact(); - - /** - * Returns this JSON number as a {@link BigInteger} object. This is a a convenience method for - * {@code bigDecimalValue().toBigInteger()}. Note that this conversion can lose information about - * the overall magnitude and precision of the number value as well as return a result with the - * opposite sign. - * - * @return a {@code BigInteger} representation of the JSON number. - * @see java.math.BigDecimal#toBigInteger() - */ - BigInteger bigIntegerValue(); - - /** - * Returns this JSON number as a {@link BigInteger} object. This is a convenience method for - * {@code bigDecimalValue().toBigIntegerExact()}. - * - * @return a {@link BigInteger} representation of the JSON number - * @throws ArithmeticException if the number has a nonzero fractional part - * @see java.math.BigDecimal#toBigIntegerExact() - */ - BigInteger bigIntegerValueExact(); - - /** - * Returns this JSON number as a {@code double}. This is a a convenience method for {@code - * bigDecimalValue().doubleValue()}. Note that this conversion can lose information about the - * overall magnitude and precision of the number value as well as return a result with the - * opposite sign. - * - * @return a {@code double} representation of the JSON number - * @see java.math.BigDecimal#doubleValue() - */ - double doubleValue(); - - /** - * Returns this JSON number as a {@link BigDecimal} object. - * - * @return a {@link BigDecimal} representation of the JSON number - */ - BigDecimal bigDecimalValue(); - - /** - * Returns this JSON number as a {@link Number} object. - * - * @return a {@link Number} representation of the JSON number - * @since 1.1 - */ - default Number numberValue() { - throw new UnsupportedOperationException(); - } - - /** - * Returns a JSON text representation of the JSON number. The representation is equivalent to - * {@link BigDecimal#toString()}. - * - * @return JSON text representation of the number - */ - @Override - String toString(); - - /** - * Compares the specified object with this {@code JsonNumber} object for equality. Returns {@code - * true} if and only if the type of the specified object is also {@code JsonNumber} and their - * {@link #bigDecimalValue()} objects are equal - * - * @param obj the object to be compared for equality with this {@code JsonNumber} - * @return {@code true} if the specified object is equal to this {@code JsonNumber} - */ - @Override - boolean equals(Object obj); - - /** - * Returns the hash code value for this {@code JsonNumber} object. The hash code of a {@code - * JsonNumber} object is defined as the hash code of its {@link #bigDecimalValue()} object. - * - * @return the hash code value for this {@code JsonNumber} object - */ - @Override - int hashCode(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonObject.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonObject.java deleted file mode 100644 index 51a86f6b41e..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonObject.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json; - -import java.util.Map; - -/** - * {@code JsonObject} class represents an immutable JSON object value (an unordered collection of - * zero or more name/value pairs). It also provides unmodifiable map view to the JSON object - * name/value mappings. - * - *

    A JsonObject instance can be created from an input source using {@link - * JsonReader#readObject()}. For example: - * - *

    
    - * JsonReader jsonReader = Json.createReader(...);
    - * JsonObject object = jsonReader.readObject();
    - * jsonReader.close();
    - * 
    - * - * It can also be built from scratch using a {@link JsonObjectBuilder}. - * - *

    For example 1: An empty JSON object can be built as follows: - * - *

    
    - * JsonObject object = Json.createObjectBuilder().build();
    - * 
    - * - * For example 2: The following JSON - * - *
    
    - * {
    - *     "firstName": "John", "lastName": "Smith", "age": 25,
    - *     "address" : {
    - *         "streetAddress": "21 2nd Street",
    - *         "city": "New York",
    - *         "state": "NY",
    - *         "postalCode": "10021"
    - *     },
    - *     "phoneNumber": [
    - *         { "type": "home", "number": "212 555-1234" },
    - *         { "type": "fax", "number": "646 555-4567" }
    - *     ]
    - * }
    - * 
    - * - * can be built using : - * - *
    
    - * JsonObject value = Json.createObjectBuilder()
    - *     .add("firstName", "John")
    - *     .add("lastName", "Smith")
    - *     .add("age", 25)
    - *     .add("address", Json.createObjectBuilder()
    - *         .add("streetAddress", "21 2nd Street")
    - *         .add("city", "New York")
    - *         .add("state", "NY")
    - *         .add("postalCode", "10021"))
    - *     .add("phoneNumber", Json.createArrayBuilder()
    - *         .add(Json.createObjectBuilder()
    - *             .add("type", "home")
    - *             .add("number", "212 555-1234"))
    - *         .add(Json.createObjectBuilder()
    - *             .add("type", "fax")
    - *             .add("number", "646 555-4567")))
    - *     .build();
    - * 
    - * - * {@code JsonObject} can be written to JSON as follows: - * - *
    
    - * JsonWriter writer = ...
    - * JsonObject obj = ...;
    - * writer.writeObject(obj);
    - * 
    - * - * {@code JsonObject} values can be {@link JsonObject}, {@link JsonArray}, {@link JsonString}, - * {@link JsonNumber}, {@link JsonValue#TRUE}, {@link JsonValue#FALSE}, {@link JsonValue#NULL}. - * These values can be accessed using various accessor methods. - * - *

    In the above example 2, "John" can be got using - * - *

    
    - * String firstName = object.getString("firstName");
    - * 
    - * - * This map object provides read-only access to the JSON object data, and attempts to modify the - * map, whether direct or via its collection views, result in an {@code - * UnsupportedOperationException}. - * - *

    The map object's iteration ordering is based on the order in which name/value pairs are added - * to the corresponding builder or the order in which name/value pairs appear in the corresponding - * stream. - */ -public interface JsonObject extends JsonStructure, Map { - - /** - * Returns the array value to which the specified name is mapped. This is a convenience method for - * {@code (JsonArray)get(name)} to get the value. - * - * @param name the name whose associated value is to be returned - * @return the array value to which the specified name is mapped, or {@code null} if this object - * contains no mapping for the name - * @throws ClassCastException if the value to which the specified name is mapped is not assignable - * to JsonArray type - */ - JsonArray getJsonArray(String name); - - /** - * Returns the object value to which the specified name is mapped. This is a convenience method - * for {@code (JsonObject)get(name)} to get the value. - * - * @param name the name whose associated value is to be returned - * @return the object value to which the specified name is mapped, or {@code null} if this object - * contains no mapping for the name - * @throws ClassCastException if the value to which the specified name is mapped is not assignable - * to JsonObject type - */ - JsonObject getJsonObject(String name); - - /** - * Returns the number value to which the specified name is mapped. This is a convenience method - * for {@code (JsonNumber)get(name)} to get the value. - * - * @param name the name whose associated value is to be returned - * @return the number value to which the specified name is mapped, or {@code null} if this object - * contains no mapping for the name - * @throws ClassCastException if the value to which the specified name is mapped is not assignable - * to JsonNumber type - */ - JsonNumber getJsonNumber(String name); - - /** - * Returns the string value to which the specified name is mapped. This is a convenience method - * for {@code (JsonString)get(name)} to get the value. - * - * @param name the name whose associated value is to be returned - * @return the string value to which the specified name is mapped, or {@code null} if this object - * contains no mapping for the name - * @throws ClassCastException if the value to which the specified name is mapped is not assignable - * to JsonString type - */ - JsonString getJsonString(String name); - - /** - * A convenience method for {@code getJsonString(name).getString()} - * - * @param name whose associated value is to be returned as String - * @return the String value to which the specified name is mapped - * @throws NullPointerException if the specified name doesn't have any mapping - * @throws ClassCastException if the value for specified name mapping is not assignable to - * JsonString - */ - String getString(String name); - - /** - * Returns the string value of the associated {@code JsonString} mapping for the specified name. - * If {@code JsonString} is found, then its {@link jakarta.json.JsonString#getString()} is - * returned. Otherwise, the specified default value is returned. - * - * @param name whose associated value is to be returned as String - * @param defaultValue a default value to be returned - * @return the string value of the associated mapping for the name, or the default value - */ - String getString(String name, String defaultValue); - - /** - * A convenience method for {@code getJsonNumber(name).intValue()} - * - * @param name whose associated value is to be returned as int - * @return the int value to which the specified name is mapped - * @throws NullPointerException if the specified name doesn't have any mapping - * @throws ClassCastException if the value for specified name mapping is not assignable to - * JsonNumber - */ - int getInt(String name); - - /** - * Returns the int value of the associated {@code JsonNumber} mapping for the specified name. If - * {@code JsonNumber} is found, then its {@link jakarta.json.JsonNumber#intValue()} is returned. - * Otherwise, the specified default value is returned. - * - * @param name whose associated value is to be returned as int - * @param defaultValue a default value to be returned - * @return the int value of the associated mapping for the name, or the default value - */ - int getInt(String name, int defaultValue); - - /** - * Returns the boolean value of the associated mapping for the specified name. If the associated - * mapping is JsonValue.TRUE, then returns true. If the associated mapping is JsonValue.FALSE, - * then returns false. - * - * @param name whose associated value is to be returned as boolean - * @return the boolean value to which the specified name is mapped - * @throws NullPointerException if the specified name doesn't have any mapping - * @throws ClassCastException if the value for specified name mapping is not assignable to - * JsonValue.TRUE or JsonValue.FALSE - */ - boolean getBoolean(String name); - - /** - * Returns the boolean value of the associated mapping for the specified name. If the associated - * mapping is JsonValue.TRUE, then returns true. If the associated mapping is JsonValue.FALSE, - * then returns false. Otherwise, the specified default value is returned. - * - * @param name whose associated value is to be returned as int - * @param defaultValue a default value to be returned - * @return the boolean value of the associated mapping for the name, or the default value - */ - boolean getBoolean(String name, boolean defaultValue); - - /** - * Returns {@code true} if the associated value for the specified name is {@code JsonValue.NULL}. - * - * @param name name whose associated value is checked - * @return return true if the associated value is {@code JsonValue.NULL}, otherwise false - * @throws NullPointerException if the specified name doesn't have any mapping - */ - boolean isNull(String name); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonObjectBuilder.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonObjectBuilder.java deleted file mode 100644 index 446205a8218..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonObjectBuilder.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json; - -import java.math.BigDecimal; -import java.math.BigInteger; - -/** - * A builder for creating {@link JsonObject} models from scratch. This interface initializes an - * empty JSON object model and provides methods to add name/value pairs to the object model and to - * return the resulting object. The methods in this class can be chained to add multiple name/value - * pairs to the object. - * - *

    The class {@link jakarta.json.Json} contains methods to create the builder object. The example - * code below shows how to build an empty {@code JsonObject} instance. - * - *

    - * 
    - * JsonObject object = Json.createObjectBuilder().build();
    - * 
    - * 
    - * - *

    The class {@link JsonBuilderFactory} also contains methods to create {@code JsonObjectBuilder} - * instances. A factory instance can be used to create multiple builder instances with the same - * configuration. This the preferred way to create multiple instances. - * - *

    The example code below shows how to build a {@code JsonObject} model that represents the - * following JSON object: - * - *

    - * 
    - * {
    - *     "firstName": "John", "lastName": "Smith", "age": 25,
    - *     "address" : {
    - *         "streetAddress": "21 2nd Street",
    - *         "city": "New York",
    - *         "state": "NY",
    - *         "postalCode": "10021"
    - *     },
    - *     "phoneNumber": [
    - *         { "type": "home", "number": "212 555-1234" },
    - *         { "type": "fax", "number": "646 555-4567" }
    - *     ]
    - * }
    - * 
    - * 
    - * - *

    The code to create the object shown above is the following: - * - *

    - * 
    - * JsonBuilderFactory factory = Json.createBuilderFactory(config);
    - * JsonObject value = factory.createObjectBuilder()
    - *     .add("firstName", "John")
    - *     .add("lastName", "Smith")
    - *     .add("age", 25)
    - *     .add("address", factory.createObjectBuilder()
    - *         .add("streetAddress", "21 2nd Street")
    - *         .add("city", "New York")
    - *         .add("state", "NY")
    - *         .add("postalCode", "10021"))
    - *     .add("phoneNumber", factory.createArrayBuilder()
    - *         .add(factory.createObjectBuilder()
    - *             .add("type", "home")
    - *             .add("number", "212 555-1234"))
    - *         .add(factory.createObjectBuilder()
    - *             .add("type", "fax")
    - *             .add("number", "646 555-4567")))
    - *     .build();
    - * 
    - * 
    - * - *

    This class does not allow null to be used as a name or value while - * building the JSON object - * - * @see JsonArrayBuilder - */ -public interface JsonObjectBuilder { - - /** - * Adds a name/{@code JsonValue} pair to the JSON object associated with this object builder. If - * the object contains a mapping for the specified name, this method replaces the old value with - * the specified value. - * - * @param name name in the name/value pair - * @param value value in the name/value pair - * @return this object builder - * @throws NullPointerException if the specified name or value is null - */ - JsonObjectBuilder add(String name, JsonValue value); - - /** - * Adds a name/{@code JsonString} pair to the JSON object associated with this object builder. If - * the object contains a mapping for the specified name, this method replaces the old value with - * the specified value. - * - * @param name name in the name/value pair - * @param value value in the name/value pair - * @return this object builder - * @throws NullPointerException if the specified name or value is null - */ - JsonObjectBuilder add(String name, String value); - - /** - * Adds a name/{@code JsonNumber} pair to the JSON object associated with this object builder. If - * the object contains a mapping for the specified name, this method replaces the old value with - * the specified value. - * - * @param name name in the name/value pair - * @param value value in the name/value pair - * @return this object builder - * @throws NullPointerException if the specified name or value is null - * @see JsonNumber - */ - JsonObjectBuilder add(String name, BigInteger value); - - /** - * Adds a name/{@code JsonNumber} pair to the JSON object associated with this object builder. If - * the object contains a mapping for the specified name, this method replaces the old value with - * the specified value. - * - * @param name name in the name/value pair - * @param value value in the name/value pair - * @return this object builder - * @throws NullPointerException if the specified name or value is null - * @see JsonNumber - */ - JsonObjectBuilder add(String name, BigDecimal value); - - /** - * Adds a name/{@code JsonNumber} pair to the JSON object associated with this object builder. If - * the object contains a mapping for the specified name, this method replaces the old value with - * the specified value. - * - * @param name name in the name/value pair - * @param value value in the name/value pair - * @return this object builder - * @throws NullPointerException if the specified name is null - * @see JsonNumber - */ - JsonObjectBuilder add(String name, int value); - - /** - * Adds a name/{@code JsonNumber} pair to the JSON object associated with this object builder. If - * the object contains a mapping for the specified name, this method replaces the old value with - * the specified value. - * - * @param name name in the name/value pair - * @param value value in the name/value pair - * @return this object builder - * @throws NullPointerException if the specified name is null - * @see JsonNumber - */ - JsonObjectBuilder add(String name, long value); - - /** - * Adds a name/{@code JsonNumber} pair to the JSON object associated with this object builder. If - * the object contains a mapping for the specified name, this method replaces the old value with - * the specified value. - * - * @param name name in the name/value pair - * @param value value in the name/value pair - * @return this object builder - * @throws NumberFormatException if the value is Not-a-Number (NaN) or infinity - * @throws NullPointerException if the specified name is null - * @see JsonNumber - */ - JsonObjectBuilder add(String name, double value); - - /** - * Adds a name/{@code JsonValue#TRUE} or name/{@code JsonValue#FALSE} pair to the JSON object - * associated with this object builder. If the object contains a mapping for the specified name, - * this method replaces the old value with the specified value. - * - * @param name name in the name/value pair - * @param value value in the name/value pair - * @return this object builder - * @throws NullPointerException if the specified name is null - */ - JsonObjectBuilder add(String name, boolean value); - - /** - * Adds a name/{@code JsonValue#NULL} pair to the JSON object associated with this object builder - * where the value is {@code null}. If the object contains a mapping for the specified name, this - * method replaces the old value with {@code null}. - * - * @param name name in the name/value pair - * @return this object builder - * @throws NullPointerException if the specified name is null - */ - JsonObjectBuilder addNull(String name); - - /** - * Adds a name/{@code JsonObject} pair to the JSON object associated with this object builder. The - * value {@code JsonObject} is built from the specified object builder. If the object contains a - * mapping for the specified name, this method replaces the old value with the {@code JsonObject} - * from the specified object builder. - * - * @param name name in the name/value pair - * @param builder the value is the object associated with this builder - * @return this object builder - * @throws NullPointerException if the specified name or builder is null - */ - JsonObjectBuilder add(String name, JsonObjectBuilder builder); - - /** - * Adds a name/{@code JsonArray} pair to the JSON object associated with this object builder. The - * value {@code JsonArray} is built from the specified array builder. If the object contains a - * mapping for the specified name, this method replaces the old value with the {@code JsonArray} - * from the specified array builder. - * - * @param name the name in the name/value pair - * @param builder the value is the object array with this builder - * @return this object builder - * @throws NullPointerException if the specified name or builder is null - */ - JsonObjectBuilder add(String name, JsonArrayBuilder builder); - - /** - * Adds all name/value pairs in the JSON object associated with the specified object builder to - * the JSON object associated with this object builder. The newly added name/value pair will - * replace any existing name/value pair with the same name. - * - * @param builder the specified object builder - * @return this object builder - * @throws NullPointerException if the specified builder is null - * @since 1.1 - */ - default JsonObjectBuilder addAll(JsonObjectBuilder builder) { - throw new UnsupportedOperationException(); - } - - /** - * Remove the name/value pair from the JSON object associated with this object builder if it is - * present. - * - * @param name the name in the name/value pair to be removed - * @return this object builder - * @throws NullPointerException if the specified name is null - * @since 1.1 - */ - default JsonObjectBuilder remove(String name) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the JSON object associated with this object builder. The iteration order for the {@code - * JsonObject} is based on the order in which name/value pairs are added to the object using this - * builder. - * - * @return JSON object that is being built - */ - JsonObject build(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonReader.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonReader.java deleted file mode 100644 index e6acf877c84..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonReader.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json; - -import java.io.Closeable; - -/** - * Reads a JSON {@link JsonObject object} or an {@link JsonArray array} structure from an input - * source. - * - *

    The class {@link jakarta.json.Json} contains methods to create readers from input sources - * ({@link java.io.InputStream} and {@link java.io.Reader}). - * - *

    The following example demonstrates how to read an empty JSON array from a string: - * - *

    - * 
    - * JsonReader jsonReader = Json.createReader(new StringReader("[]"));
    - * JsonArray array = jsonReader.readArray();
    - * jsonReader.close();
    - * 
    - * 
    - * - *

    The class {@link JsonReaderFactory} also contains methods to create {@code JsonReader} - * instances. A factory instance can be used to create multiple reader instances with the same - * configuration. This the preferred way to create multiple instances. A sample usage is shown in - * the following example: - * - *

    - * 
    - * JsonReaderFactory factory = Json.createReaderFactory(config);
    - * JsonReader reader1 = factory.createReader(...);
    - * JsonReader reader2 = factory.createReader(...);
    - * 
    - * 
    - */ -public interface JsonReader extends /*Auto*/ Closeable { - - /** - * Returns a JSON array or object that is represented in the input source. This method needs to be - * called only once for a reader instance. - * - * @return a JSON object or array - * @throws JsonException if a JSON object or array cannot be created due to i/o error (IOException - * would be cause of JsonException) - * @throws jakarta.json.stream.JsonParsingException if a JSON object or array cannot be created - * due to incorrect representation - * @throws IllegalStateException if read, readObject, readArray, readValue or close method is - * already called - */ - JsonStructure read(); - - /** - * Returns a JSON object that is represented in the input source. This method needs to be called - * only once for a reader instance. - * - * @return a JSON object - * @throws JsonException if a JSON object cannot be created due to i/o error (IOException would be - * cause of JsonException) - * @throws jakarta.json.stream.JsonParsingException if a JSON object cannot be created due to - * incorrect representation - * @throws IllegalStateException if read, readObject, readArray, readValue or close method is - * already called - */ - JsonObject readObject(); - - /** - * Returns a JSON array that is represented in the input source. This method needs to be called - * only once for a reader instance. - * - * @return a JSON array - * @throws JsonException if a JSON array cannot be created due to i/o error (IOException would be - * cause of JsonException) - * @throws jakarta.json.stream.JsonParsingException if a JSON array cannot be created due to - * incorrect representation - * @throws IllegalStateException if read, readObject, readArray, readValue or close method is - * already called - */ - JsonArray readArray(); - - /** - * Returns a JSON value that is represented in the input source. This method needs to be called - * only once for a reader instance. - * - * @return a JSON value - * @throws JsonException if a JSON value be created due to i/o error (IOException would be cause - * of JsonException) - * @throws jakarta.json.stream.JsonParsingException if a JSON value cannot be created due to - * incorrect representation - * @throws IllegalStateException if read, readObject, readArray, readValue or close method is - * already called - * @since 1.1 - */ - default JsonValue readValue() { - throw new UnsupportedOperationException(); - } - - /** - * Closes this reader and frees any resources associated with the reader. This method closes the - * underlying input source. - * - * @throws JsonException if an i/o error occurs (IOException would be cause of JsonException) - */ - @Override - void close(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonString.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonString.java deleted file mode 100644 index 9302756ad46..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonString.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json; - -/** An immutable JSON string value. */ -public interface JsonString extends JsonValue { - - /** - * Returns the JSON string value. - * - * @return a JSON string value - */ - String getString(); - - /** - * Returns the char sequence for the JSON String value - * - * @return a char sequence for the JSON String value - */ - CharSequence getChars(); - - /** - * Compares the specified object with this {@code JsonString} for equality. Returns {@code true} - * if and only if the specified object is also a {@code JsonString}, and their {@link - * #getString()} objects are equal. - * - * @param obj the object to be compared for equality with this {@code JsonString} - * @return {@code true} if the specified object is equal to this {@code JsonString} - */ - @Override - boolean equals(Object obj); - - /** - * Returns the hash code value for this {@code JsonString} object. The hash code of a {@code - * JsonString} object is defined to be its {@link #getString()} object's hash code. - * - * @return the hash code value for this {@code JsonString} object - */ - @Override - int hashCode(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonStructure.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonStructure.java deleted file mode 100644 index 664722b262b..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonStructure.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json; - -import jakarta.json.bind.JsonbException; - -/** - * Super type for the two structured types in JSON ({@link JsonObject object}s and {@link JsonArray - * array}s). - */ -public interface JsonStructure extends JsonValue { - - /** - * Get the value referenced by the provided JSON Pointer in the JsonStructure. - * - * @param jsonPointer the JSON Pointer - * @return the {@code JsonValue} at the referenced location - * @throws JsonException if the JSON Pointer is malformed, or if it references a non-existing - * member or value. - * @since 1.1 - */ - public default JsonValue getValue(String jsonPointer) { - throw new JsonbException("Not implemented"); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonValue.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonValue.java deleted file mode 100644 index 788c7244161..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonValue.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json; - -import jakarta.json.bind.JsonbException; - -/** - * JsonValue represents an immutable JSON value. - * - *

    A JSON value is one of the following: an object ({@link JsonObject}), an array ({@link - * JsonArray}), a number ({@link JsonNumber}), a string ({@link JsonString}), {@code true} ({@link - * JsonValue#TRUE JsonValue.TRUE}), {@code false} ({@link JsonValue#FALSE JsonValue.FALSE}), or - * {@code null} ({@link JsonValue#NULL JsonValue.NULL}). - */ -public interface JsonValue { - - /** - * The empty JSON object. - * - * @since 1.1 - */ - static final JsonObject EMPTY_JSON_OBJECT = new EmptyObject(); - - /** - * The empty JSON array. - * - * @since 1.1 - */ - static final JsonArray EMPTY_JSON_ARRAY = new EmptyArray(); - - /** Indicates the type of a {@link JsonValue} object. */ - enum ValueType { - /** JSON array. */ - ARRAY, - - /** JSON object. */ - OBJECT, - - /** JSON string. */ - STRING, - - /** JSON number. */ - NUMBER, - - /** JSON true. */ - TRUE, - - /** JSON false. */ - FALSE, - - /** JSON null. */ - NULL - } - - /** JSON null value. */ - static final JsonValue NULL = new JsonValueImpl(ValueType.NULL); - - /** JSON true value. */ - static final JsonValue TRUE = new JsonValueImpl(ValueType.TRUE); - - /** JSON false value. */ - static final JsonValue FALSE = new JsonValueImpl(ValueType.FALSE); - - /** - * Returns the value type of this JSON value. - * - * @return JSON value type - */ - ValueType getValueType(); - - /** - * Return the JsonValue as a JsonObject - * - * @return the JsonValue as a JsonObject - * @throws ClassCastException if the JsonValue is not a JsonObject - * @since 1.1 - */ - default JsonObject asJsonObject() { - throw new JsonbException("Not implemented"); - } - - /** - * Return the JsonValue as a JsonArray - * - * @return the JsonValue as a JsonArray - * @throws ClassCastException if the JsonValue is not a JsonArray - * @since 1.1 - */ - default JsonArray asJsonArray() { - throw new JsonbException("Not implemented"); - } - - /** - * Returns JSON text for this JSON value. - * - * @return JSON text - */ - @Override - String toString(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonValueImpl.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonValueImpl.java deleted file mode 100644 index 3e851e43292..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/JsonValueImpl.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json; - -import java.io.Serializable; - -/** - * Private implementation of {@link JsonValue} for simple {@link ValueType}s allowing their usage in - * constants which are better to implement {@link Serializable}. - * - * @author Lukas Jungmann - */ -final class JsonValueImpl implements JsonValue, Serializable { - - private final ValueType valueType; - - JsonValueImpl(ValueType valueType) { - this.valueType = valueType; - } - - /** - * Returns the value type of this JSON value. - * - * @return JSON value type - */ - @Override - public ValueType getValueType() { - return valueType; - } - - /** - * Compares the specified object with this {@link JsonValue} object for equality. Returns {@code - * true} if and only if the specified object is also a JsonValue, and their {@link - * #getValueType()} objects are equal. - * - * @param obj the object to be compared for equality with this JsonValue - * @return {@code true} if the specified object is equal to this JsonValue - */ - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof JsonValue) { - return getValueType().equals(((JsonValue) obj).getValueType()); - } - return false; - } - - /** - * Returns the hash code value for this {@link JsonValue} object. The hash code of the {@link - * JsonValue} object is defined to be its {@link #getValueType()} object's hash code. - * - * @return the hash code value for this {@link JsonValue} object - */ - @Override - public int hashCode() { - return valueType.hashCode(); - } - - @Override - public String toString() { - return valueType.name().toLowerCase(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/JsonProvider.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/JsonProvider.java deleted file mode 100644 index 35f57b5e03c..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/JsonProvider.java +++ /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. - */ - -package jakarta.json.bind; - -public interface JsonProvider {} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/Jsonb.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/Jsonb.java deleted file mode 100644 index 43285b1df07..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/Jsonb.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind; - -import java.lang.reflect.Type; - -import jakarta.json.GwtIncompatible; - -/** - * {@code Jsonb} provides an abstraction over the JSON Binding framework operations: - * - *

      - *
    • {@code fromJson}: read JSON input, deserialize to Java objects content tree - *
    • {@code toJson}: serialize Java objects content tree to JSON input - *
    - * - *

    Instance of this class is created using {@link jakarta.json.bind.JsonbBuilder JsonbBuilder} - * builder methods: - * - *

    {@code
    - * // Example 1 - Creating Jsonb using default JsonbBuilder instance provided by default JsonbProvider
    - * Jsonb jsonb = JsonbBuilder.create();
    - *
    - * // Example 2 - Creating Jsonb instance for a specific provider specified by a class name
    - * Jsonb jsonb = JsonbBuilder.newBuilder("foo.bar.ProviderImpl).build();
    - *
    - * // Example 3 - Creating Jsonb instance from a custom provider implementation
    - * Jsonb jsonb = new CustomJsonbBuilder().build();
    - * }
    - * - * Deserializing (reading) JSON
    - * - *
    - * - * Can de-serialize JSON data that represents either an entire JSON document or a subtree of a JSON - * document. - * - *
    - * - *
    - * - * Reading (deserializing) object content tree from a File:
    - *
    - * - *
    - *     Jsonb jsonb = JsonbBuilder.create();
    - *     Book book = jsonb.fromJson(new FileReader("jsonfile.json"), Book.class);
    - * - * If the deserialization process is unable to deserialize the JSON content to an object content - * tree, fatal error is reported that terminates processing by throwing JsonbException. - * - *
    - * - *

    Serializing (writing) to JSON - * - *

    - * - * Serialization writes the representation of a Java object content tree into JSON data. - * - *
    - * - *
    - * - * Writing (serializing) object content tree to a File:
    - *
    - * - *
    - *     jsonb.toJson(object, new FileWriter("foo.json"));
    - * - * Writing (serializing) to a Writer:
    - *
    - * - *
    - *     jsonb.toJson(object, new PrintWriter(System.out));
    - *    
    - * - *
    - * - *

    Encoding - * - *

    - * - * In deserialization operations ({@code fromJson}), encoding of JSON data is detected - * automatically. Use the {@link jakarta.json.bind.JsonbConfig JsonbConfig} API to configure - * expected input encoding used within deserialization operations. Client applications are expected - * to supply a valid character encoding as defined in the RFC 7159 and supported by Java Platform. - * - *

    In serialization operations ({@code toJson}), UTF-8 encoding is used by default for writing - * JSON data. Use the {@link jakarta.json.bind.JsonbConfig JsonbConfig} API to configure the output - * encoding used within serialization operations. Client applications are expected to supply a valid - * character encoding as defined in the RFC 7159 - * and supported by Java Platform. - * - *

    - * - *

    For optimal use, {@code JsonbBuilder} and {@code Jsonb} instances should be reused - for a - * typical use-case, only one {@code Jsonb} instance is required by an application. - * - *

    All the methods in this class are safe for use by multiple concurrent threads. - * - *

    Calling {@code Closable.close()} method will cleanup all CDI managed components (such as - * adapters with CDI dependencies) created during interaction with Jsonb. Calling {@code close()} - * must be done after all threads has finished interaction with Jsonb. If there are remaining - * threads working with Jsonb and {@code close()} is called, behaviour is undefined. - * - * @see Jsonb - * @see JsonbBuilder - * @see java.util.ServiceLoader - * @since JSON Binding 1.0 - */ -public interface Jsonb extends AutoCloseable { - - /** - * Reads in a JSON data from the specified string and return the resulting content tree. - * - * @param str The string to deserialize JSON data from. - * @param type Type of the content tree's root object. - * @param Type of the content tree's root object. - * @return the newly created root object of the java content tree - * @throws JsonbException If any unexpected error(s) occur(s) during deserialization. - * @throws NullPointerException If any of the parameters is {@code null}. - */ - T fromJson(String str, Class type) throws JsonbException; - - /** - * Reads in a JSON data from the specified string and return the resulting content tree. - * - * @param str The string to deserialize JSON data from. - * @param runtimeType Runtime type of the content tree's root object. - * @param Type of the content tree's root object. - * @return the newly created root object of the java content tree - * @throws JsonbException If any unexpected error(s) occur(s) during deserialization. - * @throws NullPointerException If any of the parameters is {@code null}. - */ - T fromJson(String str, Type runtimeType) throws JsonbException; - - /** - * Reads in a JSON data from the specified Reader and return the resulting content tree. - * - * @param reader The character stream is read as a JSON data. - * @param type Type of the content tree's root object. - * @param Type of the content tree's root object. - * @return the newly created root object of the java content tree - * @throws JsonbException If any unexpected error(s) occur(s) during deserialization. - * @throws NullPointerException If any of the parameters is {@code null}. - */ - @GwtIncompatible - T fromJson(java.io.Reader reader, Class type) throws JsonbException; - - /** - * Reads in a JSON data from the specified Reader and return the resulting content tree. - * - * @param reader The character stream is read as a JSON data. - * @param runtimeType Runtime type of the content tree's root object. - * @param Type of the content tree's root object. - * @return the newly created root object of the java content tree - * @throws JsonbException If any unexpected error(s) occur(s) during deserialization. - * @throws NullPointerException If any of the parameters is {@code null}. - */ - @GwtIncompatible - T fromJson(java.io.Reader reader, Type runtimeType) throws JsonbException; - - /** - * Reads in a JSON data from the specified InputStream and return the resulting content tree. - * - * @param stream The stream is read as a JSON data. Upon a successful completion, the stream will - * be closed by this method. - * @param type Type of the content tree's root object. - * @param Type of the content tree's root object. - * @return the newly created root object of the java content tree - * @throws JsonbException If any unexpected error(s) occur(s) during deserialization. - * @throws NullPointerException If any of the parameters is {@code null}. - */ - @GwtIncompatible - T fromJson(java.io.InputStream stream, Class type) throws JsonbException; - - /** - * Reads in a JSON data from the specified InputStream and return the resulting content tree. - * - * @param stream The stream is read as a JSON data. Upon a successful completion, the stream will - * be closed by this method. - * @param runtimeType Runtime type of the content tree's root object. - * @param Type of the content tree's root object. - * @return the newly created root object of the java content tree - * @throws JsonbException If any unexpected error(s) occur(s) during deserialization. - * @throws NullPointerException If any of the parameters is {@code null}. - */ - @GwtIncompatible - T fromJson(java.io.InputStream stream, Type runtimeType) throws JsonbException; - - /** - * Writes the Java object tree with root object {@code object} to a String instance as JSON. - * - * @param object The root object of the object content tree to be serialized. Must not be null. - * @return String instance with serialized JSON data. - * @throws JsonbException If any unexpected problem occurs during the serialization, such as I/O - * error. - * @throws NullPointerException If any of the parameters is {@code null}. - * @since JSON Binding 1.0 - */ - String toJson(Object object) throws JsonbException; - - /** - * Writes the Java object tree with root object {@code object} to a String instance as JSON. - * - * @param object The root object of the object content tree to be serialized. Must not be null. - * @param runtimeType Runtime type of the content tree's root object. Provided type needs to be - * related to the type of the instance. - * @return String instance with serialized JSON data. - * @throws JsonbException If any unexpected problem occurs during the serialization, such as I/O - * error. - * @throws NullPointerException If any of the parameters is {@code null}. - * @since JSON Binding 1.0 - */ - String toJson(Object object, Type runtimeType) throws JsonbException; - - /** - * Writes the object content tree into a Writer character stream. - * - * @param object The object content tree to be serialized. - * @param writer The JSON will be sent as a character stream to the given {@link Writer}. - * @throws JsonbException If any unexpected problem occurs during the serialization. - * @throws NullPointerException If any of the parameters is {@code null}. - * @since JSON Binding 1.0 - */ - @GwtIncompatible - void toJson(Object object, java.io.Writer writer) throws JsonbException; - - /** - * Writes the object content tree into a Writer character stream. - * - * @param object The object content tree to be serialized. - * @param runtimeType Runtime type of the content tree's root object. Provided type needs to be - * related to the type of the instance. - * @param writer The JSON will be sent as a character stream to the given {@link Writer}. - * @throws JsonbException If any unexpected problem occurs during the serialization. - * @throws NullPointerException If any of the parameters is {@code null}. - * @since JSON Binding 1.0 - */ - @GwtIncompatible - void toJson(Object object, Type runtimeType, java.io.Writer writer) throws JsonbException; - - /** - * Writes the object content tree into output stream. - * - * @param object The object content tree to be serialized. - * @param stream The JSON will be sent as a byte stream to the given {@link OutputStream}. Upon a - * successful completion, the stream will be closed by this method. - * @throws JsonbException If any unexpected problem occurs during the serialization. - * @throws NullPointerException If any of the parameters is {@code null}. - * @since JSON Binding 1.0 - */ - @GwtIncompatible - void toJson(Object object, java.io.OutputStream stream) throws JsonbException; - - /** - * Writes the object content tree into output stream. - * - * @param object The object content tree to be serialized. - * @param runtimeType Runtime type of the content tree's root object. Provided type needs to be - * related to the type of the instance. - * @param stream The JSON will be sent as a byte stream to the given {@link OutputStream}. Upon a - * successful completion, the stream will be closed by this method. - * @throws JsonbException If any unexpected problem occurs during the serialization. - * @throws NullPointerException If any of the parameters is {@code null}. - * @since JSON Binding 1.0 - */ - @GwtIncompatible - void toJson(Object object, Type runtimeType, java.io.OutputStream stream) throws JsonbException; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/JsonbBuilder.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/JsonbBuilder.java deleted file mode 100644 index 01acda7e12c..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/JsonbBuilder.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind; - -import jakarta.json.bind.spi.JsonbProvider; - -/** - * JsonbBuilder class provides the client's entry point to the JSON Binding API. It builds {@link - * jakarta.json.bind.Jsonb Jsonb} instances based on all parameters and configuration provided - * before calling {@code build()} method. - * - *

    For most use-cases, only one instance of JsonbBuilder is required within the application. - * - * @see Jsonb - * @see java.util.ServiceLoader - * @since JSON Binding 1.0 - */ -public interface JsonbBuilder { - - /** - * Set configuration which will be set to the newly created {@link jakarta.json.bind.Jsonb Jsonb} - * instance. - * - * @param config Configuration for {@link jakarta.json.bind.Jsonb Jsonb} instance. - * @return This {@code JsonbBuilder} instance. - */ - JsonbBuilder withConfig(JsonbConfig config); - - /** - * Provides a JSON-P provider to - * be used for all JSON-P related - * operations. - * - * @param jsonpProvider {@link jakarta.json.spi.JsonProvider JsonProvider} instance to be used by - * Jsonb to lookup JSON-P implementation. - * @return This {@code JsonbBuilder} instance. - */ - JsonbBuilder withProvider(JsonProvider jsonpProvider); - - /** - * Returns a new instance of {@link jakarta.json.bind.Jsonb Jsonb} based on the parameters and - * configuration specified previously in this builder. - * - * @return Jsonb A new instance of {@link jakarta.json.bind.Jsonb Jsonb} class. Always a non-null - * valid object. - * @throws jakarta.json.bind.JsonbException If an error was encountered while creating the Jsonb - * instance, such as (but not limited to) no JSON Binding provider found, or classes provide - * conflicting annotations. - * @throws IllegalArgumentException If there's an error processing the set parameters, such as the - * non-null parameter is assigned null value, or unrecognized property is set in {@link - * jakarta.json.bind.JsonbConfig JsonbConfig}. - */ - Jsonb build(); - - /** - * Create a new {@link jakarta.json.bind.Jsonb} instance using the default {@code JsonbBuilder} - * implementation provided as returned from {@link jakarta.json.bind.spi.JsonbProvider#provider()} - * method. - * - * @return new {@link jakarta.json.bind.Jsonb Jsonb} instance. - */ - static Jsonb create() { - return JsonbProvider.provider().create().build(); - } - - /** - * Create a new {@link jakarta.json.bind.Jsonb} instance using the default {@code JsonbBuilder} - * implementation provided as returned from {@link jakarta.json.bind.spi.JsonbProvider#provider()} - * method, configured with provided configuration. - * - * @param config Provided configuration for {@link jakarta.json.bind.Jsonb} instance. - * @return new {@link jakarta.json.bind.Jsonb Jsonb} instance. - */ - static Jsonb create(JsonbConfig config) { - return JsonbProvider.provider().create().withConfig(config).build(); - } - - /** - * Create a new {@code JsonbBuilder} instance as returned by the default {@link - * jakarta.json.bind.spi.JsonbProvider#provider()} method. - * - * @return new {@code JsonbBuilder} instance. - */ - static JsonbBuilder newBuilder() { - return JsonbProvider.provider().create(); - } - - /** - * Create a new {@code JsonbBuilder} instance as returned by {@link - * jakarta.json.bind.spi.JsonbProvider#provider(String)} method. - * - * @param providerName Provider class name to be looked up by {@link java.util.ServiceLoader - * ServiceLoader}. - * @return new {@code JsonbBuilder} instance. - */ - static JsonbBuilder newBuilder(final String providerName) { - return JsonbProvider.provider(providerName).create(); - } - - /** - * Create a new {@code JsonbBuilder} instance as returned by {@code provider#create} call. - * - * @param provider {@link jakarta.json.spi.JsonProvider JsonProvider} instance used for creating - * {@code JsonBuilder instances}. - * @return new {@code JsonbBuilder} instance. - */ - static JsonbBuilder newBuilder(final JsonbProvider provider) { - return provider.create(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/JsonbConfig.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/JsonbConfig.java deleted file mode 100644 index a00c868ae8b..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/JsonbConfig.java +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; - -import jakarta.json.bind.adapter.JsonbAdapter; -import jakarta.json.bind.config.PropertyNamingStrategy; -import jakarta.json.bind.config.PropertyVisibilityStrategy; -import jakarta.json.bind.serializer.JsonbDeserializer; -import jakarta.json.bind.serializer.JsonbSerializer; - -/** - * Supported Properties
    - * - *

    - * - *

    All JSON Binding providers are required to support the following set of properties. Some - * providers may support additional properties. - * - *

    - *
    jsonb.to.json.formatted - java.lang.Boolean - *
    Controls whether or not the {@link jakarta.json.bind.Jsonb Jsonb} {@code toJson()} methods - * will format the resulting JSON data with line breaks and indentation. A true value for this - * property indicates human readable indented data, while a false value indicates unformatted - * data. Default value is false (unformatted) if this property is not specified. - *
    - * - *
    - *
    jsonb.to.json.encoding - java.lang.String - *
    The {@link jakarta.json.bind.Jsonb Jsonb} serialization {@code toJson()} methods will - * default to this property for encoding of output JSON data. Default value is 'UTF-8' if this - * property is not specified. - *
    - * - *
    - *
    jsonb.from.json.encoding - java.lang.String - *
    The {@link jakarta.json.bind.Jsonb Jsonb} deserialization {@code fromJson()} methods will - * default to this property encoding of input JSON data if the encoding cannot be detected. - *
    - * - *
    - * - * This object is not thread safe. Implementations are expected to make a defensive copy of the - * object before applying the configuration. - * - * @since JSON Binding 1.0 - */ -public class JsonbConfig { - - private final Map configuration = new HashMap<>(); - - /** - * Property used to specify whether or not the serialized JSON data is formatted with line feeds - * and indentation. - */ - public static final String FORMATTING = "jsonb.formatting"; - - /** - * The Jsonb serialization {@code toJson()} methods will default to this property for encoding of - * output JSON data. Default value is 'UTF-8'. - * - *

    The Jsonb deserialization {@code fromJson()} methods will default to this property encoding - * of input JSON data if the encoding cannot be detected automatically. - */ - public static final String ENCODING = "jsonb.encoding"; - - /** Property used to specify custom naming strategy. */ - public static final String PROPERTY_NAMING_STRATEGY = "jsonb.property-naming-strategy"; - - /** Property used to specify custom order strategy. */ - public static final String PROPERTY_ORDER_STRATEGY = "jsonb.property-order-strategy"; - - /** Property used to specify null values serialization behavior. */ - public static final String NULL_VALUES = "jsonb.null-values"; - - /** Property used to specify strict I-JSON serialization compliance. */ - public static final String STRICT_IJSON = "jsonb.strict-ijson"; - - /** Property used to specify custom visibility strategy. */ - public static final String PROPERTY_VISIBILITY_STRATEGY = "jsonb.property-visibility-strategy"; - - /** Property used to specify custom mapping adapters for generic types. */ - public static final String ADAPTERS = "jsonb.adapters"; - - /** Property used to specify custom serializers. */ - public static final String SERIALIZERS = "jsonb.serializers"; - - /** Property used to specify custom deserializers. */ - public static final String DESERIALIZERS = "jsonb.derializers"; - - /** Property used to specify custom binary data strategy. */ - public static final String BINARY_DATA_STRATEGY = "jsonb.binary-data-strategy"; - - /** Property used to specify custom date format globally. */ - public static final String DATE_FORMAT = "jsonb.date-format"; - - /** Property used to specify locale globally. */ - public static final String LOCALE = "jsonb.locale"; - - /** Property used to specify required creator parameters. */ - public static final String CREATOR_PARAMETERS_REQUIRED = "jsonb.creator-parameters-required"; - - /** - * Set the particular configuration property to a new value. The method can only be used to set - * one of the standard JSON Binding properties defined in this class or a provider specific - * property. - * - * @param name The name of the property to be set. This value can either be specified using one of - * the constant fields or a user supplied string. - * @param value The value of the property to be set - * @return This JsonbConfig instance. - * @throws NullPointerException if the name parameter is null. - */ - public final JsonbConfig setProperty(final String name, final Object value) { - configuration.put(name, value); - return this; - } - - /** - * Return value of particular configuration property. The method can only be used to retrieve one - * of the standard JSON Binding properties defined in this class or a provider specific property. - * Attempting to get an undefined property will result in an empty Optional value. See Supported Properties. - * - * @param name The name of the property to retrieve - * @return The value of the requested property - * @throws NullPointerException if the name parameter is null. - */ - public final Optional getProperty(final String name) { - return Optional.ofNullable(configuration.get(name)); - } - - /** - * Return all configuration properties as an unmodifiable map. - * - * @return All configuration properties as an unmodifiable map - */ - public final Map getAsMap() { - return Collections.unmodifiableMap(configuration); - } - - /** - * Property used to specify whether or not the serialized JSON data is formatted with linefeeds - * and indentation. - * - *

    Configures value of {@link #FORMATTING} property. - * - * @param formatted True means serialized data is formatted, false (default) means no formatting. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withFormatting(final Boolean formatted) { - return setProperty(FORMATTING, formatted); - } - - /** - * Property used to specify whether null values should be serialized to JSON document or skipped. - * - *

    Configures value of {@link #NULL_VALUES} property. - * - * @param serializeNullValues True means that null values will be serialized into JSON document, - * otherwise they will be effectively skipped. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withNullValues(final Boolean serializeNullValues) { - return setProperty(NULL_VALUES, serializeNullValues); - } - - /** - * The binding operations will default to this property for encoding of JSON data. For input data - * (fromJson), selected encoding is used if the encoding cannot be detected automatically. Default - * value is 'UTF-8'. - * - *

    Configures value of {@link #ENCODING} property. - * - * @param encoding Valid character encoding as defined in the RFC 7159 and supported by Java Platform. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withEncoding(final String encoding) { - return setProperty(ENCODING, encoding); - } - - /** - * Property used to specify whether strict I-JSON serialization compliance should be enforced. - * - *

    Configures value of {@link #STRICT_IJSON} property. - * - * @param enabled True means data is serialized in strict compliance according to RFC 7493. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withStrictIJSON(final Boolean enabled) { - return setProperty(STRICT_IJSON, enabled); - } - - /** - * Property used to specify custom naming strategy. - * - *

    Configures value of {@link #PROPERTY_NAMING_STRATEGY} property. - * - * @param propertyNamingStrategy Custom naming strategy which affects serialization and - * deserialization. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withPropertyNamingStrategy( - final PropertyNamingStrategy propertyNamingStrategy) { - return setProperty(PROPERTY_NAMING_STRATEGY, propertyNamingStrategy); - } - - /** - * Property used to specify custom naming strategy. - * - *

    Configures value of {@link #PROPERTY_NAMING_STRATEGY} property. - * - * @param propertyNamingStrategy Predefined naming strategy which affects serialization and - * deserialization. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withPropertyNamingStrategy(final String propertyNamingStrategy) { - return setProperty(PROPERTY_NAMING_STRATEGY, propertyNamingStrategy); - } - - /** - * Property used to specify property order strategy. - * - *

    Configures values of {@link #PROPERTY_ORDER_STRATEGY} property. - * - * @param propertyOrderStrategy Predefined property order strategy which affects serialization. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withPropertyOrderStrategy(final String propertyOrderStrategy) { - return setProperty(PROPERTY_ORDER_STRATEGY, propertyOrderStrategy); - } - - /** - * Property used to specify custom property visibility strategy. - * - *

    Configures value of {@link #PROPERTY_VISIBILITY_STRATEGY} property. - * - * @param propertyVisibilityStrategy Custom property visibility strategy which affects - * serialization and deserialization. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withPropertyVisibilityStrategy( - final PropertyVisibilityStrategy propertyVisibilityStrategy) { - return setProperty(PROPERTY_VISIBILITY_STRATEGY, propertyVisibilityStrategy); - } - - /** - * Property used to specify custom mapping adapters. - * - *

    Configures value of {@link #ADAPTERS} property. - * - *

    Calling withAdapters more than once will merge the adapters with previous value. - * - * @param adapters Custom mapping adapters which affects serialization and deserialization. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withAdapters(final JsonbAdapter... adapters) { - mergeProperties(ADAPTERS, adapters, JsonbAdapter.class); - return this; - } - - /** - * Property used to specify custom serializers. - * - *

    Configures value of {@link #SERIALIZERS} property. - * - *

    Calling withSerializers more than once will merge the serializers with previous value. - * - * @param serializers Custom serializers which affects serialization. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withSerializers(final JsonbSerializer... serializers) { - mergeProperties(SERIALIZERS, serializers, JsonbSerializer.class); - return this; - } - - /** - * Property used to specify custom deserializers. - * - *

    Configures value of {@link #DESERIALIZERS} property. - * - *

    Calling withDeserializers more than once will merge the deserializers with previous value. - * - * @param deserializers Custom deserializers which affects deserialization. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withDeserializers(final JsonbDeserializer... deserializers) { - mergeProperties(DESERIALIZERS, deserializers, JsonbDeserializer.class); - return this; - } - - /** - * Property used to specify custom binary data strategy. - * - *

    Configures value of {@link #BINARY_DATA_STRATEGY} property. - * - * @param binaryDataStrategy Custom binary data strategy which affects serialization and - * deserialization. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withBinaryDataStrategy(final String binaryDataStrategy) { - return setProperty(BINARY_DATA_STRATEGY, binaryDataStrategy); - } - - /** - * Property used to specify custom date format. This format will be used by default for all date - * classes serialization and deserialization. - * - *

    Configures values of {@link #DATE_FORMAT} and {@link #LOCALE} properties. - * - * @param dateFormat Custom date format as specified in {@link - * java.time.format.DateTimeFormatter}. - * @param locale Locale, if null is specified {@link Locale#getDefault} will be used. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withDateFormat(final String dateFormat, final Locale locale) { - return setProperty(DATE_FORMAT, dateFormat) - .setProperty(LOCALE, locale != null ? locale : Locale.getDefault()); - } - - /** - * Property used to specify custom locale. - * - *

    Configures value of {@link #LOCALE} property. - * - * @param locale Locale, must not be null. - * @return This JsonbConfig instance. - */ - public final JsonbConfig withLocale(final Locale locale) { - return setProperty(LOCALE, locale); - } - - /** - * Property used to specify whether all creator parameters should be treated as required.
    - * Default value is {@code false}. - * - * @param requiredParameters Whether creator parameters are required - * @return This JsonbConfig instance. - */ - public final JsonbConfig withCreatorParametersRequired(final boolean requiredParameters) { - return setProperty(CREATOR_PARAMETERS_REQUIRED, requiredParameters); - } - - @SuppressWarnings("unchecked") - private void mergeProperties( - final String propertyKey, final T[] values, final Class tClass) { - throw new JsonbException("Not implemented"); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/JsonbException.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/JsonbException.java deleted file mode 100644 index e9a05db1a5d..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/JsonbException.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind; - -/** - * Root class for all JSON Binding exceptions. - * - * @since JSON Binding 1.0 - */ -public class JsonbException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - /** - * Constructs a new runtime exception with the specified detail message. The cause is not - * initialized, and may subsequently be initialized by a call to {@link #initCause}. - * - * @param message The detail message. The detail message is saved for later retrieval by the - * {@link #getMessage()} method. - */ - public JsonbException(final String message) { - super(message); - } - - /** - * Constructs a new runtime exception with the specified detail message and cause. - * - *

    Note that the detail message associated with {@code cause} is not automatically - * incorporated in this runtime exception's detail message. - * - * @param message The detail message (which is saved for later retrieval by the {@link - * #getMessage()} method). - * @param cause The cause (which is saved for later retrieval by the {@link #getCause()} method). - * (A {@code null} value is permitted, and indicates that the cause is nonexistent or - * unknown.) - */ - public JsonbException(final String message, final Throwable cause) { - super(message, cause); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/adapter/JsonbAdapter.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/adapter/JsonbAdapter.java deleted file mode 100644 index 3ac052ab9c2..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/adapter/JsonbAdapter.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.adapter; - -/** - * Allows to define custom mapping for given java type. The target type could be string or some - * mappable java type. - * - *

    On serialization "Original" type is converted into "Adapted" type. After that "Adapted" type - * is serialized to JSON the standard way. - * - *

    On deserialization it works the reverse way: JSON data are deserialized into "Adapted" type - * which is converted to "Original" type after that. - * - *

    Adapters are registered using {@link - * jakarta.json.bind.JsonbConfig#withAdapters(JsonbAdapter[])} method or using {@link - * jakarta.json.bind.annotation.JsonbTypeAdapter} annotation on class field. - * - * @param The type that JSONB doesn't know how to handle - * @param The type that JSONB knows how to handle out of the box - *

    Adapter runtime "Original" and "Adapted" generic types are inferred from subclassing - * information, which is mandatory for adapter to work. - *

    Sample 1: - *

    {@code
    - * // Generic information is provided by subclassing.
    - * class BoxToCrateAdapter implements JsonbAdapter, Crate> {...};
    - * jsonbConfig.withAdapters(new BoxToCrateAdapter());
    - *
    - * // Generic information is provided by subclassing with anonymous class
    - * jsonbConfig.withAdapters(new JsonbAdapter, Crate> {...});
    - * }
    - *

    Sample 2: - *

    {@code
    - * BoxToCrateAdapter implements JsonbAdapter, Integer> {...};
    - *
    - * // Bad way: Generic type information is lost due to type erasure
    - * jsonbConfig.withAdapters(new BoxToCrateAdapter());
    - *
    - * // Proper way: Anonymous class holds generic type information
    - * jsonbConfig.withAdapters(new BoxToCrateAdapter(){});
    - * }
    - * - * @see jakarta.json.bind.JsonbConfig - * @see jakarta.json.bind.annotation.JsonbTypeAdapter - * @since JSON Binding 1.0 - */ -public interface JsonbAdapter { - - /** - * This method is used on serialization only. It contains a conversion logic from type Original to - * type Adapted. After conversion Adapted type will be mapped to JSON the standard way. - * - * @param obj Object to convert or {@code null}. - * @return Converted object which will be serialized to JSON or {@code null}. - * @throws Exception if there is an error during the conversion. - */ - Adapted adaptToJson(Original obj) throws Exception; - - /** - * This method is used on deserialization only. It contains a conversion logic from type Adapted - * to type Original. - * - * @param obj Object to convert or {@code null}. - * @return Converted object representing pojo to be set into object graph or {@code null}. - * @throws Exception if there is an error during the conversion. - */ - Original adaptFromJson(Adapted obj) throws Exception; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbAnnotation.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbAnnotation.java deleted file mode 100644 index 800e3dd3937..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbAnnotation.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; - -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Marks any relevant JSON Binding annotations. Includes {@code @Documented} and - * {@code @Retention(RUNTIME)} definitions. - * - * @since JSON Binding 1.0 - */ -@Documented -@Retention(RUNTIME) -public @interface JsonbAnnotation {} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbCreator.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbCreator.java deleted file mode 100644 index f76d219b929..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbCreator.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2015, 2021 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * This annotation identifies the custom constructor or factory method to use when creating an - * instance of the associated class. - * - *

    Only one constructor or static factory method can be annotated with {@code JsonbCreator} in a - * given class. - * - *

    The {@code @JsonbCreator} annotation is intended to be used with constructors/methods with - * parameters. Such parameters could be annotated for instance with {@code @JsonbProperty}. - * - *

    Usage - * - *

    The {@code @JsonbCreator} annotation can be used with the following program elements: - * - *

      - *
    • method - *
    • constructor - *
    - * - * @since JSON Binding 1.0 - */ -@JsonbAnnotation -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR}) -public @interface JsonbCreator {} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbDateFormat.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbDateFormat.java deleted file mode 100644 index 31ce7ae32a0..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbDateFormat.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation provides way how to set custom date format to field or JavaBean property. - * - *

    The pattern format is specified in {@link java.time.format.DateTimeFormatter} - * - *

    Usage - * - *

    The {@code @JsonbDateFormat} annotation can be used with the following program elements: - * - *

      - *
    • field - *
    • getter/setter - *
    • type - *
    • parameter - *
    • package - *
    - * - * @since JSON Binding 1.0 - */ -@JsonbAnnotation -@Retention(RetentionPolicy.RUNTIME) -@Target({ - ElementType.ANNOTATION_TYPE, - ElementType.FIELD, - ElementType.METHOD, - ElementType.TYPE, - ElementType.PARAMETER, - ElementType.PACKAGE -}) -public @interface JsonbDateFormat { - - /** Value that indicates that default {@link java.util.Locale}. */ - String DEFAULT_LOCALE = "##default"; - - /** Value that indicates the default format. */ - String DEFAULT_FORMAT = "##default"; - - /** - * Special date format which serializes given date as milliseconds. Such date is serialized as a - * number. - */ - String TIME_IN_MILLIS = "##time-in-millis"; - - /** - * Specifies the date pattern to use. - * - * @return Date pattern to use. - */ - String value() default DEFAULT_FORMAT; - - /** - * Custom {@link java.util.Locale} to use. - * - * @return Locale to use. - */ - String locale() default DEFAULT_LOCALE; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbNillable.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbNillable.java deleted file mode 100644 index 9fdd6679808..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbNillable.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PACKAGE; -import static java.lang.annotation.ElementType.TYPE; - - -/** - * Specifies how fields having null values are serialized into JSON. - * - *

    There are two possible values which can be specified. In case of true, fields are serialized - * as key/value pair with value null. In case of false, fields will not be serialized (default - * behaviour). - * - *

    Annotation can be specified on field, method, type or on package and affects all underlying - * properties and classes. - * - *

    For similar functionality on a property level see {@link JsonbProperty}. However this {@link - * JsonbProperty} functionality has been deprecated and should not be used - * - * @since JSON Binding 1.0 - */ -@JsonbAnnotation -@Retention(RetentionPolicy.RUNTIME) -@Target({ANNOTATION_TYPE, FIELD, METHOD, TYPE, PACKAGE}) -public @interface JsonbNillable { - - /** - * Switches on/off serialization of properties with null value. - * - * @return True if field with null value should be serialized as key/value pair into JSON with - * null value. - */ - boolean value() default true; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbNumberFormat.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbNumberFormat.java deleted file mode 100644 index fe7c1f861f4..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbNumberFormat.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation provides way how to set custom number format to field or JavaBean property. - * - *

    The pattern format is specified in {@link java.text.DecimalFormat} - * - *

    Usage - * - *

    The {@code @JsonbNumberFormat} annotation can be used with the following program elements: - * - *

      - *
    • field - *
    • getter/setter - *
    • type - *
    • parameter - *
    • package - *
    - * - * @since JSON Binding 1.0 - */ -@JsonbAnnotation -@Retention(RetentionPolicy.RUNTIME) -@Target({ - ElementType.ANNOTATION_TYPE, - ElementType.FIELD, - ElementType.METHOD, - ElementType.TYPE, - ElementType.PARAMETER, - ElementType.PACKAGE -}) -public @interface JsonbNumberFormat { - - /** Value that indicates that default {@link java.util.Locale}. */ - String DEFAULT_LOCALE = "##default"; - - /** - * Specifies the number pattern to use. - * - * @return Number pattern to use. - */ - String value() default ""; - - /** - * Custom {@link java.util.Locale} to use. - * - * @return Custom locale to use. - */ - String locale() default DEFAULT_LOCALE; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbProperty.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbProperty.java deleted file mode 100644 index 1a2eff1b883..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbProperty.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2015, 2021 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Allows customization of field (or JavaBean property) name.This name is used either in - * serialization or in deserialization. - * - *

    Usage - * - *

    The {@code @JsonbProperty} annotation can be used with the following program elements: - * - *

      - *
    • a JavaBean property - *
    • field - *
    • parameter - *
    - * - * @since JSON Binding 1.0 - */ -@JsonbAnnotation -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) -public @interface JsonbProperty { - - /** - * Customized name of the field (or JavaBean property). - * - * @return Customized property name. - */ - String value() default ""; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbPropertyOrder.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbPropertyOrder.java deleted file mode 100644 index 5cd56e43515..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbPropertyOrder.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Specifies order in which properties are serialized. - * - *

    Partial mapping can also be specified. In that case, properties included in annotation - * declaration will be serialized first (in defined order), followed by any properties not included - * in the definition. The order of properties not included in the definition is not guaranteed. - * - * @since JSON Binding 1.0 - */ -@JsonbAnnotation -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE}) -public @interface JsonbPropertyOrder { - - /** - * Order in which properties are serialized. Names must correspond to original names defined in - * Java class before any customization applied. - * - * @return Array of property names which defines an order. - */ - String[] value(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbSubtype.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbSubtype.java deleted file mode 100644 index cbd0a39f299..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbSubtype.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Subtype is tightly bound to the {@link JsonbTypeInfo}.
    - * Type defines class which instance will be created when processing specific alias, or when - * processing instance of the specified type, to determine which alias should be used.
    - * Alias is used instead of a class name. It has to be unique value among all the defined subtypes - * bound to the specific {@link JsonbTypeInfo}. An exception should be thrown when processing and - * validating aliases and duplicate alias is found. - * - *

    
    - * // Example
    - * {@literal @}JsonbTypeInfo({
    - *      {@literal @}JsonbSubtype(alias = "dog", type = Dog.class)
    - *      {@literal @}JsonbSubtype(alias = "cat", type = Cat.class)
    - * })
    - * interface Animal {}
    - *
    - * class Dog implements Animal {
    - *     public String isDog = true;
    - * }
    - * class Cat implements Animal {
    - *     public String isCat = true;
    - * }
    - * class Rat implements Animal {
    - *     public String isRat = true;
    - * }
    - *
    - * jsonb.toJson(new Dog());// {"@type":"dog","isDog":true}
    - * jsonb.toJson(new Cat());// {"@type":"cat","isCat":true}
    - * jsonb.toJson(new Rat());// {"isRat":true}
    - * 
    - */ -@JsonbAnnotation -@Retention(RetentionPolicy.RUNTIME) -@Target({}) -public @interface JsonbSubtype { - - /** - * Type alias which is used instead of a class name. - * - * @return alias value - */ - String alias(); - - /** - * An actual type bound to the alias. - * - * @return alias bound type - */ - Class type(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTransient.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTransient.java deleted file mode 100644 index 7d501af4f0b..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTransient.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; - - -/** - * Prevents mapping of a Java Bean property, field or type to JSON representation. - * - *

    Usage - * - *

    The {@code @JsonbTransient} annotation can be used with the following program elements: - * - *

      - *
    • getter/setter - *
    • field - *
    - * - *

    {@code @JsonbTransient} is mutually exclusive with all other JSON Binding defined annotations. - * - *

    If a class field is annotated with {@code @JsonbTransient}, exception is thrown when this - * field, getter or setter is annotated with other JSON Binding annotations. - * - *

    If a getter is annotated with {@code @JsonbTransient}, exception is thrown if when the field - * or this getter are annotated with other JSON Binding annotations. Exception is not thrown if JSON - * Binding annotations are presented on the setter. - * - *

    If a setter is annotated with {@code @JsonbTransient}, exception is thrown if when the field - * or this setter are annotated with other JSON Binding annotations. Exception is not thrown if JSON - * Binding annotations are presented on the getter. - * - * @since JSON Binding 1.0 - */ -@JsonbAnnotation -@Retention(RetentionPolicy.RUNTIME) -@Target({ANNOTATION_TYPE, FIELD, METHOD}) -public @interface JsonbTransient {} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTypeAdapter.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTypeAdapter.java deleted file mode 100644 index 6f5e126318f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTypeAdapter.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import jakarta.json.bind.adapter.JsonbAdapter; - -/** - * Annotation provides way how to set custom JsonbAdapter to field or JavaBean property. - * - *

    Usage - * - *

    The {@code @JsonbTypeAdapter} annotation can be used with the following program elements: - * - *

      - *
    • type - *
    • field - *
    • method - *
    • parameter - *
    - * - * @since JSON Binding 1.0 - */ -@JsonbAnnotation -@Retention(RetentionPolicy.RUNTIME) -@Target({ - ElementType.ANNOTATION_TYPE, - ElementType.TYPE, - ElementType.FIELD, - ElementType.METHOD, - ElementType.PARAMETER -}) -public @interface JsonbTypeAdapter { - - /** - * Custom JsonbAdapter which provides custom mapping for given field or JavaBean property. - * - * @return Adapter to use. - */ - Class value(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTypeDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTypeDeserializer.java deleted file mode 100644 index 9e146b462f9..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTypeDeserializer.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2016, 2021 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import jakarta.json.bind.serializer.JsonbDeserializer; - -/** - * Annotation provides way how to set custom JsonbDeserializer to field or JavaBean property. - * - *

    Usage - * - *

    The {@code @JsonbDeserializer} annotation can be used with the following program elements: - * - *

      - *
    • type - *
    • field - *
    • method - *
    • creator parameter - *
    - * - * @since JSON Binding 1.0 - */ -@JsonbAnnotation -@Retention(RetentionPolicy.RUNTIME) -@Target({ - ElementType.ANNOTATION_TYPE, - ElementType.TYPE, - ElementType.FIELD, - ElementType.METHOD, - ElementType.PARAMETER -}) -public @interface JsonbTypeDeserializer { - - /** - * Custom {@link JsonbDeserializer} which provides custom mapping for given field or JavaBean - * property. - * - * @return Deserializer to use. - */ - Class value(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTypeInfo.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTypeInfo.java deleted file mode 100644 index 2ad6beeb4ef..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTypeInfo.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Configuration annotation of the type information handling.
    - * This annotation is required on the most common parent of all classes when type information will - * be applied. - * - *
    
    - * // Example
    - * {@literal @}JsonbTypeInfo(key = "@key")
    - * interface Animal {}
    - *
    - * class Dog implements Animal {}
    - * class Cat implements Animal {}
    - * 
    - * - * This annotation is tightly bound to {@link JsonbSubtype}. It is required to use {@link - * JsonbSubtype} annotations to specify all the possible classes and their aliases. - */ -@JsonbAnnotation -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE}) -public @interface JsonbTypeInfo { - - /** Default type information key name. */ - String DEFAULT_KEY_NAME = "@type"; - - /** - * Key used for keeping the type information (alias). Default value is {@code @type}. - * - * @return key name - */ - String key() default DEFAULT_KEY_NAME; - - /** - * Allowed aliases of the handled type. - * - * @return list of allowed aliases - */ - JsonbSubtype[] value() default {}; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTypeSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTypeSerializer.java deleted file mode 100644 index 507856037f6..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbTypeSerializer.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import jakarta.json.bind.serializer.JsonbSerializer; - -/** - * Annotation provides way how to set custom JsonbSerializer to field or JavaBean property. - * - *

    Usage - * - *

    The {@code @JsonbSerializer} annotation can be used with the following program elements: - * - *

      - *
    • type - *
    • field - *
    • method - *
    - * - * @since JSON Binding 1.0 - */ -@JsonbAnnotation -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) -public @interface JsonbTypeSerializer { - - /** - * Custom {@link JsonbSerializer} which provides custom mapping for given field or JavaBean - * property. - * - * @return Serializaer to use. - */ - Class value(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbVisibility.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbVisibility.java deleted file mode 100644 index 8be57eeac7f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/annotation/JsonbVisibility.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import jakarta.json.bind.config.PropertyVisibilityStrategy; - -/** - * Annotation provides way how to customize visibility strategy of the JSON Binding. - * - *

    It allows for example to specify, that only public getters and setter should be visible. - * - *

    Usage - * - *

    The {@code @JsonbVisibility} annotation can be used with the following program elements: - * - *

      - *
    • type - *
    • package - *
    - * - * @since JSON Binding 1.0 - */ -@JsonbAnnotation -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.PACKAGE}) -public @interface JsonbVisibility { - - /** - * Custom property visibility strategy used to resolve visibility of the members. - * - * @return Visibility strategy to use. - */ - Class value(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/config/BinaryDataStrategy.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/config/BinaryDataStrategy.java deleted file mode 100644 index 9a1b6e1355f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/config/BinaryDataStrategy.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.config; - -/** - * Specifies predefined binary data handling strategies. This strategy can be set via {@link - * jakarta.json.bind.JsonbConfig#withBinaryDataStrategy(String)}. - * - * @see jakarta.json.bind.JsonbConfig - * @since JSON Binding 1.0 - */ -public final class BinaryDataStrategy { - - /** Private constructor to disallow instantiation. */ - private BinaryDataStrategy() {}; - - /** Using this strategy, binary data is encoded as a byte array. Default encoding strategy. */ - public static final String BYTE = "BYTE"; - - /** - * Using this strategy, binary data is encoded using the Base64 encoding scheme as specified in - * RFC 4648 and RFC 2045. - */ - public static final String BASE_64 = "BASE_64"; - - /** - * Using this strategy, binary data is encoded using the "URL and Filename safe Base64 Alphabet" - * as specified in Table 2 of RFC 4648. - */ - public static final String BASE_64_URL = "BASE_64_URL"; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/config/PropertyNamingStrategy.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/config/PropertyNamingStrategy.java deleted file mode 100644 index 3cb23619488..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/config/PropertyNamingStrategy.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.config; - -/** - * Allows to define custom property naming strategy. Specifies predefined property naming - * strategies. Does not override JsonbProperty value. - * - *

    This strategy can be set via {@link jakarta.json.bind.JsonbConfig}. - * - * @see jakarta.json.bind.JsonbConfig - * @since JSON Binding 1.0 - */ -public interface PropertyNamingStrategy { - /** Using this strategy, the property name is unchanged. */ - String IDENTITY = "IDENTITY"; - - /** - * Using this strategy, the property name is transformed to lower case with dashes. The dashes are - * on the positions of different case boundaries in the original field name (camel case). - */ - String LOWER_CASE_WITH_DASHES = "LOWER_CASE_WITH_DASHES"; - - /** - * Using this strategy, the property name is transformed to lower case with underscores. The - * underscores are on the positions of different case boundaries in the original field name (camel - * case). - */ - String LOWER_CASE_WITH_UNDERSCORES = "LOWER_CASE_WITH_UNDERSCORES"; - - /** Using this strategy, the first character will be capitalized. */ - String UPPER_CAMEL_CASE = "UPPER_CAMEL_CASE"; - - /** - * Using this strategy, the first character will be capitalized and the words will be separated by - * spaces. - */ - String UPPER_CAMEL_CASE_WITH_SPACES = "UPPER_CAMEL_CASE_WITH_SPACES"; - - /** - * Using this strategy, the serialization will be same as identity. Deserialization will be case - * insensitive. E.g. property in JSON with name PropertyNAME, will be mapped to field - * propertyName. - */ - String CASE_INSENSITIVE = "CASE_INSENSITIVE"; - - /** - * Translates the property name into its JSON field name representation. - * - * @param propertyName Name of the property to translate. - * @return Translated JSON field name. - */ - String translateName(String propertyName); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/config/PropertyOrderStrategy.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/config/PropertyOrderStrategy.java deleted file mode 100644 index adf2929d1c1..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/config/PropertyOrderStrategy.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.config; - -/** - * Specifies predefined property order strategies. This strategy can be set via {@link - * jakarta.json.bind.JsonbConfig#withPropertyOrderStrategy(String)} - * - * @see jakarta.json.bind.JsonbConfig - * @since JSON Binding 1.0 - */ -public final class PropertyOrderStrategy { - - /** Private constructor to disallow instantiation. */ - private PropertyOrderStrategy() {}; - - /** Using this strategy, the order of properties is lexicographical. */ - public static final String LEXICOGRAPHICAL = "LEXICOGRAPHICAL"; - - /** Using this strategy, the order of properties is not guaranteed to retain any order. */ - public static final String ANY = "ANY"; - - /** Using this strategy, the order of properties is in reverse order to lexicographical order. */ - public static final String REVERSE = "REVERSE"; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/config/PropertyVisibilityStrategy.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/config/PropertyVisibilityStrategy.java deleted file mode 100644 index 7802b38c732..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/config/PropertyVisibilityStrategy.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.config; - -/** - * Provides mechanism how to define customized property visibility strategy. - * - *

    This strategy can be set via {@link jakarta.json.bind.JsonbConfig}. - * - * @see jakarta.json.bind.JsonbConfig - * @since JSON Binding 1.0 - */ -public interface PropertyVisibilityStrategy {} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/serializer/DeserializationContext.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/serializer/DeserializationContext.java deleted file mode 100644 index 4f9f39bd46f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/serializer/DeserializationContext.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.serializer; - -import java.lang.reflect.Type; - -import jakarta.json.stream.JsonParser; - -/** - * Provides JSONB Mapper functionality on top of JSONP parser. - * - * @see JsonbDeserializer - * @since JSON Binding 1.0 - */ -public interface DeserializationContext { - - /** - * Deserialize JSON stream into instance of provided class using {@link - * jakarta.json.stream.JsonParser}. JsonParser cursor have to be at KEY_NAME before START_OBJECT / - * START_ARRAY, or at START_OBJECT / START_ARRAY to call this method. After deserialization is - * complete JsonParser will be at END_OBJECT / END_ARRAY for deserialized JSON structure. - * - *

    If method is called for the same type, which is deserializer bound to, deserializer - * recursion is suppressed. Otherwise deserializers are reentrant during deserialization process - * started by this method. {@link JsonParser} instance of JSONB runtime is shared with custom - * deserializer. - * - * @param clazz Type to deserialize into. No arg constructor required. - * @param parser JSONP parser to drive. - * @param Type of class. - * @return Deserialized instance. - */ - T deserialize(Class clazz, JsonParser parser); - - /** - * Deserialize JSON stream into instance of provided class using {@link - * jakarta.json.stream.JsonParser}. JsonParser cursor have to be at KEY_NAME before START_OBJECT / - * START_ARRAY, or at START_OBJECT / START_ARRAY to call this method. After deserialization is - * complete JsonParser will be at END_OBJECT / END_ARRAY for deserialized JSON structure. - * - *

    If method is called for the same type, which is deserializer bound to, deserializer - * recursion is suppressed. Otherwise deserializers are reentrant during deserialization process - * started by this method. {@link JsonParser} instance of JSONB runtime is shared with custom - * deserializer. - * - * @param type Type to deserialize into. No arg constructor required. - * @param parser JSONP parser to drive. - * @param Type to deserialize into. - * @return Deserialized instance. - */ - T deserialize(Type type, JsonParser parser); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/serializer/JsonbDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/serializer/JsonbDeserializer.java deleted file mode 100644 index b57b6ac61d1..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/serializer/JsonbDeserializer.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.serializer; - -import java.lang.reflect.Type; - -import jakarta.json.stream.JsonParser; - -/** - * Interface representing a custom deserializer for a given type. It provides a low-level API for - * java object deserialization from JSON stream using {@link JsonParser}. Unlike {@link - * jakarta.json.bind.adapter.JsonbAdapter}, which acts more as converter from one java type to - * another, deserializer provides more fine grained control over deserialization process. - * - *

    {@link DeserializationContext} acts as JSONB runtime, able to deserialize any java object - * provided. - * - *

    Sample of custom Deserializer: - * - *

    - *     class Box {
    - *         public BoxInner boxInnerObject;
    - *         public String name;
    - *     }
    - *
    - *     BoxDeserializer implements JsonbDeserializer<Box> {
    - *         public Box deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) {
    - *             Box = new Box();
    - *
    - *             while (parser.hasNext()) {
    - *                 Event event = parser.next();
    - *
    - *                 if (event == JsonParser.Event.KEY_NAME && parser.getString().equals("boxInnerObject") {
    - *                     // Deserialize inner object
    - *                     box.boxInnerObject = ctx.deserialize(BoxInner.class, jsonParser);
    - *
    - *                 } else if (event == JsonParser.Event.KEY_NAME && parser.getString().equals("name") {
    - *                     // Deserialize name property
    - *                     parser.next(); // move to VALUE
    - *                     box.name = parser.getString();
    - *                 }
    - *             }
    - *
    - *             return box;
    - *         }
    - *     }
    - * 
    - * - *

    Deserializers are registered using {@link - * jakarta.json.bind.JsonbConfig#withDeserializers(JsonbDeserializer[])} method or using {@link - * jakarta.json.bind.annotation.JsonbTypeDeserializer} annotation on type. - * - * @param Type to bind deserializer for. - * @see jakarta.json.bind.JsonbConfig - * @see jakarta.json.bind.annotation.JsonbTypeDeserializer - * @see JsonbSerializer - * @see jakarta.json.bind.adapter.JsonbAdapter - * @since JSON Binding 1.0 - */ -public interface JsonbDeserializer { - - /** - * Deserialize JSON stream into object. - * - * @param parser Json parser. - * @param ctx Deserialization context. - * @param rtType Type of returned object. - * @return Deserialized instance. - */ - T deserialize(JsonParser parser, DeserializationContext ctx, Type rtType); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/serializer/JsonbSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/serializer/JsonbSerializer.java deleted file mode 100644 index 950d76e7fe1..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/serializer/JsonbSerializer.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.serializer; - -import jakarta.json.stream.JsonGenerator; - -/** - * Interface representing a custom serializer for given type. Unlike {@link - * jakarta.json.bind.adapter.JsonbAdapter} serializer provides more fine grained control over - * serialization process by writing java object directly into JSON stream using {@link - * JsonGenerator}. {@link SerializationContext} acts as JSONB runtime, able to serialize any java - * object provided. - * - *

    Serializers are registered using {@link - * jakarta.json.bind.JsonbConfig#withSerializers(JsonbSerializer[])} method or using {@link - * jakarta.json.bind.annotation.JsonbTypeSerializer} annotation on type - * - *

    Sample of custom Serializer: - * - *

    - * class Box {
    - *     public BoxInner boxInnerObject;
    - *     public String name;
    - * }
    - *
    - * class BoxSerializer implements JsonbSerializer<Box> {
    - *      public void serialize(Box box, JsonGenerator generator, SerializationContext ctx) {
    - *          generator.write("name", box.name);
    - *          ctx.serialize("boxInnerObject", generator);
    - *      }
    - * }
    - * 
    - * - * @param Type to bind serializer for. - * @see jakarta.json.bind.JsonbConfig - * @see jakarta.json.bind.annotation.JsonbTypeSerializer - * @see JsonbDeserializer - * @see jakarta.json.bind.adapter.JsonbAdapter - * @since JSON Binding 1.0 - */ -public interface JsonbSerializer { - - /** - * Serializes object into JSON stream. - * - * @param obj Object to serialize. - * @param generator JSON generator used to write java object to JSON stream. - * @param ctx JSONB mapper context. Use it to serialize sub-objects. - */ - void serialize(T obj, JsonGenerator generator, SerializationContext ctx); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/serializer/SerializationContext.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/serializer/SerializationContext.java deleted file mode 100644 index 4d58d99906e..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/serializer/SerializationContext.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.serializer; - -import jakarta.json.stream.JsonGenerator; - -/** - * Provides JSONB internals for custom serializers. - * - * @see JsonbSerializer - * @since JSON Binding 1.0 - */ -public interface SerializationContext { - - /** - * Serializes arbitrary object to JSON, using current {@link jakarta.json.stream.JsonGenerator} - * instance. Serialization is ran as serialization of a root type from user {@link - * JsonbSerializer}. {@link JsonGenerator} instance is shared with JSONB and user serializer. - * - * @param key JSON key name. - * @param object Object to serialize. - * @param generator JSONP generator to serialize with. - * @param Type of serialized object. - */ - void serialize(String key, T object, JsonGenerator generator); - - /** - * Serializes arbitrary object to JSON, using current {@link jakarta.json.stream.JsonGenerator} - * instance. Serialization is ran as serialization of a root type from user {@link - * JsonbSerializer}. {@link JsonGenerator} instance is shared with JSONB and user serializer. - * - *

    Method without key parameter is intended to serialize inside JSON_ARRAYs. - * - * @param object Object to serialize. - * @param generator JSONP generator to serialize with. - * @param Type of serialized object. - */ - void serialize(T object, JsonGenerator generator); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/spi/JsonbProvider.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/spi/JsonbProvider.java deleted file mode 100644 index 42b60ef11f7..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/bind/spi/JsonbProvider.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.bind.spi; - -import jakarta.json.bind.JsonbBuilder; -import jakarta.json.bind.JsonbException; - -/** - * Service provider for JSON Binding implementations. - * - *

    Provider implementors must implement all abstract methods. - * - *

    API clients can obtain instance of default provider by calling: - * - *

    {@code
    - * JsonbProvider provider = JsonbProvider.provider();
    - * }
    - * }
    - * - * Specific provider instance lookup: - * - *
    {@code
    - * JsonbProvider provider;
    - * try {
    - *   JsonbProvider.provider("foo.bar.ProviderImpl");
    - * } catch (JsonbException e) {
    - *   // provider not found or could not be instantiated
    - * }
    - * }
    - * - * where '{@code foo.bar.ProviderImpl}' is a vendor implementation class extending {@link - * jakarta.json.bind.spi.JsonbProvider} and identified to service loader as specified in {@link - * java.util.ServiceLoader} documentation.
    - * All the methods in this class are allowed to be called by multiple concurrent threads. - * - * @see jakarta.json.bind.Jsonb - * @see java.util.ServiceLoader - * @since JSON Binding 1.0 - */ -public abstract class JsonbProvider { - - /** - * A constant representing the name of the default {@link jakarta.json.bind.spi.JsonbProvider - * JsonbProvider} implementation class. - */ - private static final String DEFAULT_PROVIDER = "org.eclipse.yasson.JsonBindingProvider"; - - /** Protected constructor. */ - protected JsonbProvider() {} - - /** - * Creates a JSON Binding provider object by using the {@link java.util.ServiceLoader#load(Class)} - * method. The first provider of {@code JsonbProvider} class from list of providers returned by - * {@code ServiceLoader.load} call is returned. If there are no available service providers, this - * method tries to load the default service provider using {@link Class#forName(String)} method. - * - * @see java.util.ServiceLoader - * @throws JsonbException if there is no provider found, or there is a problem instantiating the - * provider instance. - * @return {@code JsonbProvider} instance - */ - @SuppressWarnings("UseSpecificCatch") - public static JsonbProvider provider() { - throw new JsonbException("Not implemented"); - } - - /** - * Creates a JSON Binding provider object by using the {@link java.util.ServiceLoader#load(Class)} - * method, matching {@code providerName}. The first provider of {@code JsonbProvider} class from - * list of providers returned by {@code ServiceLoader.load} call, matching providerName is - * returned. If no such provider is found, JsonbException is thrown. - * - * @param providerName Class name ({@code class.getName()}) to be chosen from the list of - * providers returned by {@code ServiceLoader.load(JsonbProvider.class)} call. - * @throws JsonbException if there is no provider found, or there is a problem instantiating the - * provider instance. - * @throws NullPointerException if providerName is {@code null}. - * @see java.util.ServiceLoader - * @return {@code JsonbProvider} instance - */ - @SuppressWarnings("UseSpecificCatch") - public static JsonbProvider provider(final String providerName) { - throw new JsonbException("Not implemented"); - } - - /** - * Returns a new instance of {@link jakarta.json.bind.JsonbBuilder JsonbBuilder} class. - * - *

    {@link jakarta.json.bind.JsonbBuilder JsonbBuilder} provides necessary getter methods to - * access required parameters. - * - * @return JsonbBuilder A new instance of class implementing {@link - * jakarta.json.bind.JsonbBuilder}. Always a non-null valid object. - * @see jakarta.json.bind.Jsonb - * @see jakarta.json.bind.JsonbBuilder - * @throws JsonbException If an error was encountered while creating the {@link JsonbBuilder} - * instance. - */ - public abstract JsonbBuilder create(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/stream/JsonGenerator.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/stream/JsonGenerator.java deleted file mode 100644 index 35e488d911b..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/stream/JsonGenerator.java +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.stream; - -import java.io.Closeable; -import java.io.Flushable; -import java.math.BigDecimal; -import java.math.BigInteger; - -import jakarta.json.JsonValue; -/** - * Writes JSON data to an output source in a streaming way. The class {@link jakarta.json.Json} - * contains methods to create generators for character or output streams ({@link java.io.Writer} and - * {@link java.io.OutputStream}). - * - *

    The following example shows how to create a JSON generator: - * - *

    - * 
    - * JsonGenerator generator = Json.createGenerator(...);
    - * 
    - * 
    - * - *

    The class {@link JsonGeneratorFactory} also contains methods to create {@code JsonGenerator} - * instances. {@link JsonGeneratorFactory} should be used when creating multiple generator - * instances, as in the following example: - * - *

    - * 
    - * JsonGeneratorFactory factory = Json.createGeneratorFactory();
    - * JsonGenerator generator1 = factory.createGenerator(...);
    - * JsonGenerator generator2 = factory.createGenerator(...);
    - * 
    - * 
    - * - *

    JSON objects can be created using {@code JsonGenerator} by calling the {@link - * #writeStartObject()} method and then adding name/value pairs with the {@code write} method. - * - *

    The following example shows how to generate an empty JSON object: - * - *

    - * 
    - * JsonGenerator generator = ...;
    - * generator.writeStartObject().writeEnd().close();
    - * 
    - * 
    - * - * JSON arrays can be created using {@code JsonGenerator} by calling the {@link #writeStartArray()} - * method and then adding values with the {@code write} method. - * - *

    The following example shows how to generate an empty JSON array: - * - *

    - * 
    - * JsonGenerator generator = ...;
    - * generator.writeStartArray().writeEnd().close();
    - * 
    - * 
    - * - *

    Other JSON values (that are not JSON objects or arrays) can be created by calling the - * appropiate {@code write} methods. - * - *

    The following example shows how to generate a JSON string: - * - *

    
    - * JsonGenerator generator = ...;
    - * generator.write("message").close();
    - * 
    - * - * {@code JsonGenerator} methods can be chained as in the following example: - * - *
    - * 
    - * generator
    - *     .writeStartObject()
    - *         .write("firstName", "John")
    - *         .write("lastName", "Smith")
    - *         .write("age", 25)
    - *         .writeStartObject("address")
    - *             .write("streetAddress", "21 2nd Street")
    - *             .write("city", "New York")
    - *             .write("state", "NY")
    - *             .write("postalCode", "10021")
    - *         .writeEnd()
    - *         .writeStartArray("phoneNumber")
    - *             .writeStartObject()
    - *  *                 .write("type", "home")
    - *  *                 .write("number", "212 555-1234")
    - *  *             .writeEnd()
    - *             .writeStartObject()
    - *                 .write("type", "fax")
    - *                 .write("number", "646 555-4567")
    - *             .writeEnd()
    - *         .writeEnd()
    - *     .writeEnd();
    - * generator.close();
    - * 
    - * 
    - * - * The example code above generates the following JSON (or equivalent): - * - *
    - * 
    - * {
    - *   "firstName": "John", "lastName": "Smith", "age": 25,
    - *   "address" : {
    - *       "streetAddress": "21 2nd Street",
    - *       "city": "New York",
    - *       "state": "NY",
    - *       "postalCode": "10021"
    - *   },
    - *   "phoneNumber": [
    - *       {"type": "home", "number": "212 555-1234"},
    - *       {"type": "fax", "number": "646 555-4567"}
    - *    ]
    - * }
    - * 
    - * 
    - * - * The generated JSON text must strictly conform to the grammar defined in RFC 7159. - * - * @see jakarta.json.Json - * @see JsonGeneratorFactory - */ -public interface JsonGenerator extends Flushable, /*Auto*/ Closeable { - /** - * Configuration property to generate JSON prettily. All providers must support this property. The - * value of the property could be be anything. - */ - String PRETTY_PRINTING = "jakarta.json.stream.JsonGenerator.prettyPrinting"; - - /** - * Writes the JSON start object character. It starts a new child object context within which JSON - * name/value pairs can be written to the object. This method is valid only in an array context, - * field context or in no context (when a context is not yet started). This method can only be - * called once in no context. - * - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is called within an object context or if it is - * called more than once in no context. - */ - JsonGenerator writeStartObject(); - - /** - * Writes the JSON name/start object character pair in the current object context. It starts a new - * child object context within which JSON name/value pairs can be written to the object. - * - * @param name a name within the JSON name/object pair to be written - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an object context - */ - JsonGenerator writeStartObject(String name); - - /** - * Writes the JSON name with a colon. It starts a field context, in which valid options are - * writing a value, starting an object or an array. - * - *

    Writing value closes field context, if object or array is started after field name, field - * context will be closed after object/array close. - * - * @param name name of json field - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an object context - * @since 1.1 - */ - JsonGenerator writeKey(String name); - - /** - * Writes the JSON start array character. It starts a new child array context within which JSON - * values can be written to the array. This method is valid only in an array context, field - * context or in no context (when a context is not yet started). This method can only be called - * once in no context. - * - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is called within an object context or if called - * more than once in no context - */ - JsonGenerator writeStartArray(); - - /** - * Writes the JSON name/start array character pair with in the current object context. It starts a - * new child array context within which JSON values can be written to the array. - * - * @param name a name within the JSON name/array pair to be written - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an object context - */ - JsonGenerator writeStartArray(String name); - - /** - * Writes a JSON name/value pair in the current object context. - * - * @param name a name in the JSON name/value pair to be written in current JSON object - * @param value a value in the JSON name/value pair to be written in current JSON object - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an object context - */ - JsonGenerator write(String name, JsonValue value); - - /** - * Writes a JSON name/string value pair in the current object context. The specified value is - * written as JSON string value. - * - * @param name a name in the JSON name/string pair to be written in current JSON object - * @param value a value in the JSON name/string pair to be written in current JSON object - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an object context - */ - JsonGenerator write(String name, String value); - - /** - * Writes a JSON name/number value pair in the current object context. The specified value is - * written as a JSON number value. The string {@code new BigDecimal(value).toString()} is used as - * the text value for writing. - * - * @param name a name in the JSON name/number pair to be written in current JSON object - * @param value a value in the JSON name/number pair to be written in current JSON object - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an object context. - */ - JsonGenerator write(String name, BigInteger value); - - /** - * Writes a JSON name/number value pair in the current object context. The specified value is - * written as a JSON number value. The specified value's {@code toString()} is used as the text - * value for writing. - * - * @param name a name in the JSON name/number pair to be written in current JSON object - * @param value a value in the JSON name/number pair to be written in current JSON object - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an object context. - */ - JsonGenerator write(String name, BigDecimal value); - - /** - * Writes a JSON name/number value pair in the current object context. The specified value is - * written as a JSON number value. The string {@code new BigDecimal(value).toString()} is used as - * the text value for writing. - * - * @param name a name in the JSON name/number pair to be written in current JSON object - * @param value a value in the JSON name/number pair to be written in current JSON object - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an object context. - */ - JsonGenerator write(String name, int value); - - /** - * Writes a JSON name/number value pair in the current object context. The specified value is - * written as a JSON number value. The string {@code new BigDecimal(value).toString()} is used as - * the text value for writing. - * - * @param name a name in the JSON name/number pair to be written in current JSON object - * @param value a value in the JSON name/number pair to be written in current JSON object - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an object context. - */ - JsonGenerator write(String name, long value); - - /** - * Writes a JSON name/number value pair in the current object context. The specified value is - * written as a JSON number value. The string {@code BigDecimal.valueOf(double).toString()} is - * used as the text value for writing. - * - * @param name a name in the JSON name/number pair to be written in current JSON object - * @param value a value in the JSON name/number pair to be written in current JSON object - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws NumberFormatException if the value is Not-a-Number (NaN) or infinity. - * @throws JsonGenerationException if this method is not called within an object context - */ - JsonGenerator write(String name, double value); - - /** - * Writes a JSON name/boolean value pair in the current object context. If value is true, it - * writes the JSON {@code true} value, otherwise it writes the JSON {@code false} value. - * - * @param name a name in the JSON name/boolean pair to be written in current JSON object - * @param value a value in the JSON name/boolean pair to be written in current JSON object - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an object context. - */ - JsonGenerator write(String name, boolean value); - - /** - * Writes a JSON name/null value pair in an current object context. - * - * @param name a name in the JSON name/null pair to be written in current JSON object - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an object context - */ - JsonGenerator writeNull(String name); - - /** - * Writes the end of the current context. If the current context is an array context, this method - * writes the end-of-array character (']'). If the current context is an object context, this - * method writes the end-of-object character ('}'). After writing the end of the current context, - * the parent context becomes the new current context. If parent context is field context, it is - * closed. - * - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is called in no context. - */ - JsonGenerator writeEnd(); - - /** - * Writes the specified value as a JSON value within the current array, field or root context. - * - * @param value a value to be written in current JSON array - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an array or root context. - */ - JsonGenerator write(JsonValue value); - - /** - * Writes the specified value as a JSON string value within the current array, field or root - * context. - * - * @param value a value to be written in current JSON array - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an array or root context. - */ - JsonGenerator write(String value); - - /** - * Writes the specified value as a JSON number value within the current array, field or root - * context. The specified value's {@code toString()} is used as the the text value for writing. - * - * @param value a value to be written in current JSON array - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an array or root context. - * @see jakarta.json.JsonNumber - */ - JsonGenerator write(BigDecimal value); - - /** - * Writes the specified value as a JSON number value within the current array, field or root - * context. The string {@code new BigDecimal(value).toString()} is used as the text value for - * writing. - * - * @param value a value to be written in current JSON array - * @return this generator. - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an array or root context. - * @see jakarta.json.JsonNumber - */ - JsonGenerator write(BigInteger value); - - /** - * Writes the specified value as a JSON number value within the current array, field or root - * context. The string {@code new BigDecimal(value).toString()} is used as the text value for - * writing. - * - * @param value a value to be written in current JSON array - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an array or root context. - */ - JsonGenerator write(int value); - - /** - * Writes the specified value as a JSON number value within the current array, field or root - * context. The string {@code new BigDecimal(value).toString()} is used as the text value for - * writing. - * - * @param value a value to be written in current JSON array - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an array or root context. - */ - JsonGenerator write(long value); - - /** - * Writes the specified value as a JSON number value within the current array, field or root - * context. The string {@code BigDecimal.valueOf(value).toString()} is used as the text value for - * writing. - * - * @param value a value to be written in current JSON array - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an array or root context. - * @throws NumberFormatException if the value is Not-a-Number (NaN) or infinity. - */ - JsonGenerator write(double value); - - /** - * Writes a JSON true or false value within the current array, field or root context. If value is - * true, this method writes the JSON {@code true} value, otherwise it writes the JSON {@code - * false} value. - * - * @param value a {@code boolean} value - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an array or root context. - */ - JsonGenerator write(boolean value); - - /** - * Writes a JSON null value within the current array, field or root context. - * - * @return this generator - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if this method is not called within an array or root context. - */ - JsonGenerator writeNull(); - - /** - * Closes this generator and frees any resources associated with it. This method closes the - * underlying output source. - * - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonGenerationException if an incomplete JSON is generated - */ - @Override - void close(); - - /** - * Flushes the underlying output source. If the generator has saved any characters in a buffer, - * writes them immediately to the underlying output source before flushing it. - * - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - */ - @Override - void flush(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/stream/JsonLocation.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/stream/JsonLocation.java deleted file mode 100644 index 0550e65aef4..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/stream/JsonLocation.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.stream; - -/** - * Provides the location information of a JSON event in an input source. The {@code JsonLocation} - * information can be used to identify incorrect JSON or can be used by higher frameworks to know - * about the processing location. - * - *

    All the information provided by a {@code JsonLocation} is optional. For example, a provider - * may only report line numbers. Also, there may not be any location information for an input - * source. For example, if a {@code JsonParser} is created using {@link jakarta.json.JsonArray - * JsonArray} input source, all the methods in this class return -1. - * - * @see JsonParser - * @see JsonParsingException - */ -public interface JsonLocation { - - /** - * Return the line number (starts with 1 for the first line) for the current JSON event in the - * input source. - * - * @return the line number (starts with 1 for the first line) or -1 if none is available - */ - long getLineNumber(); - - /** - * Return the column number (starts with 1 for the first column) for the current JSON event in the - * input source. - * - * @return the column number (starts with 1 for the first column) or -1 if none is available - */ - long getColumnNumber(); - - /** - * Return the stream offset into the input source this location is pointing to. If the input - * source is a file or a byte stream then this is the byte offset into that stream, but if the - * input source is a character media then the offset is the character offset. Returns -1 if there - * is no offset available. - * - * @return the offset of input source stream, or -1 if there is no offset available - */ - long getStreamOffset(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/stream/JsonParser.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/stream/JsonParser.java deleted file mode 100644 index 3a287d02b8d..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/java/jakarta/json/stream/JsonParser.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package jakarta.json.stream; - -import java.io.Closeable; -import java.math.BigDecimal; -import java.util.Map; -import java.util.stream.Stream; - -import jakarta.json.JsonArray; -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; - -/** - * Provides forward, read-only access to JSON data in a streaming way. This is the most efficient - * way for reading JSON data. This is the only way to parse and process JSON data that are too big - * to be loaded in memory. - * - *

    The class {@link jakarta.json.Json} contains methods to create parsers from input sources - * ({@link java.io.InputStream} and {@link java.io.Reader}). - * - *

    The following example demonstrates how to create a parser from a string that contains an empty - * JSON array: - * - *

    - * 
    - * JsonParser parser = Json.createParser(new StringReader("[]"));
    - * 
    - * 
    - * - *

    The class {@link JsonParserFactory} also contains methods to create {@code JsonParser} - * instances. {@link JsonParserFactory} is preferred when creating multiple parser instances. A - * sample usage is shown in the following example: - * - *

    - * 
    - * JsonParserFactory factory = Json.createParserFactory();
    - * JsonParser parser1 = factory.createParser(...);
    - * JsonParser parser2 = factory.createParser(...);
    - * 
    - * 
    - * - *

    {@code JsonParser} parses JSON using the pull parsing programming model. In this model the - * client code controls the thread and calls the method {@code next()} to advance the parser to the - * next state after processing each element. The parser can generate the following events: {@code - * START_OBJECT}, {@code END_OBJECT}, {@code START_ARRAY}, {@code END_ARRAY}, {@code KEY_NAME}, - * {@code VALUE_STRING}, {@code VALUE_NUMBER}, {@code VALUE_TRUE}, {@code VALUE_FALSE}, and {@code - * VALUE_NULL}. - * - *

    For example, for an empty JSON object ({ }), the parser generates the event {@code - * START_OBJECT} with the first call to the method {@code next()} and the event {@code END_OBJECT} - * with the second call to the method {@code next()}. The following code demonstrates how to access - * these events: - * - *

    - * 
    - * Event event = parser.next(); // START_OBJECT
    - * event = parser.next();       // END_OBJECT
    - * 
    - * 
    - * - *

    For example, for the following JSON: - * - *

    - * {
    - *   "firstName": "John", "lastName": "Smith", "age": 25,
    - *   "phoneNumber": [
    - *       { "type": "home", "number": "212 555-1234" },
    - *       { "type": "fax", "number": "646 555-4567" }
    - *    ]
    - * }
    - * 
    - * - *

    calls to the method {@code next()} result in parse events at the specified locations below - * (marked in bold): - * - *

    - * {START_OBJECT
    - *   "firstName"KEY_NAME: "John"VALUE_STRING, "lastName"KEY_NAME: "Smith"VALUE_STRING, "age"KEY_NAME: 25VALUE_NUMBER,
    - *   "phoneNumber"KEY_NAME : [START_ARRAY
    - *       {START_OBJECT "type"KEY_NAME: "home"VALUE_STRING, "number"KEY_NAME: "212 555-1234"VALUE_STRING }END_OBJECT,
    - *       {START_OBJECT "type"KEY_NAME: "fax"VALUE_STRING, "number"KEY_NAME: "646 555-4567"VALUE_STRING }END_OBJECT
    - *    ]END_ARRAY
    - * }END_OBJECT
    - * 
    - * - * The methods {@link #next()} and {@link #hasNext()} enable iteration over parser events to process - * JSON data. {@code JsonParser} provides get methods to obtain the value at the current state of - * the parser. For example, the following code shows how to obtain the value "John" from the JSON - * above: - * - *
    - * 
    - * Event event = parser.next(); // START_OBJECT
    - * event = parser.next();       // KEY_NAME
    - * event = parser.next();       // VALUE_STRING
    - * parser.getString();          // "John"
    - * 
    - * 
    - * - * Starting in version 1.1, it is possible to build a partial JSON object model from the stream, at - * the current parser position. The methods {@link #getArray} and {@link #getObject} can be used to - * read in a {@code JsonArray} or {@code JsonObject}. For example, the following code shows how to - * obtain the phoneNumber in a JsonArray, from the JSON above: - * - *
    
    - * while (parser.hasNext() {
    - *     Event event = parser.next();
    - *     if (event == JsonParser.Event.KEY_NAME ) {
    - *         String key = getString();
    - *         event = parser.next();
    - *         if (key.equals("phoneNumber") {
    - *             JsonArray phones = parser.getArray();
    - *         }
    - *     }
    - * }
    - * 
    - * - * The methods {@link #getArrayStream} and {@link #getObjectStream} can be used to get a stream of - * the elements of a {@code JsonArray} or {@code JsonObject}. For example, the following code shows - * another way to obtain John's phoneNumber in a {@code JsonArray} : - * - *
    {@code
    - * Event event = parser.next(); // START_OBJECT
    - * JsonArray phones = (JsonArray)
    - *     parser.getObjectStream().filter(e->e.getKey().equals("phoneNumber"))
    - *                             .map(e->e.getValue())
    - *                             .findFirst()
    - *                             .get();
    - * }
    - * - * The methods {@link #skipArray} and {@link #skipObject} can be used to skip tokens and position - * the parser to {@code END_ARRAY} or {@code END_OBJECT}. - * - *

    {@code JsonParser} can be used to parse sequence of JSON values that are not enclosed in a - * JSON array, e.g. { } { }. The following code demonstrates how to parse such sequence. - * - *

    
    - * JsonParser parser = Json.createParser(...);
    - * while (parser.hasNext) {
    - *     parser.next(); // advance parser state
    - *     JsonValue value = parser.getValue();
    - * }
    - * 
    - * - * @see jakarta.json.Json - * @see JsonParserFactory - */ -public interface JsonParser extends /*Auto*/ Closeable { - - /** An event from {@code JsonParser}. */ - enum Event { - /** Start of a JSON array. The position of the parser is after '['. */ - START_ARRAY, - /** Start of a JSON object. The position of the parser is after '{'. */ - START_OBJECT, - /** - * Name in a name/value pair of a JSON object. The position of the parser is after the key name. - * The method {@link #getString} returns the key name. - */ - KEY_NAME, - /** - * String value in a JSON array or object. The position of the parser is after the string value. - * The method {@link #getString} returns the string value. - */ - VALUE_STRING, - /** - * Number value in a JSON array or object. The position of the parser is after the number value. - * {@code JsonParser} provides the following methods to access the number value: {@link - * #getInt}, {@link #getLong}, and {@link #getBigDecimal}. - */ - VALUE_NUMBER, - /** - * {@code true} value in a JSON array or object. The position of the parser is after the {@code - * true} value. - */ - VALUE_TRUE, - /** - * {@code false} value in a JSON array or object. The position of the parser is after the {@code - * false} value. - */ - VALUE_FALSE, - /** - * {@code null} value in a JSON array or object. The position of the parser is after the {@code - * null} value. - */ - VALUE_NULL, - /** End of a JSON object. The position of the parser is after '}'. */ - END_OBJECT, - /** End of a JSON array. The position of the parser is after ']'. */ - END_ARRAY - } - - /** - * Returns {@code true} if there are more parsing states. This method returns {@code false} if the - * parser reaches the end of the JSON text. - * - * @return {@code true} if there are more parsing states. - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonParsingException if the parser encounters invalid JSON when advancing to next - * state. - */ - boolean hasNext(); - - /** - * Returns the event for the next parsing state. - * - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - * @throws JsonParsingException if the parser encounters invalid JSON when advancing to next - * state. - * @throws java.util.NoSuchElementException if there are no more parsing states. - * @return the event for the next parsing state - */ - Event next(); - - /** - * Returns a {@code String} for the name in a name/value pair, for a string value or a number - * value. This method should only be called when the parser state is {@link Event#KEY_NAME}, - * {@link Event#VALUE_STRING}, or {@link Event#VALUE_NUMBER}. - * - * @return a name when the parser state is {@link Event#KEY_NAME} a string value when the parser - * state is {@link Event#VALUE_STRING} a number value when the parser state is {@link - * Event#VALUE_NUMBER} - * @throws IllegalStateException when the parser state is not {@code KEY_NAME}, {@code - * VALUE_STRING}, or {@code VALUE_NUMBER} - */ - String getString(); - - /** - * Returns true if the JSON number at the current parser state is a integral number. A {@link - * BigDecimal} may be used to store the value internally and this method semantics are defined - * using its {@code scale()}. If the scale is zero, then it is considered integral type. This - * integral type information can be used to invoke an appropriate accessor method to obtain a - * numeric value as in the following example: - * - *
    -   * 
    -   * JsonParser parser = ...
    -   * if (parser.isIntegralNumber()) {
    -   *     parser.getInt();     // or other methods to get integral value
    -   * } else {
    -   *     parser.getBigDecimal();
    -   * }
    -   * 
    -   * 
    - * - * @return true if this number is a integral number, otherwise false - * @throws IllegalStateException when the parser state is not {@code VALUE_NUMBER} - */ - boolean isIntegralNumber(); - - /** - * Returns a JSON number as an integer. The returned value is equal to {@code new - * BigDecimal(getString()).intValue()}. Note that this conversion can lose information about the - * overall magnitude and precision of the number value as well as return a result with the - * opposite sign. This method should only be called when the parser state is {@link - * Event#VALUE_NUMBER}. - * - * @return an integer for a JSON number - * @throws IllegalStateException when the parser state is not {@code VALUE_NUMBER} - * @see java.math.BigDecimal#intValue() - */ - int getInt(); - - /** - * Returns a JSON number as a long. The returned value is equal to {@code new - * BigDecimal(getString()).longValue()}. Note that this conversion can lose information about the - * overall magnitude and precision of the number value as well as return a result with the - * opposite sign. This method is only called when the parser state is {@link Event#VALUE_NUMBER}. - * - * @return a long for a JSON number - * @throws IllegalStateException when the parser state is not {@code VALUE_NUMBER} - * @see java.math.BigDecimal#longValue() - */ - long getLong(); - - /** - * Returns a JSON number as a {@code BigDecimal}. The {@code BigDecimal} is created using {@code - * new BigDecimal(getString())}. This method should only called when the parser state is {@link - * Event#VALUE_NUMBER}. - * - * @return a {@code BigDecimal} for a JSON number - * @throws IllegalStateException when the parser state is not {@code VALUE_NUMBER} - */ - BigDecimal getBigDecimal(); - - /** - * Return the location that corresponds to the parser's current state in the JSON input source. - * The location information is only valid in the current parser state (or until the parser is - * advanced to a next state). - * - * @return a non-null location corresponding to the current parser state in JSON input source - */ - jakarta.json.stream.JsonLocation getLocation(); - - /** - * Returns a {@code JsonObject} and advances the parser to the corresponding {@code END_OBJECT}. - * - * @return the {@code JsonObject} at the current parser position - * @throws IllegalStateException when the parser state is not {@code START_OBJECT} - * @since 1.1 - */ - public default JsonObject getObject() { - throw new UnsupportedOperationException(); - } - - /** - * Returns a {@code JsonValue} at the current parser position. If the parser state is {@code - * START_ARRAY}, the behavior is the same as {@link #getArray}. If the parser state is {@code - * START_OBJECT}, the behavior is the same as {@link #getObject}. For all other cases, if - * applicable, the JSON value is read and returned. - * - * @return the {@code JsonValue} at the current parser position. - * @throws IllegalStateException when the parser state is {@code END_OBJECT} or {@code END_ARRAY} - * @since 1.1 - */ - public default JsonValue getValue() { - throw new UnsupportedOperationException(); - } - - /** - * Returns a {@code JsonArray} and advance the parser to the the corresponding {@code END_ARRAY}. - * - * @return the {@code JsonArray} at the current parser position - * @throws IllegalStateException when the parser state is not {@code START_ARRAY} - * @since 1.1 - */ - public default JsonArray getArray() { - throw new UnsupportedOperationException(); - } - - /** - * Returns a stream of the {@code JsonArray} elements. The parser state must be {@code - * START_ARRAY}. The elements are read lazily, on an as-needed basis, as required by the stream - * operations. If the stream operations do not consume all of the array elements, {@link - * skipArray} can be used to skip the unprocessed array elements. - * - * @return a stream of elements of the {@code JsonArray} - * @throws IllegalStateException when the parser state is not {@code START_ARRAY} - * @since 1.1 - */ - public default Stream getArrayStream() { - throw new UnsupportedOperationException(); - } - - /** - * Returns a stream of the {@code JsonObject}'s name/value pairs. The parser state must be {@code - * START_OBJECT}. The name/value pairs are read lazily, on an as-needed basis, as required by the - * stream operations. If the stream operations do not consume all of the object's name/value - * pairs, {@link skipObject} can be used to skip the unprocessed elements. - * - * @return a stream of name/value pairs of the {@code JsonObject} - * @throws IllegalStateException when the parser state is not {@code START_OBJECT} - * @since 1.1 - */ - public default Stream> getObjectStream() { - throw new UnsupportedOperationException(); - } - - /** - * Returns a stream of {@code JsonValue} from a sequence of JSON values. The values are read - * lazily, on an as-needed basis, as needed by the stream operations. - * - * @return a Stream of {@code JsonValue} - * @throws IllegalStateException if the parser is in an array or object. - * @since 1.1 - */ - public default Stream getValueStream() { - throw new UnsupportedOperationException(); - } - - /** - * Advance the parser to {@code END_ARRAY}. If the parser is in array context, i.e. it has - * previously encountered a {@code START_ARRAY} without encountering the corresponding {@code - * END_ARRAY}, the parser is advanced to the corresponding {@code END_ARRAY}. If the parser is not - * in any array context, nothing happens. - * - * @since 1.1 - */ - public default void skipArray() { - throw new UnsupportedOperationException(); - } - - /** - * Advance the parser to {@code END_OBJECT}. If the parser is in object context, i.e. it has - * previously encountered a {@code START_OBJECT} without encountering the corresponding {@code - * END_OBJECT}, the parser is advanced to the corresponding {@code END_OBJECT}. If the parser is - * not in any object context, nothing happens. - * - * @since 1.1 - */ - public default void skipObject() { - throw new UnsupportedOperationException(); - } - - /** - * Closes this parser and frees any resources associated with the parser. This method closes the - * underlying input source. - * - * @throws jakarta.json.JsonException if an i/o error occurs (IOException would be cause of - * JsonException) - */ - @Override - void close(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/resources/jakarta/JSONB.gwt.xml b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/resources/jakarta/JSONB.gwt.xml deleted file mode 100644 index 867d7108702..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/api/src/main/resources/jakarta/JSONB.gwt.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/pom.xml b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/pom.xml deleted file mode 100644 index fd38f4fac0c..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/pom.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - 4.0.0 - - org.kie.kogito.stunner.serverless.editor.third_party.jakarta.jsonb - parent - ${revision} - - - impl - jar - - GWT/J2CL compatible Jakarta JSON-B Specs Impl - GWT/J2CL compatible Jakarta JSON-B Specs Impl - - - - org.kie.kogito.stunner.serverless.editor.third_party.jakarta.jsonb - api - - - com.google.elemental2 - elemental2-core - - - org.glassfish - jakarta.json - provided - - - - - - - src/main/java - - **/*.java - - - - src/main/resources - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - package - - jar - - - - - - - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/JsonNumberImpl.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/JsonNumberImpl.java deleted file mode 100644 index 38db8ed714a..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/JsonNumberImpl.java +++ /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 jakarta.json; - -import java.math.BigDecimal; -import java.math.BigInteger; - -import elemental2.core.JsNumber; - -public class JsonNumberImpl implements JsonNumber { - - private JsNumber holder; - - public JsonNumberImpl() { - this(new JsNumber()); - } - - public JsonNumberImpl(Object holder) { - this(new JsNumber(holder)); - } - - public JsonNumberImpl(JsNumber holder) { - this.holder = holder; - } - - @Override - public boolean isIntegral() { - throw new UnsupportedOperationException(); - } - - @Override - public int intValue() { - return Integer.valueOf(holder.toString()); - } - - @Override - public int intValueExact() { - throw new UnsupportedOperationException(); - } - - @Override - public long longValue() { - return Long.valueOf(holder.toString()); - } - - @Override - public long longValueExact() { - throw new UnsupportedOperationException(); - } - - public Number numberValue() { - return Double.valueOf(new JsNumber(holder).valueOf()); - } - - @Override - public BigInteger bigIntegerValue() { - throw new UnsupportedOperationException(); - } - - @Override - public BigInteger bigIntegerValueExact() { - throw new UnsupportedOperationException(); - } - - @Override - public double doubleValue() { - return holder.valueOf(); - } - - @Override - public BigDecimal bigDecimalValue() { - throw new UnsupportedOperationException(); - } - - @Override - public ValueType getValueType() { - return ValueType.NUMBER; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/JsonObjectDecorator.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/JsonObjectDecorator.java deleted file mode 100644 index 652ca0aea30..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/JsonObjectDecorator.java +++ /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 jakarta.json; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -public class JsonObjectDecorator implements JsonObject { - - public JsonObject holder; - - public JsonObjectDecorator(JsonObject holder) { - this.holder = holder; - } - - @Override - public JsonArray getJsonArray(String name) { - return holder.getJsonArray(name); - } - - @Override - public JsonObject getJsonObject(String name) { - return holder.getJsonObject(name); - } - - @Override - public JsonNumber getJsonNumber(String name) { - - return holder.getJsonNumber(name); - } - - @Override - public JsonString getJsonString(String name) { - return holder.getJsonString(name); - } - - @Override - public String getString(String name) { - return holder.getString(name); - } - - @Override - public String getString(String name, String defaultValue) { - return holder.getString(name, defaultValue); - } - - @Override - public int getInt(String name) { - if (holder.containsKey(name)) { - return holder.getInt(name); - } else { - return 0; - } - } - - public Integer getInteger(String name) { - if (holder.containsKey(name)) { - return holder.getInt(name); - } - return null; - } - - @Override - public int getInt(String name, int defaultValue) { - return holder.getInt(name, defaultValue); - } - - @Override - public boolean getBoolean(String name) { - if (holder.containsKey(name)) { - return holder.getBoolean(name); - } else { - return false; - } - } - - public Boolean getBooleanBoxed(String name) { - if (holder.containsKey(name)) { - return holder.getBoolean(name); - } else { - return null; - } - } - - @Override - public boolean getBoolean(String name, boolean defaultValue) { - return holder.getBoolean(name, defaultValue); - } - - @Override - public boolean isNull(String name) { - return holder.isNull(name); - } - - @Override - public ValueType getValueType() { - return holder.getValueType(); - } - - @Override - public int size() { - return holder.size(); - } - - @Override - public boolean isEmpty() { - return holder.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return holder.containsKey(key); - } - - @Override - public boolean containsValue(Object value) { - return holder.containsValue(value); - } - - @Override - public JsonValue get(Object key) { - if (!holder.containsKey(key)) { - return null; - } - return holder.get(key); - } - - @Override - public JsonValue put(String key, JsonValue value) { - return holder.put(key, value); - } - - @Override - public JsonValue remove(Object key) { - return holder.remove(key); - } - - @Override - public void putAll(Map m) { - holder.putAll(m); - } - - @Override - public void clear() { - holder.clear(); - } - - @Override - public Set keySet() { - return holder.keySet(); - } - - @Override - public Collection values() { - return holder.values(); - } - - @Override - public Set> entrySet() { - return holder.entrySet(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/JsonStringImpl.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/JsonStringImpl.java deleted file mode 100644 index 6859ba7065f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/JsonStringImpl.java +++ /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 jakarta.json; - -import elemental2.core.JsString; - -public class JsonStringImpl implements JsonString { - - private JsString holder; - - public JsonStringImpl(Object holder) { - this(new JsString(holder)); - } - - public JsonStringImpl(String holder) { - this(new JsString(holder)); - } - - public JsonStringImpl(JsString holder) { - this.holder = holder; - } - - @Override - public String getString() { - return holder.toString_(); - } - - @Override - public CharSequence getChars() { - return holder.toString_(); - } - - @Override - public ValueType getValueType() { - return ValueType.STRING; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/JsonValueDecorator.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/JsonValueDecorator.java deleted file mode 100644 index 2211cddc9ce..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/JsonValueDecorator.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package jakarta.json; - -import java.math.BigDecimal; -import java.math.BigInteger; - -import elemental2.core.JsBoolean; -import elemental2.core.JsNumber; -import jakarta.json.stream.gwt.JsonObjectImpl; -import jakarta.json.stream.gwt.JsonValueImpl; -import jsinterop.base.Js; - -public class JsonValueDecorator { - - JreDecorator decorator = new JreDecorator(); - - public JsonValueDecorator(Object object) { - decorator.setDelegate(object); - } - - public Integer asInteger() { - return decorator.getInteger(); - } - - public Double asDouble() { - return decorator.getDouble(); - } - - public Float asFloat() { - return decorator.getFloat(); - } - - public Long asLong() { - return decorator.getLong(); - } - - public Byte asByte() { - return decorator.getByte(); - } - - public Short asShort() { - return decorator.getShort(); - } - - public Character asCharacter() { - return decorator.getCharacter(); - } - - public String asString() { - return decorator.getString(); - } - - public Boolean asBoolean() { - return decorator.getBoolean(); - } - - public BigInteger asBigInteger() { - return decorator.getBigInteger(); - } - - public BigDecimal asBigDecimal() { - return decorator.getBigDecimal(); - } - - private static class GWTDecorator { - - private JsonObjectImpl delegate; - - public GWTDecorator setDelegate(Object delegate) { - if (delegate instanceof jakarta.json.stream.gwt.JsonValueImpl) { - this.delegate = (JsonObjectImpl) ((JsonValueImpl) delegate).asJsonObject(); - } else { - this.delegate = (JsonObjectImpl) delegate; - } - return this; - }; - - public Integer getInteger() { - return Double.valueOf(Js.uncheckedCast(delegate).valueOf()).intValue(); - } - - public Double getDouble() { - return new JsNumber(delegate).valueOf(); - } - - public Float getFloat() { - return Double.valueOf(new JsNumber(delegate).valueOf()).floatValue(); - } - - public Long getLong() { - return Double.valueOf(new JsNumber(delegate).valueOf()).longValue(); - } - - public Byte getByte() { - return Double.valueOf(new JsNumber(delegate).valueOf()).byteValue(); - } - - public Short getShort() { - return (short) Double.valueOf(new JsNumber(delegate).valueOf()).intValue(); - } - - public Character getCharacter() { - return (char) Double.valueOf(new JsNumber(delegate).valueOf()).intValue(); - } - - public String getString() { - if (delegate == null) { - return null; - } - return Js.asString(delegate.__holder__); - } - - public Boolean getBoolean() { - return new JsBoolean(delegate.__holder__).valueOf(); - } - - public BigInteger getBigInteger() { - return BigDecimal.valueOf(new JsNumber(delegate).valueOf()).toBigInteger(); - } - - public BigDecimal getBigDecimal() { - return BigDecimal.valueOf(new JsNumber(delegate).valueOf()); - } - } - - private static class JreDecorator extends GWTDecorator { - - @GwtIncompatible private JsonValue delegate; - - @Override - @GwtIncompatible - public GWTDecorator setDelegate(Object delegate) { - this.delegate = (JsonValue) delegate; - return this; - }; - - @Override - @GwtIncompatible - public Integer getInteger() { - return ((JsonNumber) delegate).intValue(); - } - - @Override - @GwtIncompatible - public Double getDouble() { - return ((JsonNumber) delegate).doubleValue(); - } - - @Override - @GwtIncompatible - public Float getFloat() { - return ((JsonNumber) delegate).numberValue().floatValue(); - } - - @Override - @GwtIncompatible - public Long getLong() { - return ((JsonNumber) delegate).numberValue().longValue(); - } - - @Override - @GwtIncompatible - public Byte getByte() { - return ((JsonNumber) delegate).numberValue().byteValue(); - } - - @Override - @GwtIncompatible - public Short getShort() { - return (short) ((JsonNumber) delegate).intValue(); - } - - @Override - @GwtIncompatible - public Character getCharacter() { - return (char) ((JsonNumber) delegate).intValue(); - } - - @Override - @GwtIncompatible - public String getString() { - if (delegate == null) { - return null; - } - return ((JsonString) delegate).getString(); - } - - @Override - @GwtIncompatible - public Boolean getBoolean() { - return delegate.getValueType().equals(JsonValue.ValueType.TRUE) ? true : false; - } - - @Override - @GwtIncompatible - public BigInteger getBigInteger() { - return ((JsonNumber) delegate).bigIntegerValue(); - } - - @Override - @GwtIncompatible - public BigDecimal getBigDecimal() { - return ((JsonNumber) delegate).bigDecimalValue(); - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/bind/serializer/JsonDeserializationContext.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/bind/serializer/JsonDeserializationContext.java deleted file mode 100644 index 8806605845e..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/bind/serializer/JsonDeserializationContext.java +++ /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 jakarta.json.bind.serializer; - -import java.io.StringReader; -import java.lang.reflect.Type; - -import jakarta.json.GwtIncompatible; -import jakarta.json.stream.JsonParser; -import jakarta.json.stream.JsonParserImpl; -import jakarta.json.stream.gwt.JsonObjectImpl; - -public class JsonDeserializationContext implements DeserializationContext { - - public JsonParser createParser(String json) { - return new JREParserFactory().createParser(json); - } - - @Override - public T deserialize(Class clazz, JsonParser parser) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public T deserialize(Type type, JsonParser parser) { - throw new UnsupportedOperationException("Not supported yet."); - } - - private static class GWTParserFactory { - public JsonParser createParser(String json) { - return new JsonParserImpl(new JsonObjectImpl(json)); - } - } - - private static class JREParserFactory extends GWTParserFactory { - @GwtIncompatible - @Override - public JsonParser createParser(String json) { - return jakarta.json.Json.createParser(new StringReader(json)); - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/bind/serializer/JsonSerializationContext.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/bind/serializer/JsonSerializationContext.java deleted file mode 100644 index 643e1480863..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/bind/serializer/JsonSerializationContext.java +++ /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. - */ - -package jakarta.json.bind.serializer; - -import jakarta.json.GwtIncompatible; -import jakarta.json.JsonObjectBuilder; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonGeneratorDecorator; -import jakarta.json.stream.gwt.GWTJsonGenerator; -import jakarta.json.stream.gwt.JsonObjectBuilderImpl; -import jakarta.json.stream.jre.JreJsonGenerator; - -public class JsonSerializationContext implements SerializationContext { - - @Override - public void serialize(String key, T object, JsonGenerator generator) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void serialize(T object, JsonGenerator generator) { - throw new UnsupportedOperationException("Not supported yet."); - } - - public JsonGeneratorDecorator createGenerator() { - return new JREGenerator().createGenerator(this); - } - - private static class GWTGenerator { - - public JsonGeneratorDecorator createGenerator(SerializationContext ctx) { - JsonObjectBuilder builder = new JsonObjectBuilderImpl(); - JsonGeneratorDecorator generator = new GWTJsonGenerator(builder, ctx); - return generator; - } - } - - private static class JREGenerator extends GWTGenerator { - - @GwtIncompatible - @Override - public JsonGeneratorDecorator createGenerator(SerializationContext ctx) { - JsonObjectBuilder builder = jakarta.json.Json.createObjectBuilder(); - JsonGeneratorDecorator generator = new JreJsonGenerator(builder, ctx); - return generator; - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/ContextedJsonGenerator.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/ContextedJsonGenerator.java deleted file mode 100644 index 5b80dd790e8..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/ContextedJsonGenerator.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package jakarta.json.stream; - -import java.math.BigDecimal; -import java.math.BigInteger; - -import jakarta.json.JsonValue; - -public class ContextedJsonGenerator extends JsonGeneratorDecorator { - - private final String name; - private final JsonGenerator generator; - - public ContextedJsonGenerator(String name, JsonGenerator generator) { - super(null, null); - this.name = name; - this.generator = generator; - } - - @Override - public JsonGenerator writeStartObject() { - return generator.writeStartObject(name); - } - - @Override - public JsonGenerator writeStartObject(String name) { - return generator.writeStartObject(name); - } - - @Override - public JsonGenerator writeKey(String name) { - return generator.writeKey(name); - } - - @Override - public JsonGenerator writeStartArray() { - return generator.writeStartObject(name); - } - - @Override - public JsonGenerator writeStartArray(String name) { - return generator.writeStartArray(name); - } - - @Override - public JsonGenerator write(String name, JsonValue value) { - return generator.write(name, value); - } - - @Override - public JsonGenerator write(String name, String value) { - return generator.write(name, value); - } - - @Override - public JsonGenerator write(String name, BigInteger value) { - return generator.write(name, value); - } - - @Override - public JsonGenerator write(String name, BigDecimal value) { - return generator.write(name, value); - } - - @Override - public JsonGenerator write(String name, int value) { - return generator.write(name, value); - } - - @Override - public JsonGenerator write(String name, long value) { - return generator.write(name, value); - } - - @Override - public JsonGenerator write(String name, double value) { - return generator.write(name, value); - } - - @Override - public JsonGenerator write(String name, boolean value) { - return generator.write(name, value); - } - - @Override - public JsonGenerator writeNull(String name) { - return generator.writeNull(name); - } - - @Override - public JsonGenerator writeEnd() { - return generator.writeEnd(); - } - - @Override - public JsonGenerator write(JsonValue value) { - return write(name, value); - } - - @Override - public JsonGenerator write(String value) { - return write(name, value); - } - - @Override - public JsonGenerator write(BigDecimal value) { - return write(name, value); - } - - @Override - public JsonGenerator write(BigInteger value) { - return write(name, value); - } - - @Override - public JsonGenerator write(int value) { - return write(name, value); - } - - @Override - public JsonGenerator write(long value) { - return write(name, value); - } - - @Override - public JsonGenerator write(double value) { - return write(name, value); - } - - @Override - public JsonGenerator write(boolean value) { - return write(name, value); - } - - @Override - public JsonGenerator writeNull() { - return writeNull(name); - } - - @Override - public void close() { - generator.close(); - } - - @Override - public void flush() { - generator.flush(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonArrayGenerator.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonArrayGenerator.java deleted file mode 100644 index 8525d212cf6..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonArrayGenerator.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package jakarta.json.stream; - -import java.math.BigDecimal; -import java.math.BigInteger; - -import jakarta.json.JsonArrayBuilder; -import jakarta.json.JsonObjectBuilder; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.jre.JreJsonGenerator; - -public class JsonArrayGenerator extends JreJsonGenerator { - - private final JsonArrayBuilder arrayBuilder; - private final String name; - - public JsonArrayGenerator( - JsonArrayBuilder arrayBuilder, - JsonObjectBuilder builder, - String name, - SerializationContext ctx) { - super(builder, ctx); - this.arrayBuilder = arrayBuilder; - this.name = name; - } - - @Override - public JsonGenerator writeStartObject() { - return new JsonGeneratorDecorator(builder, ctx) { - @Override - public JsonGenerator writeEnd() { - arrayBuilder.add(builder.build()); - return this; - } - }; - } - - @Override - public JsonGenerator writeEnd() { - builder.add(name, arrayBuilder); - return this; - } - - public JsonGenerator write(JsonGeneratorDecorator value) { - arrayBuilder.add(value.builder); - return this; - } - - @Override - public JsonGenerator write(JsonValue value) { - arrayBuilder.add(value); - return this; - } - - @Override - public JsonGenerator write(String value) { - arrayBuilder.add(value); - return this; - } - - @Override - public JsonGenerator write(BigDecimal value) { - arrayBuilder.add(value); - return this; - } - - @Override - public JsonGenerator write(BigInteger value) { - arrayBuilder.add(value); - return this; - } - - @Override - public JsonGenerator write(int value) { - arrayBuilder.add(value); - return this; - } - - @Override - public JsonGenerator write(long value) { - arrayBuilder.add(value); - return this; - } - - @Override - public JsonGenerator write(double value) { - arrayBuilder.add(value); - return this; - } - - @Override - public JsonGenerator write(boolean value) { - arrayBuilder.add(value); - return this; - } - - @Override - public JsonGenerator writeNull() { - arrayBuilder.addNull(); - return this; - } - - @Override - public void close() {} - - @Override - public void flush() {} -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonGeneratorDecorator.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonGeneratorDecorator.java deleted file mode 100644 index 69be318c6d4..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonGeneratorDecorator.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package jakarta.json.stream; - -import java.math.BigDecimal; -import java.math.BigInteger; - -import elemental2.core.JsArray; -import jakarta.json.JsonObjectBuilder; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.JsonSerializationContext; -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.gwt.GwtArrayJsonGenerator; - -public class JsonGeneratorDecorator implements JsonGenerator { - - protected final JsonObjectBuilder builder; - - protected final JsonSerializationContext ctx; - - public JsonGeneratorDecorator(JsonObjectBuilder builder, SerializationContext ctx) { - this.builder = builder; - this.ctx = (JsonSerializationContext) ctx; - } - - @Override - public JsonGenerator writeStartObject() { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator writeStartObject(String name) { - JsonObjectBuilder objBuilder = ctx.createGenerator().builder(); - return new JsonNestedObjecGenerator(builder, objBuilder, name, ctx); - } - - @Override - public JsonGenerator writeKey(String name) { - return new ContextedJsonGenerator(name, this); - } - - @Override - public JsonGenerator writeStartArray() { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator writeStartArray(String name) { - JsArray array = new JsArray(); - GwtArrayJsonGenerator generator = new GwtArrayJsonGenerator(array, ctx); - builder.add(name, generator); - return generator; - } - - @Override - public JsonGenerator write(String name, JsonValue value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(String name, String value) { - if (value != null) builder.add(name, value); - return this; - } - - @Override - public JsonGenerator write(String name, BigInteger value) { - if (value != null) builder.add(name, value); - return this; - } - - @Override - public JsonGenerator write(String name, BigDecimal value) { - if (value != null) builder.add(name, value); - return this; - } - - @Override - public JsonGenerator write(String name, int value) { - builder.add(name, value); - return this; - } - - public JsonGenerator write(String name, Integer value) { - if (value != null) builder.add(name, value); - return this; - } - - public JsonGenerator write(String name, Character value) { - if (value != null) builder.add(name, value); - return this; - } - - public JsonGenerator write(String name, Float value) { - if (value != null) builder.add(name, value); - return this; - } - - public JsonGenerator write(String name, Short value) { - if (value != null) builder.add(name, value); - return this; - } - - @Override - public JsonGenerator write(String name, long value) { - builder.add(name, value); - return this; - } - - public JsonGenerator write(String name, Long value) { - if (value != null) builder.add(name, value); - return this; - } - - @Override - public JsonGenerator write(String name, double value) { - builder.add(name, value); - return this; - } - - public JsonGenerator write(String name, Double value) { - if (value != null) builder.add(name, value); - return this; - } - - @Override - public JsonGenerator write(String name, boolean value) { - builder.add(name, value); - return this; - } - - public JsonGenerator write(String name, Boolean value) { - if (value != null) builder.add(name, value); - return this; - } - - @Override - public JsonGenerator writeNull(String name) { - builder.addNull(name); - return this; - } - - @Override - public JsonGenerator writeEnd() { - builder.build(); - return this; - } - - @Override - public JsonGenerator write(JsonValue value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(String value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(BigDecimal value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(BigInteger value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(int value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(long value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(double value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(boolean value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator writeNull() { - throw new UnsupportedOperationException(); - } - - @Override - public void close() {} - - @Override - public void flush() {} - - public JsonObjectBuilder builder() { - return builder; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonNestedObjecGenerator.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonNestedObjecGenerator.java deleted file mode 100644 index 6bbe7dff2cf..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonNestedObjecGenerator.java +++ /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 jakarta.json.stream; - -import jakarta.json.JsonObjectBuilder; -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.jre.JreJsonGenerator; - -public class JsonNestedObjecGenerator extends JreJsonGenerator { - - private final JsonObjectBuilder parent; - private final String name; - - public JsonNestedObjecGenerator( - JsonObjectBuilder parent, JsonObjectBuilder builder, String name, SerializationContext ctx) { - super(builder, ctx); - this.parent = parent; - this.name = name; - } - - @Override - public JsonGenerator writeEnd() { - parent.add(name, builder); - return this; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonParserImpl.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonParserImpl.java deleted file mode 100644 index ac115604e80..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonParserImpl.java +++ /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. - */ - -package jakarta.json.stream; - -import java.math.BigDecimal; - -import jakarta.json.JsonArray; -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; -import jakarta.json.JsonValueDecorator; - -public class JsonParserImpl implements JsonParser { - - private JsonValue holder; - - public JsonParserImpl(JsonValue holder) { - this.holder = holder; - } - - @Override - public boolean hasNext() { - return false; - } - - @Override - public Event next() { - if (holder != null - && (holder.getValueType() != null && holder.getValueType() == JsonValue.ValueType.OBJECT)) { - return Event.START_OBJECT; - } - return null; - } - - public JsonArray getArray() { - if (holder.getValueType() == JsonValue.ValueType.ARRAY) { - return holder.asJsonArray(); - } - throw new IllegalStateException("Not an array"); - } - - public JsonObject getObject() { - if (holder.getValueType() == JsonValue.ValueType.OBJECT) { - if (holder instanceof JsonObject) { - return (JsonObject) holder; - } - return holder.asJsonObject(); - } - throw new IllegalStateException("Not an object"); - } - - public JsonValue getValue() { - return holder; - } - - @Override - public String getString() { - if (holder.getValueType().equals(JsonValue.ValueType.STRING)) { - return new JsonValueDecorator(holder).asString(); - } - throw new IllegalStateException("Not a string"); - } - - @Override - public boolean isIntegralNumber() { - throw new UnsupportedOperationException(); - } - - @Override - public int getInt() { - if (holder.getValueType().equals(JsonValue.ValueType.NUMBER)) { - return new JsonValueDecorator(holder).asInteger(); - } - throw new IllegalStateException("Not a int"); - } - - @Override - public long getLong() { - if (holder.getValueType().equals(JsonValue.ValueType.NUMBER)) { - return new JsonValueDecorator(holder).asLong(); - } - throw new IllegalStateException("Not a long"); - } - - @Override - public BigDecimal getBigDecimal() { - throw new UnsupportedOperationException(); - } - - @Override - public JsonLocation getLocation() { - throw new UnsupportedOperationException(); - } - - @Override - public void close() {} -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonbPropertyDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonbPropertyDeserializer.java deleted file mode 100644 index 90d026cd6bb..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonbPropertyDeserializer.java +++ /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 jakarta.json.stream; - -import jakarta.json.JsonObjectDecorator; -import jakarta.json.bind.serializer.DeserializationContext; - -@FunctionalInterface -public interface JsonbPropertyDeserializer { - - void accept(T t, JsonObjectDecorator u, DeserializationContext context); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonbPropertySerializer.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonbPropertySerializer.java deleted file mode 100644 index 94fcdae258c..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/JsonbPropertySerializer.java +++ /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 jakarta.json.stream; - -import jakarta.json.bind.serializer.SerializationContext; - -@FunctionalInterface -public interface JsonbPropertySerializer { - - void accept(T t, JsonGeneratorDecorator u, SerializationContext context); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/GWTJsonGenerator.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/GWTJsonGenerator.java deleted file mode 100644 index 6934fd0fb4d..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/GWTJsonGenerator.java +++ /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 jakarta.json.stream.gwt; - -import java.math.BigDecimal; -import java.math.BigInteger; - -import jakarta.json.JsonObjectBuilder; -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonGeneratorDecorator; - -public class GWTJsonGenerator extends JsonGeneratorDecorator { - - public GWTJsonGenerator(JsonObjectBuilder builder, SerializationContext ctx) { - super(builder, ctx); - } - - @Override - public JsonGenerator write(String name, String value) { - if (value != null) { - builder.add(name, value); - } - return this; - } - - @Override - public JsonGenerator write(String name, BigInteger value) { - builder.add(name, value); - return this; - } - - @Override - public JsonGenerator write(String name, BigDecimal value) { - builder.add(name, value); - return this; - } - - @Override - public JsonGenerator write(String name, int value) { - builder.add(name, value); - return this; - } - - @Override - public JsonGenerator write(String name, long value) { - builder.add(name, value); - return this; - } - - @Override - public JsonGenerator write(String name, double value) { - builder.add(name, value); - return this; - } - - @Override - public JsonGenerator write(String name, boolean value) { - builder.add(name, value); - return this; - } - - @Override - public JsonGenerator writeNull(String name) { - builder.addNull(name); - return this; - } - - public JsonObjectBuilder builder() { - return builder; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/GwtArrayJsonGenerator.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/GwtArrayJsonGenerator.java deleted file mode 100644 index 12c24b9090e..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/GwtArrayJsonGenerator.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package jakarta.json.stream.gwt; - -import java.math.BigDecimal; -import java.math.BigInteger; - -import elemental2.core.JsArray; -import elemental2.core.JsNumber; -import jakarta.json.JsonArray; -import jakarta.json.JsonArrayBuilder; -import jakarta.json.JsonObjectBuilder; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonGeneratorDecorator; - -public class GwtArrayJsonGenerator extends JsonGeneratorDecorator implements JsonArrayBuilder { - - private final JsArray array; - - public GwtArrayJsonGenerator(JsArray array, SerializationContext ctx) { - super(null, ctx); - this.array = array; - } - - @Override - public JsonGenerator writeStartObject() { - JsonObjectBuilderImpl builder = new JsonObjectBuilderImpl(); - return new JsonGeneratorDecorator(builder, ctx) { - @Override - public JsonGenerator writeEnd() { - array.push(builder.build().asJsonObject()); - return this; - } - }; - } - - @Override - public JsonGenerator writeStartObject(String name) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator writeKey(String name) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator writeStartArray() { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator writeStartArray(String name) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(String name, JsonValue value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(String name, String value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(String name, BigInteger value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(String name, BigDecimal value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(String name, int value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(String name, long value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(String name, double value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator write(String name, boolean value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator writeNull(String name) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonGenerator writeEnd() { - return this; - } - - @Override - public JsonGenerator write(JsonValue value) { - array.push(value.asJsonObject()); - return this; - } - - @Override - public JsonGenerator write(String value) { - array.push(value); - return this; - } - - @Override - public JsonGenerator write(BigDecimal value) { - array.push(value); - return this; - } - - @Override - public JsonGenerator write(BigInteger value) { - array.push(value); - return this; - } - - @Override - public JsonGenerator write(int value) { - array.push(new JsNumber(value)); - return this; - } - - @Override - public JsonGenerator write(long value) { - array.push(new JsNumber(value)); - return this; - } - - @Override - public JsonGenerator write(double value) { - array.push(value); - return this; - } - - @Override - public JsonGenerator write(boolean value) { - array.push(value); - return this; - } - - @Override - public JsonGenerator writeNull() { - return null; - } - - @Override - public void close() {} - - @Override - public void flush() {} - - @Override - public JsonArrayBuilder add(JsonValue value) { - array.push(value); - return this; - } - - @Override - public JsonArrayBuilder add(String value) { - array.push(value); - return this; - } - - @Override - public JsonArrayBuilder add(BigDecimal value) { - array.push(value); - return this; - } - - @Override - public JsonArrayBuilder add(BigInteger value) { - array.push(value); - return this; - } - - @Override - public JsonArrayBuilder add(int value) { - array.push(value); - return this; - } - - @Override - public JsonArrayBuilder add(long value) { - array.push(value); - return this; - } - - @Override - public JsonArrayBuilder add(double value) { - array.push(value); - return this; - } - - @Override - public JsonArrayBuilder add(boolean value) { - array.push(value); - return this; - } - - @Override - public JsonArrayBuilder addNull() { - return null; - } - - @Override - public JsonArrayBuilder add(JsonObjectBuilder builder) { - array.push(builder.build()); - return this; - } - - @Override - public JsonArrayBuilder add(JsonArrayBuilder builder) { - array.push(((GwtArrayJsonGenerator) builder).array); - return this; - } - - @Override - public JsonArray build() { - return new JsonArrayImpl(array); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/JsonArrayImpl.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/JsonArrayImpl.java deleted file mode 100644 index a12835927f7..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/JsonArrayImpl.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package jakarta.json.stream.gwt; - -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -import elemental2.core.JsArray; -import jakarta.json.JsonArray; -import jakarta.json.JsonNumber; -import jakarta.json.JsonNumberImpl; -import jakarta.json.JsonObject; -import jakarta.json.JsonString; -import jakarta.json.JsonStringImpl; -import jakarta.json.JsonValue; - -public class JsonArrayImpl implements JsonArray { - - JsArray array; - - public JsonArrayImpl() { - this(new JsArray()); - } - - public JsonArrayImpl(JsArray array) { - this.array = array; - } - - @Override - public JsonArray asJsonArray() { - return this; - } - - @Override - public JsonObject getJsonObject(int index) { - return new JsonObjectImpl(array.getAt(index)); - } - - @Override - public JsonArray getJsonArray(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonNumber getJsonNumber(int index) { - return new JsonNumberImpl(array.getAt(index)); - } - - @Override - public JsonString getJsonString(int index) { - return new JsonStringImpl(array.getAt(index)); - } - - @Override - public List getValuesAs(Class clazz) { - throw new UnsupportedOperationException(); - } - - @Override - public String getString(int index) { - return new JsonStringImpl(array.getAt(index)).getString(); - } - - @Override - public String getString(int index, String defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public int getInt(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public int getInt(int index, int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean getBoolean(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean getBoolean(int index, boolean defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isNull(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public ValueType getValueType() { - return ValueType.ARRAY; - } - - @Override - public int size() { - return array.length; - } - - @Override - public boolean isEmpty() { - return array == null || array.length == 0; - } - - @Override - public boolean contains(Object o) { - return array.includes(o); - } - - @Override - public Iterator iterator() { - throw new UnsupportedOperationException(); - } - - @Override - public Object[] toArray() { - throw new UnsupportedOperationException(); - } - - @Override - public T[] toArray(T[] a) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean add(JsonValue jsonValue) { - array.push(jsonValue); - return true; - } - - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean addAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean addAll(int index, Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removeAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean retainAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - while (array.length > 0) { - array.pop(); - } - } - - @Override - public JsonValue get(int index) { - return new JsonValueImpl(array.getAt(index)); - } - - @Override - public JsonValue set(int index, JsonValue element) { - JsonValue old = new JsonValueImpl(array.getAt(index)); - array.setAt(index, ((JsonValueImpl) element).__holder__); - return old; - } - - @Override - public void add(int index, JsonValue element) { - array.setAt(index, ((JsonValueImpl) element).__holder__); - } - - @Override - public JsonValue remove(int index) { - JsonValue old = new JsonValueImpl(array.getAt(index)); - array.delete(index); - return old; - } - - @Override - public int indexOf(Object o) { - return array.indexOf(o); - } - - @Override - public int lastIndexOf(Object o) { - return array.lastIndexOf(o); - } - - @Override - public ListIterator listIterator() { - throw new UnsupportedOperationException(); - } - - @Override - public ListIterator listIterator(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public List subList(int fromIndex, int toIndex) { - throw new UnsupportedOperationException(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/JsonObjectBuilderImpl.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/JsonObjectBuilderImpl.java deleted file mode 100644 index 937d6ab2213..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/JsonObjectBuilderImpl.java +++ /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. - */ - -package jakarta.json.stream.gwt; - -import java.math.BigDecimal; -import java.math.BigInteger; - -import elemental2.core.JsNumber; -import jakarta.json.JsonArrayBuilder; -import jakarta.json.JsonObject; -import jakarta.json.JsonObjectBuilder; -import jakarta.json.JsonValue; -import jsinterop.base.JsPropertyMap; - -public class JsonObjectBuilderImpl implements JsonObjectBuilder { - - private final JsPropertyMap object = JsPropertyMap.of(); - - public JsonObjectBuilderImpl() {} - - @Override - public JsonObjectBuilder add(String name, JsonValue value) { - if (value instanceof JsonArrayImpl) { - object.set(name, ((JsonArrayImpl) value).array); - } else { - object.set(name, value); - } - return this; - } - - @Override - public JsonObjectBuilder add(String name, String value) { - if (value != null) { - object.set(name, value); - } - return this; - } - - @Override - public JsonObjectBuilder add(String name, BigInteger value) { - if (value != null) { - object.set(name, value.toString()); - } - return this; - } - - @Override - public JsonObjectBuilder add(String name, BigDecimal value) { - if (value != null) { - object.set(name, value.toString()); - } - return this; - } - - @Override - public JsonObjectBuilder add(String name, int value) { - object.set(name, value); - return this; - } - - @Override - public JsonObjectBuilder add(String name, long value) { - object.set(name, new JsNumber(value)); - return this; - } - - @Override - public JsonObjectBuilder add(String name, double value) { - object.set(name, value); - return this; - } - - @Override - public JsonObjectBuilder add(String name, boolean value) { - object.set(name, value); - return this; - } - - @Override - public JsonObjectBuilder addNull(String name) { - object.set(name, null); - return this; - } - - @Override - public JsonObjectBuilder add(String name, JsonObjectBuilder builder) { - object.set(name, ((JsonObjectBuilderImpl) builder).object); - return this; - } - - @Override - public JsonObjectBuilder add(String name, JsonArrayBuilder builder) { - JsonArrayImpl impl = (JsonArrayImpl) builder.build(); - object.set(name, impl.array); - return this; - } - - @Override - public JsonObject build() { - return new JsonObjectImpl(object); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/JsonObjectImpl.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/JsonObjectImpl.java deleted file mode 100644 index dc950f15ca9..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/JsonObjectImpl.java +++ /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 jakarta.json.stream.gwt; - -import java.util.Collection; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import elemental2.core.Global; -import elemental2.core.JsArray; -import elemental2.core.Reflect; -import jakarta.json.JsonArray; -import jakarta.json.JsonNumber; -import jakarta.json.JsonNumberImpl; -import jakarta.json.JsonObject; -import jakarta.json.JsonString; -import jakarta.json.JsonStringImpl; -import jakarta.json.JsonValue; -import jakarta.json.bind.JsonbException; -import jsinterop.base.Js; - -public class JsonObjectImpl implements JsonObject { - - public Object __holder__; // TODO make it private - - public JsonObjectImpl(String json) { - this(Global.JSON.parse(json)); - } - - public JsonObjectImpl(Object holder) { - this.__holder__ = holder; - } - - @Override - public JsonArray getJsonArray(String name) { - if (Reflect.has(__holder__, name)) { - JsArray array = Js.uncheckedCast(Reflect.get(__holder__, name)); - return new JsonArrayImpl(array); - } - return null; - } - - @Override - public JsonObject getJsonObject(String name) { - if (Reflect.has(__holder__, name)) { - return new JsonObjectImpl(Reflect.get(__holder__, name)); - } - return null; - } - - @Override - public JsonNumber getJsonNumber(String name) { - if (Reflect.has(__holder__, name)) { - return new JsonNumberImpl(Js.asPropertyMap(__holder__).get(name)); - } - return null; - } - - @Override - public JsonString getJsonString(String name) { - if (Reflect.has(__holder__, name)) { - return new JsonStringImpl(Js.asPropertyMap(__holder__).get(name).toString()); - } - return null; - } - - @Override - public String getString(String name) { - if (Reflect.has(__holder__, name)) { - return Js.asPropertyMap(__holder__).get(name).toString(); - } - return null; - } - - @Override - public String getString(String name, String defaultValue) { - if (Reflect.has(__holder__, name)) { - return Js.asPropertyMap(__holder__).get(name).toString(); - } - return defaultValue; - } - - @Override - public int getInt(String name) { - return Integer.valueOf(Js.asPropertyMap(__holder__).get(name).toString()); - } - - @Override - public int getInt(String name, int defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean getBoolean(String name) { - return Boolean.valueOf(Js.asPropertyMap(__holder__).get(name).toString()); - } - - @Override - public boolean getBoolean(String name, boolean defaultValue) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isNull(String name) { - throw new UnsupportedOperationException(); - } - - @Override - public ValueType getValueType() { - if (JsArray.isArray(__holder__)) { - return ValueType.ARRAY; - } - String type = Js.typeof(__holder__).toLowerCase(Locale.ROOT); - if (type.equals("number")) { - return ValueType.NUMBER; - } else if (type.equals("string")) { - return ValueType.STRING; - } else if (type.equals("boolean")) { - if (__holder__.toString().toLowerCase(Locale.ROOT).equals("true")) { - return ValueType.TRUE; - } else { - return ValueType.FALSE; - } - } else if (type.equals("null")) { - return ValueType.NULL; - } else if (type.equals("object")) { - return ValueType.OBJECT; - } - - throw new IllegalStateException("Unknown type: " + type); - } - - @Override - public int size() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isEmpty() { - return Global.JSON.stringify(__holder__).equals("{}"); - } - - @Override - public boolean containsKey(Object key) { - return Js.asPropertyMap(__holder__).has(key.toString()); - } - - @Override - public boolean containsValue(Object value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonValue get(Object key) { - return new JsonObjectImpl(Js.asPropertyMap(__holder__).get(key.toString())); - } - - @Override - public JsonValue put(String key, JsonValue value) { - throw new UnsupportedOperationException(); - } - - @Override - public JsonValue remove(Object key) { - throw new UnsupportedOperationException(); - } - - @Override - public void putAll(Map m) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - } - - @Override - public Set keySet() { - return Reflect.ownKeys(__holder__).asList().stream() - .map(Reflect.OwnKeysArrayUnionType::asString) - .collect(Collectors.toSet()); - } - - @Override - public Collection values() { - throw new UnsupportedOperationException(); - } - - @Override - public Set> entrySet() { - throw new UnsupportedOperationException(); - } - - public Double asBoxedDouble() { - return Js.uncheckedCast(__holder__); - } - - @Override - public JsonObject asJsonObject() { - return Js.uncheckedCast(__holder__); // TODO wrong impl - } - - @Override - public JsonArray asJsonArray() { - if (getValueType() == ValueType.ARRAY) { - return new JsonArrayImpl(Js.uncheckedCast(__holder__)); - } - throw new JsonbException("JsonValue is not an array"); - } - - @Override - public String toString() { - return Global.JSON.stringify(__holder__); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/JsonValueImpl.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/JsonValueImpl.java deleted file mode 100644 index 99cc2005c99..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/gwt/JsonValueImpl.java +++ /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. - */ - -package jakarta.json.stream.gwt; - -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; -import jsinterop.base.Js; - -public class JsonValueImpl implements JsonValue { - - Object __holder__; - - public JsonValueImpl(Object holder) { - this.__holder__ = holder; - } - - @Override - public ValueType getValueType() { - return new JsonObjectImpl(__holder__).getValueType(); - } - - public JsonObject asJsonObject() { - if (this instanceof JsonObject) { - return Js.uncheckedCast(this); - } - return new JsonObjectImpl(__holder__); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/jre/JreJsonGenerator.java b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/jre/JreJsonGenerator.java deleted file mode 100644 index 8c5ae363cc2..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/java/jakarta/json/stream/jre/JreJsonGenerator.java +++ /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 jakarta.json.stream.jre; - -import jakarta.json.GwtIncompatible; -import jakarta.json.JsonArrayBuilder; -import jakarta.json.JsonObjectBuilder; -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonArrayGenerator; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonGeneratorDecorator; - -public class JreJsonGenerator extends JsonGeneratorDecorator { - - public JreJsonGenerator(JsonObjectBuilder builder, SerializationContext ctx) { - super(builder, ctx); - } - - @GwtIncompatible - @Override - public JsonGenerator writeStartArray(String name) { - JsonArrayBuilder arrayBuilder = jakarta.json.Json.createArrayBuilder(); - return new JsonArrayGenerator(arrayBuilder, builder, name, ctx); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/resources/jakarta/JSONBImpl.gwt.xml b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/resources/jakarta/JSONBImpl.gwt.xml deleted file mode 100644 index adab613e019..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/impl/src/main/resources/jakarta/JSONBImpl.gwt.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/pom.xml b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/pom.xml deleted file mode 100644 index 1af5a374b32..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/jsonb/pom.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - org.kie.kogito.stunner.serverless.editor.third_party.jakarta - parent - ${revision} - - 4.0.0 - pom - - org.kie.kogito.stunner.serverless.editor.third_party.jakarta.jsonb - parent - - GWT/J2CL compatible Jakarta JSON-B Specs parent - GWT/J2CL compatible Jakarta JSON-B Specs parent - - - api - impl - - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/pom.xml b/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/pom.xml deleted file mode 100644 index 57ec3d18d21..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/jakarta-spec/pom.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - third_party - org.kie.kogito.stunner.serverless.editor.third_party - ${revision} - - 4.0.0 - - org.kie.kogito.stunner.serverless.editor.third_party.jakarta - parent - pom - - GWT/J2CL compatible Jakarta Specs - GWT/J2CL compatible Jakarta Specs - - - jsonb - - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/pom.xml b/packages/serverless-workflow-diagram-editor/third_party/pom.xml index fcd0eea0689..833ced821b8 100644 --- a/packages/serverless-workflow-diagram-editor/third_party/pom.xml +++ b/packages/serverless-workflow-diagram-editor/third_party/pom.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > - stunner-editors-parent + serverless-workflow-diagram-editor-parent org.kie.kogito.stunner.serverless.editor ${revision} diff --git a/packages/serverless-workflow-diagram-editor/third_party/stdlib/pom.xml b/packages/serverless-workflow-diagram-editor/third_party/stdlib/pom.xml deleted file mode 100644 index 220c561d466..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/stdlib/pom.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - third_party - org.kie.kogito.stunner.serverless.editor.third_party - ${revision} - - 4.0.0 - - stdlib - jar - - GWT/J2CL compatible missed classes from stdlib - GWT/J2CL missed classes from stdlib - - - - com.google.elemental2 - elemental2-webstorage - - - - - - - src/main/java - - **/*.java - - - - src/main/resources - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - default-compile - compile - - compile - - - true - - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - package - - jar - - - - - - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/lang/ClassNotFoundException.java b/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/lang/ClassNotFoundException.java deleted file mode 100644 index 0025438144b..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/lang/ClassNotFoundException.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package java.lang; - -public class ClassNotFoundException extends Exception {} diff --git a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/Calendar.java b/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/Calendar.java deleted file mode 100644 index 3cf637cabf7..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/Calendar.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package java.util; - -import elemental2.core.JsDate; -import jsinterop.base.Js; - -public final class Calendar { - public static final int MONTH = 2; - public static final int DAY_OF_MONTH = 5; - - public static final int HOUR_OF_DAY = 11; - public static final int MINUTE = 12; - public static final int SECOND = 13; - - protected Calendar() {} - - public static Calendar getInstance() { - return Js.uncheckedCast(new JsDate()); - } - - public int get(int field) { - switch (field) { - case 2: - return Js.uncheckedCast(this).getMonth(); - case 5: - return Js.uncheckedCast(this).getDate(); - case 11: - return Js.uncheckedCast(this).getHours(); - case 12: - return Js.uncheckedCast(this).getMinutes(); - case 13: - return Js.uncheckedCast(this).getSeconds(); - default: - throw new UnsupportedOperationException("Unsupported Calendar field " + field); - } - } /*-{ - switch(field) { - case 2: - return this.getMonth(); - case 5: - return this.getDate(); - case 11: - return this.getHours(); - case 12: - return this.getMinutes(); - case 13: - return this.getSeconds(); - default: - throw "Unsupported Calendar field " + field; - } - }-*/; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/StringTokenizer.java b/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/StringTokenizer.java deleted file mode 100644 index 3066b32b12e..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/StringTokenizer.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package java.util; - -public class StringTokenizer { - private final String deli; - private final String s; - private final int len; - - private int pos; - private String next; - - public StringTokenizer(String s, String deli) { - this.s = s; - this.deli = deli; - len = s.length(); - } - - public StringTokenizer(String s) { - this(s, " \t\n\r\f"); - } - - public String nextToken() { - if (!hasMoreTokens()) { - throw new NoSuchElementException(); - } - String result = next; - next = null; - return result; - } - - public boolean hasMoreTokens() { - if (next != null) { - return true; - } - // skip leading delimiters - while (pos < len && deli.indexOf(s.charAt(pos)) != -1) { - pos++; - } - - if (pos >= len) { - return false; - } - - int p0 = pos++; - while (pos < len && deli.indexOf(s.charAt(pos)) == -1) { - pos++; - } - - next = s.substring(p0, pos++); - return true; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/UUID.java b/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/UUID.java deleted file mode 100644 index c8f31091d2f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/UUID.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package java.util; - -import java.io.Serializable; - -/** - * UUID class. - * - * @author senk.christian@gmail.com - * @version $Id: $Id - */ -public class UUID implements Serializable, Comparable { - - private static final long serialVersionUID = 7373345728974414241L; - private static final char[] CHARS = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); - - private String value; - - /** */ - private UUID() {} - - /** - * fromString. - * - * @param uuidString a {@link String} object. - * @return a {@link UUID} object. - */ - public static UUID fromString(String uuidString) { - // TODO: Validation - - final UUID uuid = new UUID(); - uuid.value = uuidString; - - return uuid; - } - - /** - * randomUUID. - * - * @return a {@link UUID} object. - */ - public static UUID randomUUID() { - return fromString(generateUUIDString()); - } - - /** Generate a RFC4122, version 4 ID. Example: "92329D39-6F5C-4520-ABFC-AAB64544E172" */ - private static String generateUUIDString() { - char[] uuid = new char[36]; - int r; - - // rfc4122 requires these characters - uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'; - uuid[14] = '4'; - - // Fill in random data. At i==19 set the high bits of clock sequence as - // per rfc4122, sec. 4.1.5 - for (int i = 0; i < 36; i++) { - if (uuid[i] == 0) { - r = (int) (Math.random() * 16); - uuid[i] = CHARS[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf]; - } - } - return new String(uuid); - } - - /* (non-Javadoc) - * @see java.lang.Comparable#compareTo(java.lang.Object) - */ - /** {@inheritDoc} */ - @Override - public int compareTo(UUID arg0) { - return value.compareTo(arg0.value); - } - - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ - /** {@inheritDoc} */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((value == null) ? 0 : value.hashCode()); - return result; - } - - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - /** {@inheritDoc} */ - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - UUID other = (UUID) obj; - if (value == null) { - if (other.value != null) return false; - } else if (!value.equals(other.value)) return false; - return true; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - /** {@inheritDoc} */ - @Override - public String toString() { - return value; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/regex/Matcher.java b/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/regex/Matcher.java deleted file mode 100644 index b022bfee6a5..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/regex/Matcher.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package java.util.regex; - -import elemental2.core.JsRegExp; -import elemental2.core.RegExpResult; - -public class Matcher { - private final JsRegExp regExp; - private final String input; - private final RegExpResult matchResult; - - Matcher(Pattern pattern, CharSequence input) { - this.regExp = pattern.regExp; - this.input = String.valueOf(input); - matchResult = regExp.exec(this.input); - } - - public boolean find() { - return regExp.test(input); - } - - public boolean matches() { - return regExp.test(input); - } - - public String group(int group) { - return matchResult.getAt(group); - } - - public String group(String group) { - return matchResult.groups.get(group); - } - - public static String quoteReplacement(String s) { - if ((s.indexOf('\\') == -1) && (s.indexOf('$') == -1)) return s; - StringBuilder sb = new StringBuilder(s.length()); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - if (c == '\\' || c == '$') { - sb.append('\\'); - } - sb.append(c); - } - return sb.toString(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/regex/Pattern.java b/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/regex/Pattern.java deleted file mode 100644 index fb58bd2bf6d..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/regex/Pattern.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package java.util.regex; - -import elemental2.core.JsRegExp; - -public class Pattern { - - final JsRegExp regExp; - - private Pattern(String regExp) { - this.regExp = new JsRegExp(regExp); - } - - public static Pattern compile(String regex) { - return new Pattern(regex); - } - - public Matcher matcher(CharSequence input) { - return new Matcher(this, input); - } - - public static String quote(String s) { - int slashEIndex = s.indexOf("\\E"); - if (slashEIndex == -1) return "\\Q" + s + "\\E"; - - int lenHint = s.length(); - lenHint = - (lenHint < Integer.MAX_VALUE - 8 - lenHint) ? (lenHint << 1) : (Integer.MAX_VALUE - 8); - - StringBuilder sb = new StringBuilder(lenHint); - sb.append("\\Q"); - int current = 0; - do { - sb.append(s, current, slashEIndex).append("\\E\\\\E\\Q"); - current = slashEIndex + 2; - } while ((slashEIndex = s.indexOf("\\E", current)) != -1); - - return sb.append(s, current, s.length()).append("\\E").toString(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/regex/PatternSyntaxException.java b/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/regex/PatternSyntaxException.java deleted file mode 100644 index cd709c6d301..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/java/org/kie/workbench/common/gwt/emul/client/java/util/regex/PatternSyntaxException.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package java.util.regex; - -public class PatternSyntaxException extends Exception {} diff --git a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/resources/org/kie/workbench/common/gwt/emul/Stdlib.gwt.xml b/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/resources/org/kie/workbench/common/gwt/emul/Stdlib.gwt.xml deleted file mode 100644 index 1a2bb6c8336..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/stdlib/src/main/resources/org/kie/workbench/common/gwt/emul/Stdlib.gwt.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/pom.xml b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/pom.xml deleted file mode 100644 index bbbe879643f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/pom.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - org.kie.kogito.stunner.serverless.editor.third_party.tooling.marshalling.json - parent - ${revision} - - 4.0.0 - - common - jar - - GWT/J2CL Jakarta JSON Binding commons - GWT/J2CL Jakarta JSON Binding commons - - - - org.kie.kogito.stunner.serverless.editor.third_party.jakarta.jsonb - api - - - org.kie.kogito.stunner.serverless.editor.third_party.jakarta.jsonb - impl - - - com.google.elemental2 - elemental2-core - - - com.google.elemental2 - elemental2-dom - - - com.google.jsinterop - base - - - org.glassfish - jakarta.json - - - - - - - src/main/java - - **/*.java - - - - src/main/resources - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - package - - jar - - - - - - - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/AbstractObjectMapper.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/AbstractObjectMapper.java deleted file mode 100644 index 4531178d3ab..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/AbstractObjectMapper.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper; - -import jakarta.json.bind.serializer.DeserializationContext; -import jakarta.json.bind.serializer.JsonDeserializationContext; -import jakarta.json.bind.serializer.JsonSerializationContext; -import jakarta.json.bind.serializer.JsonbDeserializer; -import jakarta.json.bind.serializer.JsonbSerializer; -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGeneratorDecorator; -import jakarta.json.stream.JsonParser; - -public abstract class AbstractObjectMapper { - - protected abstract JsonbDeserializer newDeserializer(); - - protected abstract JsonbSerializer newSerializer(); - - public T fromJSON(String json) { - return fromJSON(json, new JsonDeserializationContext()); - } - - public T fromJSON(String json, DeserializationContext context) { - JsonParser parser = ((JsonDeserializationContext) context).createParser(json); - return newDeserializer().deserialize(parser, context, null); - } - - public String toJSON(T bean) { - return toJSON(bean, new JsonSerializationContext()); - } - - public String toJSON(T bean, SerializationContext context) { - JsonGeneratorDecorator generator = ((JsonSerializationContext) context).createGenerator(); - newSerializer().serialize(bean, generator, context); - return generator.builder().build().toString(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/annotation/JSONMapper.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/annotation/JSONMapper.java deleted file mode 100644 index e6c36ed09d9..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/annotation/JSONMapper.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface JSONMapper {} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/Pair.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/Pair.java deleted file mode 100644 index edc81fcda23..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/Pair.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal; - -public class Pair { - - public final K k; - public final V v; - - public Pair(K k, V v) { - this.k = k; - this.v = v; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/AbstractBeanJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/AbstractBeanJsonDeserializer.java deleted file mode 100644 index ca9a46d6c6d..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/AbstractBeanJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer; - -import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.Map; - -import jakarta.json.JsonObject; -import jakarta.json.JsonObjectDecorator; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import jakarta.json.stream.JsonParser; -import jakarta.json.stream.JsonbPropertyDeserializer; - - -public abstract class AbstractBeanJsonDeserializer extends JsonbDeserializer - implements jakarta.json.bind.serializer.JsonbDeserializer { - - protected Map> properties = new HashMap(); - - @Override - public T deserialize(JsonValue value, DeserializationContext ctx) { - if (value instanceof JsonObject) { - return deserialize((JsonObject) value, ctx); - } - return deserialize(value.asJsonObject(), ctx); - } - - @Override - public T deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { - JsonParser.Event event = parser.next(); - if (event == JsonParser.Event.START_OBJECT) { - return deserialize(parser.getObject(), ctx); - } - return null; - } - - public T deserialize(JsonObject jsonObject, DeserializationContext ctx) { - if (jsonObject == null) { - return null; - } - T instance = newInstance(); - if (!jsonObject.isEmpty()) { - JsonObjectDecorator jsonObjectDecorator = new JsonObjectDecorator(jsonObject); - properties.forEach( - (key, value) -> { - if (jsonObjectDecorator.containsKey(key)) { - value.accept(instance, jsonObjectDecorator, ctx); - } - }); - } - return instance; - } - - protected abstract T newInstance(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/BaseNumberJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/BaseNumberJsonDeserializer.java deleted file mode 100644 index 4c94bd29775..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/BaseNumberJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer; - -import java.math.BigDecimal; -import java.math.BigInteger; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.JsonValueDecorator; -import jakarta.json.bind.serializer.DeserializationContext; - - -public abstract class BaseNumberJsonDeserializer extends JsonbDeserializer { - - public static final class BigDecimalJsonDeserializer - extends BaseNumberJsonDeserializer { - - @Override - public BigDecimal deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - if (json == null) { - return null; - } - return new JsonValueDecorator(json).asBigDecimal(); - } - } - - public static final class BigIntegerJsonDeserializer - extends BaseNumberJsonDeserializer { - - @Override - public BigInteger deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - if (json == null) { - return null; - } - return new JsonValueDecorator(json).asBigInteger(); - } - } - - public static final class ByteJsonDeserializer extends BaseNumberJsonDeserializer { - - @Override - public Byte deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - if (json == null) { - return null; - } - return new JsonValueDecorator(json).asByte(); - } - } - - public static final class DoubleJsonDeserializer extends BaseNumberJsonDeserializer { - - @Override - public Double deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - if (json == null) { - return null; - } - return new JsonValueDecorator(json).asDouble(); - } - } - - public static final class FloatJsonDeserializer extends BaseNumberJsonDeserializer { - - @Override - public Float deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - if (json == null) { - return null; - } - return new JsonValueDecorator(json).asFloat(); - } - } - - public static final class IntegerJsonDeserializer extends BaseNumberJsonDeserializer { - - @Override - public Integer deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - if (json == null) { - return null; - } - return new JsonValueDecorator(json).asInteger(); - } - } - - public static final class LongJsonDeserializer extends BaseNumberJsonDeserializer { - - @Override - public Long deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - if (json == null) { - return null; - } - return new JsonValueDecorator(json).asLong(); - } - } - - public static final class ShortJsonDeserializer extends BaseNumberJsonDeserializer { - - @Override - public Short deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - if (json == null) { - return null; - } - return new JsonValueDecorator(json).asShort(); - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/BooleanJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/BooleanJsonDeserializer.java deleted file mode 100644 index 191e10bac51..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/BooleanJsonDeserializer.java +++ /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. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.JsonValueDecorator; -import jakarta.json.bind.serializer.DeserializationContext; - -public class BooleanJsonDeserializer extends JsonbDeserializer { - - @Override - public Boolean deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - if (json == null) { - return null; - } - return new JsonValueDecorator(json).asBoolean(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/CharacterJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/CharacterJsonDeserializer.java deleted file mode 100644 index f3e058208e5..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/CharacterJsonDeserializer.java +++ /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. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.JsonValueDecorator; -import jakarta.json.bind.serializer.DeserializationContext; - -public class CharacterJsonDeserializer extends JsonbDeserializer { - - @Override - public Character deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - if (json == null) { - return null; - } - return new JsonValueDecorator(json).asCharacter(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/DeserializerJsonbTypeSerializerWrapper.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/DeserializerJsonbTypeSerializerWrapper.java deleted file mode 100644 index 78348a89403..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/DeserializerJsonbTypeSerializerWrapper.java +++ /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. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer; - -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import jakarta.json.stream.JsonParserImpl; - -public class DeserializerJsonbTypeSerializerWrapper extends JsonbDeserializer { - - private final jakarta.json.bind.serializer.JsonbDeserializer deserializer; - private final Class clazz; - - public DeserializerJsonbTypeSerializerWrapper( - jakarta.json.bind.serializer.JsonbDeserializer deserializer, Class clazz) { - this.deserializer = deserializer; - this.clazz = clazz; - } - - @Override - public T deserialize(JsonValue value, DeserializationContext ctx) { - return deserializer.deserialize(new JsonParserImpl(value), ctx, clazz); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/EnumJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/EnumJsonDeserializer.java deleted file mode 100644 index 3b60e1f2495..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/EnumJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer; - -import java.util.function.Function; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; - -public class EnumJsonDeserializer> extends JsonbDeserializer { - - private final Function func; - - private final Class enumClass; - - private final StringJsonDeserializer stringJsonDeserializer = new StringJsonDeserializer(); - - public EnumJsonDeserializer(Class enumClass, Function func) { - this.enumClass = enumClass; - this.func = func; - } - - @Override - public E deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - String asString = stringJsonDeserializer.deserialize(json, ctx); - return getEnum(asString); - } - - public > E getEnum(String name) { - E result = (E) func.apply(name); - if (result != null) { - return result; - } - throw new IllegalArgumentException( - "[" + name + "] is not a valid enum constant for Enum type " + enumClass.getName()); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/JsonbDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/JsonbDeserializer.java deleted file mode 100644 index 0f8b538c8a4..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/JsonbDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer; - -import java.lang.reflect.Type; - -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import jakarta.json.stream.JsonParser; - -public abstract class JsonbDeserializer - implements jakarta.json.bind.serializer.JsonbDeserializer { - - public abstract T deserialize(JsonValue value, DeserializationContext ctx); - - @Override - public T deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { - return deserialize(parser.getValue(), ctx); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/JsonbSubtypeDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/JsonbSubtypeDeserializer.java deleted file mode 100644 index 85253cafa71..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/JsonbSubtypeDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer; - -import java.util.HashMap; -import java.util.Map; - -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.Pair; - -public class JsonbSubtypeDeserializer extends JsonbDeserializer { - - private Map types = new HashMap<>(); - private final String typeFieldName; - - public JsonbSubtypeDeserializer(String typeFieldName, Pair... pairs) { - this.typeFieldName = typeFieldName; - for (Pair pair : pairs) { - types.put(pair.k, pair.v); - } - } - - @Override - public T deserialize(JsonValue value, DeserializationContext ctx) { - JsonObject valueHolder = - (value instanceof JsonObject) ? ((JsonObject) value) : value.asJsonObject(); - if (valueHolder.containsKey(typeFieldName)) { - if (types.containsKey(valueHolder.getString(typeFieldName))) { - return (T) types.get(valueHolder.getString(typeFieldName)).deserialize(value, ctx); - } - } - throw new Error("Unknown type " + value); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/StringJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/StringJsonDeserializer.java deleted file mode 100644 index 2dad8dcfdac..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/StringJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer; - -import jakarta.json.JsonException; -import jakarta.json.JsonString; -import jakarta.json.JsonValue; -import jakarta.json.JsonValueDecorator; -import jakarta.json.bind.serializer.DeserializationContext; - -public class StringJsonDeserializer extends JsonbDeserializer { - - @Override - public String deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - if (json instanceof JsonString) { - return ((JsonString) json).getString(); - } - return new JsonValueDecorator(json).asString(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/AbstractArrayJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/AbstractArrayJsonDeserializer.java deleted file mode 100644 index 1e8cac61e7a..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/AbstractArrayJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array; - -import java.util.ArrayList; -import java.util.List; - -import jakarta.json.JsonArray; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.JsonbDeserializer; - -public abstract class AbstractArrayJsonDeserializer extends JsonbDeserializer { - - protected List deserializeIntoList( - JsonValue json, JsonbDeserializer internalDeser, DeserializationContext ctx) { - if (json == null) { - return null; - } - List collection = new ArrayList<>(); - JsonArray array = json.asJsonArray(); - - if (array.isEmpty()) { - return collection; - } - - for (int i = 0; i < array.size(); i++) { - collection.add(internalDeser.deserialize(array.get(i), ctx)); - } - return collection; - } - - @Override - public T deserialize(JsonValue value, DeserializationContext ctx) { - throw new UnsupportedOperationException(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/ArrayJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/ArrayJsonDeserializer.java deleted file mode 100644 index 0ee9af43cff..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/ArrayJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array; - -import java.util.List; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.JsonbDeserializer; - -public class ArrayJsonDeserializer extends AbstractArrayJsonDeserializer { - - private final JsonbDeserializer deserializer; - private final ArrayCreator arrayCreator; - - public ArrayJsonDeserializer(JsonbDeserializer deserializer, ArrayCreator arrayCreator) { - if (null == deserializer) { - throw new IllegalArgumentException("deserializer cannot be null"); - } - if (null == arrayCreator) { - throw new IllegalArgumentException("Cannot deserialize an array without an arrayCreator"); - } - this.deserializer = deserializer; - this.arrayCreator = arrayCreator; - } - - /** {@inheritDoc} */ - public T[] deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - List list = deserializeIntoList(json, deserializer, ctx); - if (list == null) { - return null; - } - return list.toArray(arrayCreator.create(list.size())); - } - - @FunctionalInterface - public interface ArrayCreator { - - T[] create(int length); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveBooleanArrayJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveBooleanArrayJsonDeserializer.java deleted file mode 100644 index 50c707b75ab..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveBooleanArrayJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array; - -import java.util.List; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BooleanJsonDeserializer; - -public class PrimitiveBooleanArrayJsonDeserializer - extends AbstractArrayJsonDeserializer { - - private final BooleanJsonDeserializer deser = new BooleanJsonDeserializer(); - - @Override - public boolean[] deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - List list = deserializeIntoList(json, deser, ctx); - - boolean[] result = new boolean[list.size()]; - int i = 0; - for (Boolean value : list) { - if (null != value) { - result[i] = value; - } - i++; - } - return result; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveByteArrayJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveByteArrayJsonDeserializer.java deleted file mode 100644 index c4bf6600c3a..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveByteArrayJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array; - -import java.util.List; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; - -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.ByteJsonDeserializer; - -public class PrimitiveByteArrayJsonDeserializer extends AbstractArrayJsonDeserializer { - - private final ByteJsonDeserializer deser = new ByteJsonDeserializer(); - - @Override - public byte[] deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - List list = deserializeIntoList(json, deser, ctx); - - byte[] result = new byte[list.size()]; - int i = 0; - for (Byte value : list) { - if (null != value) { - result[i] = value; - } - i++; - } - return result; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveCharacterArrayJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveCharacterArrayJsonDeserializer.java deleted file mode 100644 index b6c694a9b8f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveCharacterArrayJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array; - -import java.util.List; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.CharacterJsonDeserializer; - -public class PrimitiveCharacterArrayJsonDeserializer extends AbstractArrayJsonDeserializer { - - private final CharacterJsonDeserializer deser = new CharacterJsonDeserializer(); - - @Override - public char[] deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - List list = deserializeIntoList(json, deser, ctx); - - char[] result = new char[list.size()]; - int i = 0; - for (Character value : list) { - if (null != value) { - result[i] = value; - } - i++; - } - return result; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveDoubleArrayJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveDoubleArrayJsonDeserializer.java deleted file mode 100644 index f362b366802..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveDoubleArrayJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array; - -import java.util.List; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; - -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.DoubleJsonDeserializer; - -public class PrimitiveDoubleArrayJsonDeserializer extends AbstractArrayJsonDeserializer { - - private final DoubleJsonDeserializer deser = new DoubleJsonDeserializer(); - - @Override - public double[] deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - List list = deserializeIntoList(json, deser, ctx); - - double[] result = new double[list.size()]; - int i = 0; - for (Double value : list) { - if (null != value) { - result[i] = value; - } - i++; - } - return result; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveFloatArrayJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveFloatArrayJsonDeserializer.java deleted file mode 100644 index 48776003749..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveFloatArrayJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array; - -import java.util.List; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; - -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.FloatJsonDeserializer; - -public class PrimitiveFloatArrayJsonDeserializer extends AbstractArrayJsonDeserializer { - - private final FloatJsonDeserializer deser = new FloatJsonDeserializer(); - - @Override - public float[] deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - List list = deserializeIntoList(json, deser, ctx); - - float[] result = new float[list.size()]; - int i = 0; - for (Float value : list) { - if (null != value) { - result[i] = value; - } - i++; - } - return result; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveIntegerArrayJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveIntegerArrayJsonDeserializer.java deleted file mode 100644 index 2960e5f85ee..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveIntegerArrayJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array; - -import java.util.List; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; - -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.IntegerJsonDeserializer; - -public class PrimitiveIntegerArrayJsonDeserializer extends AbstractArrayJsonDeserializer { - - private final IntegerJsonDeserializer deser = new IntegerJsonDeserializer(); - - @Override - public int[] deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - List list = deserializeIntoList(json, deser, ctx); - - int[] result = new int[list.size()]; - int i = 0; - for (Integer value : list) { - if (null != value) { - result[i] = value; - } - i++; - } - return result; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveLongArrayJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveLongArrayJsonDeserializer.java deleted file mode 100644 index 598935b11b6..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveLongArrayJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array; - -import java.util.List; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; - -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.LongJsonDeserializer; - -public class PrimitiveLongArrayJsonDeserializer extends AbstractArrayJsonDeserializer { - - private final LongJsonDeserializer deser = - new LongJsonDeserializer(); - - @Override - public long[] deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - List list = deserializeIntoList(json, deser, ctx); - - long[] result = new long[list.size()]; - int i = 0; - for (Long value : list) { - if (null != value) { - result[i] = value; - } - i++; - } - return result; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveShortArrayJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveShortArrayJsonDeserializer.java deleted file mode 100644 index 6f2a437f78c..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/PrimitiveShortArrayJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array; - -import java.util.List; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; - -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.ShortJsonDeserializer; - -public class PrimitiveShortArrayJsonDeserializer extends AbstractArrayJsonDeserializer { - - private final ShortJsonDeserializer deser = new ShortJsonDeserializer(); - - @Override - public short[] deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - List list = deserializeIntoList(json, deser, ctx); - - short[] result = new short[list.size()]; - int i = 0; - for (Short value : list) { - if (null != value) { - result[i] = value; - } - i++; - } - return result; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/StringArrayJsonDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/StringArrayJsonDeserializer.java deleted file mode 100644 index 0301f157125..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/array/StringArrayJsonDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array; - -import java.util.List; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.StringJsonDeserializer; - -public class StringArrayJsonDeserializer extends AbstractArrayJsonDeserializer { - - private final StringJsonDeserializer deser = new StringJsonDeserializer(); - - @Override - public String[] deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - List list = deserializeIntoList(json, deser, ctx); - - String[] result = new String[list.size()]; - int i = 0; - for (String value : list) { - if (null != value) { - result[i] = value; - } - i++; - } - return result; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/ArrayListDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/ArrayListDeserializer.java deleted file mode 100644 index 7bbe6654cc2..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/ArrayListDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection; - -import java.util.ArrayList; - -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.JsonbDeserializer; - -public class ArrayListDeserializer extends CollectionDeserializer, T> { - - public ArrayListDeserializer(JsonbDeserializer deserializer) { - super(deserializer); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/CollectionCreator.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/CollectionCreator.java deleted file mode 100644 index 1d19d51d342..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/CollectionCreator.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection; - -import java.util.Collection; - -@FunctionalInterface -public interface CollectionCreator { - - Collection create(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/CollectionDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/CollectionDeserializer.java deleted file mode 100644 index 2c64c804356..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/CollectionDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection; - -import java.util.Collection; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.JsonbDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array.AbstractArrayJsonDeserializer; - - -public class CollectionDeserializer, T> - extends AbstractArrayJsonDeserializer { - - protected final JsonbDeserializer deserializer; - - public CollectionDeserializer(JsonbDeserializer deserializer) { - this.deserializer = deserializer; - } - - public C deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - Collection list = deserializeIntoList(json, deserializer, ctx); - if (list == null) { - return null; - } - return (C) list; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/HashSetDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/HashSetDeserializer.java deleted file mode 100644 index 39aea266529..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/HashSetDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.JsonbDeserializer; - -public class HashSetDeserializer extends CollectionDeserializer, T> { - - public HashSetDeserializer(JsonbDeserializer deserializer) { - super(deserializer); - } - - public HashSet deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - Collection list = deserializeIntoList(json, deserializer, ctx); - if (list == null) { - return null; - } - return new HashSet<>(list); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/LinkedHashSetDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/LinkedHashSetDeserializer.java deleted file mode 100644 index 0dad12469c0..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/LinkedHashSetDeserializer.java +++ /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. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection; - -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.Set; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.JsonbDeserializer; - -public class LinkedHashSetDeserializer extends CollectionDeserializer, T> { - - public LinkedHashSetDeserializer(JsonbDeserializer deserializer) { - super(deserializer); - } - - public LinkedHashSet deserialize(JsonValue json, DeserializationContext ctx) - throws JsonException { - Collection list = deserializeIntoList(json, deserializer, ctx); - if (list == null) { - return null; - } - return new LinkedHashSet<>(list); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/LinkedListDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/LinkedListDeserializer.java deleted file mode 100644 index 278b6530fc2..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/LinkedListDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection; - -import java.util.Collection; -import java.util.LinkedList; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.JsonbDeserializer; - -public class LinkedListDeserializer extends CollectionDeserializer, T> { - - public LinkedListDeserializer(JsonbDeserializer deserializer) { - super(deserializer); - } - - public LinkedList deserialize(JsonValue json, DeserializationContext ctx) - throws JsonException { - Collection list = deserializeIntoList(json, deserializer, ctx); - if (list == null) { - return null; - } - return new LinkedList<>(list); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/ListDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/ListDeserializer.java deleted file mode 100644 index 5b7d42f508c..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/ListDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection; - -import java.util.List; - -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.JsonbDeserializer; - -public class ListDeserializer extends CollectionDeserializer, T> { - - public ListDeserializer(JsonbDeserializer deserializer) { - super(deserializer); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/SortedSetDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/SortedSetDeserializer.java deleted file mode 100644 index 2f250b6ac4c..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/deserializer/collection/SortedSetDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection; - -import java.util.Collection; -import java.util.Set; -import java.util.TreeSet; - -import jakarta.json.JsonException; -import jakarta.json.JsonValue; -import jakarta.json.bind.serializer.DeserializationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.JsonbDeserializer; - -public class SortedSetDeserializer extends CollectionDeserializer, T> { - - public SortedSetDeserializer(JsonbDeserializer deserializer) { - super(deserializer); - } - - public TreeSet deserialize(JsonValue json, DeserializationContext ctx) throws JsonException { - Collection list = deserializeIntoList(json, deserializer, ctx); - if (list == null) { - return null; - } - return new TreeSet<>(list); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/AbstractBeanJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/AbstractBeanJsonSerializer.java deleted file mode 100644 index 2b37048d5c0..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/AbstractBeanJsonSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer; - -import java.util.ArrayList; -import java.util.List; - -import jakarta.json.bind.serializer.JsonbSerializer; -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonGeneratorDecorator; -import jakarta.json.stream.JsonbPropertySerializer; - -public class AbstractBeanJsonSerializer extends JsonSerializer implements JsonbSerializer { - - protected List> properties = new ArrayList<>(); - - @Override - public void serialize(T obj, JsonGenerator generator, SerializationContext ctx) { - properties.forEach(p -> p.accept(obj, (JsonGeneratorDecorator) generator, ctx)); - } - - public void serialize( - T obj, String objectName, JsonGenerator generator, SerializationContext ctx) { - if (obj != null) { - JsonGenerator objBuilder = generator.writeStartObject(objectName); - properties.forEach(p -> p.accept(obj, (JsonGeneratorDecorator) objBuilder, ctx)); - objBuilder.writeEnd(); - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/BaseNumberJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/BaseNumberJsonSerializer.java deleted file mode 100644 index e24360a9721..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/BaseNumberJsonSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer; - -import java.math.BigDecimal; -import java.math.BigInteger; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; - -public abstract class BaseNumberJsonSerializer extends JsonSerializer { - - public static final class BigDecimalJsonSerializer extends BaseNumberJsonSerializer { - - @Override - public void serialize( - BigDecimal obj, String property, JsonGenerator generator, SerializationContext ctx) { - generator.write(property, obj); - } - - @Override - public void serialize(BigDecimal obj, JsonGenerator generator, SerializationContext ctx) { - generator.write(obj); - } - } - - public static final class BigIntegerJsonSerializer extends BaseNumberJsonSerializer { - - @Override - public void serialize( - BigInteger obj, String property, JsonGenerator generator, SerializationContext ctx) { - generator.write(property, obj); - } - - @Override - public void serialize(BigInteger obj, JsonGenerator generator, SerializationContext ctx) { - generator.write(obj); - } - } - - public static final class ByteJsonSerializer extends BaseNumberJsonSerializer { - - @Override - public void serialize( - Byte obj, String property, JsonGenerator generator, SerializationContext ctx) { - generator.write(property, obj); - } - - @Override - public void serialize(Byte obj, JsonGenerator generator, SerializationContext ctx) { - generator.write(obj); - } - } - - public static final class DoubleJsonSerializer extends BaseNumberJsonSerializer { - - @Override - public void serialize( - Double obj, String property, JsonGenerator generator, SerializationContext ctx) { - generator.write(property, obj); - } - - @Override - public void serialize(Double obj, JsonGenerator generator, SerializationContext ctx) { - generator.write(obj); - } - } - - public static final class FloatJsonSerializer extends BaseNumberJsonSerializer { - - @Override - public void serialize( - Float obj, String property, JsonGenerator generator, SerializationContext ctx) { - generator.write(property, obj); - } - - @Override - public void serialize(Float obj, JsonGenerator generator, SerializationContext ctx) { - generator.write(obj); - } - } - - public static final class IntegerJsonSerializer extends BaseNumberJsonSerializer { - - @Override - public void serialize( - Integer obj, String property, JsonGenerator generator, SerializationContext ctx) { - generator.write(property, obj); - } - - @Override - public void serialize(Integer obj, JsonGenerator generator, SerializationContext ctx) { - generator.write(obj); - } - } - - public static final class LongJsonSerializer extends BaseNumberJsonSerializer { - - @Override - public void serialize( - Long obj, String property, JsonGenerator generator, SerializationContext ctx) { - generator.write(property, obj); - } - - @Override - public void serialize(Long obj, JsonGenerator generator, SerializationContext ctx) { - generator.write(obj); - } - } - - public static final class ShortJsonSerializer extends BaseNumberJsonSerializer { - - @Override - public void serialize( - Short obj, String property, JsonGenerator generator, SerializationContext ctx) { - generator.write(property, obj); - } - - @Override - public void serialize(Short obj, JsonGenerator generator, SerializationContext ctx) { - generator.write(obj); - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/BooleanJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/BooleanJsonSerializer.java deleted file mode 100644 index 7cb9159fc0c..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/BooleanJsonSerializer.java +++ /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. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.internal.serializer; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; - -public class BooleanJsonSerializer extends JsonSerializer { - - @Override - public void serialize( - Boolean obj, String property, JsonGenerator generator, SerializationContext ctx) { - generator.write(property, obj); - } - - public void serialize(Boolean obj, JsonGenerator generator, SerializationContext ctx) { - generator.write(obj); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/CharacterJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/CharacterJsonSerializer.java deleted file mode 100644 index 12cb7cb592f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/CharacterJsonSerializer.java +++ /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. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.internal.serializer; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; - -public class CharacterJsonSerializer extends JsonSerializer { - - @Override - public void serialize( - Character obj, String property, JsonGenerator generator, SerializationContext ctx) { - generator.write(property, obj); - } - - public void serialize(Character obj, JsonGenerator generator, SerializationContext ctx) { - generator.write(obj); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/EnumJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/EnumJsonSerializer.java deleted file mode 100644 index b06cd33ec98..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/EnumJsonSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer; - -import java.util.function.Function; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; - -public class EnumJsonSerializer> extends JsonSerializer { - - private final Function typeStringFunction; - - public EnumJsonSerializer(Function typeStringFunction) { - this.typeStringFunction = typeStringFunction; - } - - @Override - public void serialize(E obj, String property, JsonGenerator generator, SerializationContext ctx) { - generator.write(property, typeStringFunction.apply(obj)); - } - - public void serialize(E obj, JsonGenerator generator, SerializationContext ctx) { - generator.write(typeStringFunction.apply(obj)); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/JsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/JsonSerializer.java deleted file mode 100644 index 61270e2e71e..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/JsonSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; - -public abstract class JsonSerializer implements jakarta.json.bind.serializer.JsonbSerializer { - - public abstract void serialize( - T obj, String property, JsonGenerator generator, SerializationContext ctx); - - public abstract void serialize(T obj, JsonGenerator generator, SerializationContext ctx); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/JsonSerializerAdapter.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/JsonSerializerAdapter.java deleted file mode 100644 index a6c9cbcf62e..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/JsonSerializerAdapter.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer; - -import jakarta.json.bind.serializer.JsonbSerializer; -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; - -public class JsonSerializerAdapter extends JsonSerializer { - - private final JsonbSerializer serializer; - - public JsonSerializerAdapter(JsonbSerializer serializer) { - this.serializer = serializer; - } - - @Override - public void serialize(T obj, String property, JsonGenerator generator, SerializationContext ctx) { - throw new UnsupportedOperationException(); - } - - @Override - public void serialize(T obj, JsonGenerator generator, SerializationContext ctx) { - serializer.serialize(obj, generator, ctx); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/JsonbSubtypeSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/JsonbSubtypeSerializer.java deleted file mode 100644 index a9ab0a0128a..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/JsonbSubtypeSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer; - -import java.util.HashMap; -import java.util.Map; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonbPropertySerializer; - -public class JsonbSubtypeSerializer extends JsonSerializer { - private Map types = new HashMap<>(); - - private final String typeFieldName; - - public JsonbSubtypeSerializer(String typeFieldName, Info... infos) { - this.typeFieldName = typeFieldName; - for (Info info : infos) { - types.put(info.clazz, info); - } - } - - @Override - public void serialize(T obj, String property, JsonGenerator generator, SerializationContext ctx) { - if (obj == null) { - return; - } - if (types.containsKey(obj.getClass())) { - AbstractBeanJsonSerializer serializer = - (AbstractBeanJsonSerializer) types.get(obj.getClass()).ser; - serializer.properties.add( - (JsonbPropertySerializer) - (s, u, context) -> u.write(typeFieldName, types.get(obj.getClass()).alias)); - serializer.serialize(obj, property, generator, ctx); - } else { - throw new Error("Unable to find ser for " + obj.getClass()); - } - } - - // TODO remove code dups - @Override - public void serialize(T obj, JsonGenerator generator, SerializationContext ctx) { - if (obj == null) { - return; - } - if (types.containsKey(obj.getClass())) { - AbstractBeanJsonSerializer serializer = - (AbstractBeanJsonSerializer) types.get(obj.getClass()).ser; - serializer.properties.add( - (JsonbPropertySerializer) - (s, u, context) -> u.write(typeFieldName, types.get(obj.getClass()).alias)); - serializer.serialize(obj, generator, ctx); - } else { - throw new Error("Unable to find ser for " + obj.getClass()); - } - } - - public static class Info { - - private final String alias; - private final Class clazz; - private final JsonSerializer ser; - - public Info(String alias, Class clazz, JsonSerializer ser) { - this.alias = alias; - this.clazz = clazz; - this.ser = ser; - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/SerializerJsonbTypeSerializerWrapper.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/SerializerJsonbTypeSerializerWrapper.java deleted file mode 100644 index e9fd3b93e35..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/SerializerJsonbTypeSerializerWrapper.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer; - -import jakarta.json.bind.serializer.JsonbSerializer; -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; - -public class SerializerJsonbTypeSerializerWrapper implements JsonbSerializer { - - private final JsonbSerializer serializer; - private final String property; - - public SerializerJsonbTypeSerializerWrapper(JsonbSerializer serializer, String property) { - this.serializer = serializer; - this.property = property; - } - - @Override - public void serialize(T obj, JsonGenerator generator, SerializationContext ctx) { - if (obj instanceof Object[]) { - JsonGenerator builder = generator.writeStartArray(property); - serializer.serialize(obj, builder, ctx); - builder.writeEnd(); - } else { - JsonGenerator gen = generator.writeKey(property); - serializer.serialize(obj, gen, ctx); - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/StringJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/StringJsonSerializer.java deleted file mode 100644 index a422f450532..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/StringJsonSerializer.java +++ /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. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.internal.serializer; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; - -public class StringJsonSerializer extends JsonSerializer { - - @Override - public void serialize( - String obj, String property, JsonGenerator generator, SerializationContext ctx) { - generator.write(property, obj); - } - - public void serialize(String obj, JsonGenerator generator, SerializationContext ctx) { - generator.write(obj); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/ArrayBeanJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/ArrayBeanJsonSerializer.java deleted file mode 100644 index 2e0391028a8..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/ArrayBeanJsonSerializer.java +++ /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. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array; - -import jakarta.json.bind.serializer.JsonSerializationContext; -import jakarta.json.bind.serializer.JsonbSerializer; -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonGeneratorDecorator; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.JsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.JsonSerializerAdapter; - -public class ArrayBeanJsonSerializer extends ArrayJsonSerializer { - - public ArrayBeanJsonSerializer(JsonSerializer serializer) { - super(serializer); - } - - public ArrayBeanJsonSerializer(JsonbSerializer serializer) { - this(new JsonSerializerAdapter<>(serializer)); - } - - @Override - public void serialize( - T[] obj, String property, JsonGenerator generator, SerializationContext ctx) { - if (obj != null) { - JsonGenerator builder = generator.writeStartArray(property); - JsonSerializationContext jsonSerializationContext = (JsonSerializationContext) ctx; - for (int i = 0; i < obj.length; i++) { - JsonGeneratorDecorator arrayElmBuilder = jsonSerializationContext.createGenerator(); - serializer.serialize(obj[i], arrayElmBuilder, ctx); - builder.write(arrayElmBuilder.builder().build()); - } - builder.writeEnd(); - } - } - - @Override - public void serialize(T[] obj, JsonGenerator generator, SerializationContext ctx) { - if (obj != null) { - JsonSerializationContext jsonSerializationContext = (JsonSerializationContext) ctx; - for (int i = 0; i < obj.length; i++) { - JsonGeneratorDecorator arrayElmBuilder = jsonSerializationContext.createGenerator(); - serializer.serialize(obj[i], arrayElmBuilder, ctx); - generator.write(arrayElmBuilder.builder().build()); - } - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/ArrayJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/ArrayJsonSerializer.java deleted file mode 100644 index feb71e9ab48..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/ArrayJsonSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.JsonSerializer; - -public class ArrayJsonSerializer extends BasicArrayJsonSerializer { - - protected final JsonSerializer serializer; - - public ArrayJsonSerializer(JsonSerializer serializer) { - this.serializer = serializer; - } - - @Override - public void serialize( - T[] obj, String property, JsonGenerator generator, SerializationContext ctx) { - if (obj != null) { - JsonGenerator builder = generator.writeStartArray(property); - for (int i = 0; i < obj.length; i++) { - serializer.serialize(obj[i], builder, ctx); - } - builder.writeEnd(); - } - } - - @Override - public void serialize(T[] obj, JsonGenerator generator, SerializationContext ctx) { - for (int i = 0; i < obj.length; i++) { - serializer.serialize(obj[i], generator, ctx); - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/BasicArrayJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/BasicArrayJsonSerializer.java deleted file mode 100644 index 026eb275fa4..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/BasicArrayJsonSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array; - -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.JsonSerializer; - -public abstract class BasicArrayJsonSerializer extends JsonSerializer {} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveBooleanArrayJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveBooleanArrayJsonSerializer.java deleted file mode 100644 index 8ab013826ab..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveBooleanArrayJsonSerializer.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BooleanJsonSerializer; - -public class PrimitiveBooleanArrayJsonSerializer extends BasicArrayJsonSerializer { - - private final BooleanJsonSerializer serializer = new BooleanJsonSerializer(); - - @Override - public void serialize( - boolean[] obj, String property, JsonGenerator generator, SerializationContext ctx) { - if (obj != null) { - JsonGenerator builder = generator.writeStartArray(property); - for (int i = 0; i < obj.length; i++) { - serializer.serialize(obj[i], builder, ctx); - } - builder.writeEnd(); - } - } - - @Override - public void serialize(boolean[] obj, JsonGenerator generator, SerializationContext ctx) { - throw new UnsupportedOperationException(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveByteArrayJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveByteArrayJsonSerializer.java deleted file mode 100644 index af68f7241bb..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveByteArrayJsonSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer; - -public class PrimitiveByteArrayJsonSerializer extends BasicArrayJsonSerializer { - - private final BaseNumberJsonSerializer.ByteJsonSerializer serializer = - new BaseNumberJsonSerializer.ByteJsonSerializer(); - - @Override - public void serialize( - byte[] obj, String property, JsonGenerator generator, SerializationContext ctx) { - if (obj != null) { - JsonGenerator builder = generator.writeStartArray(property); - for (int i = 0; i < obj.length; i++) { - serializer.serialize(obj[i], builder, ctx); - } - builder.writeEnd(); - } - } - - @Override - public void serialize(byte[] obj, JsonGenerator generator, SerializationContext ctx) { - throw new UnsupportedOperationException(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveCharacterArrayJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveCharacterArrayJsonSerializer.java deleted file mode 100644 index b89cd8a8a0c..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveCharacterArrayJsonSerializer.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.CharacterJsonSerializer; - -public class PrimitiveCharacterArrayJsonSerializer extends BasicArrayJsonSerializer { - - private final CharacterJsonSerializer serializer = new CharacterJsonSerializer(); - - @Override - public void serialize( - char[] obj, String property, JsonGenerator generator, SerializationContext ctx) { - if (obj != null) { - JsonGenerator builder = generator.writeStartArray(property); - for (int i = 0; i < obj.length; i++) { - serializer.serialize(obj[i], builder, ctx); - } - builder.writeEnd(); - } - } - - @Override - public void serialize(char[] obj, JsonGenerator generator, SerializationContext ctx) { - throw new UnsupportedOperationException(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveDoubleArrayJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveDoubleArrayJsonSerializer.java deleted file mode 100644 index 0f5c4674a67..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveDoubleArrayJsonSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; - -import static org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer.DoubleJsonSerializer; - -public class PrimitiveDoubleArrayJsonSerializer extends BasicArrayJsonSerializer { - - private final DoubleJsonSerializer serializer = new DoubleJsonSerializer(); - - @Override - public void serialize( - double[] obj, String property, JsonGenerator generator, SerializationContext ctx) { - if (obj != null) { - JsonGenerator builder = generator.writeStartArray(property); - for (int i = 0; i < obj.length; i++) { - serializer.serialize(obj[i], builder, ctx); - } - builder.writeEnd(); - } - } - - @Override - public void serialize(double[] obj, JsonGenerator generator, SerializationContext ctx) { - throw new UnsupportedOperationException(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveFloatArrayJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveFloatArrayJsonSerializer.java deleted file mode 100644 index 4156d8cad98..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveFloatArrayJsonSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; - -import static org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer.FloatJsonSerializer; - -public class PrimitiveFloatArrayJsonSerializer extends BasicArrayJsonSerializer { - - private final FloatJsonSerializer serializer = - new FloatJsonSerializer(); - - @Override - public void serialize( - float[] obj, String property, JsonGenerator generator, SerializationContext ctx) { - if (obj != null) { - JsonGenerator builder = generator.writeStartArray(property); - for (int i = 0; i < obj.length; i++) { - serializer.serialize(obj[i], builder, ctx); - } - builder.writeEnd(); - } - } - - @Override - public void serialize(float[] obj, JsonGenerator generator, SerializationContext ctx) { - throw new UnsupportedOperationException(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveIntegerArrayJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveIntegerArrayJsonSerializer.java deleted file mode 100644 index e7169d0454b..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveIntegerArrayJsonSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; - -import static org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer.IntegerJsonSerializer; - -public class PrimitiveIntegerArrayJsonSerializer extends BasicArrayJsonSerializer { - - private final IntegerJsonSerializer serializer = - new IntegerJsonSerializer(); - - @Override - public void serialize( - int[] obj, String property, JsonGenerator generator, SerializationContext ctx) { - if (obj != null) { - JsonGenerator builder = generator.writeStartArray(property); - for (int i = 0; i < obj.length; i++) { - serializer.serialize(obj[i], builder, ctx); - } - builder.writeEnd(); - } - } - - @Override - public void serialize(int[] obj, JsonGenerator generator, SerializationContext ctx) { - throw new UnsupportedOperationException(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveLongArrayLongSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveLongArrayLongSerializer.java deleted file mode 100644 index 739fc12aa9f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveLongArrayLongSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; - -import static org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer.LongJsonSerializer; - -public class PrimitiveLongArrayLongSerializer extends BasicArrayJsonSerializer { - - private final LongJsonSerializer serializer = - new LongJsonSerializer(); - - @Override - public void serialize( - long[] obj, String property, JsonGenerator generator, SerializationContext ctx) { - if (obj != null) { - JsonGenerator builder = generator.writeStartArray(property); - for (int i = 0; i < obj.length; i++) { - serializer.serialize(obj[i], builder, ctx); - } - builder.writeEnd(); - } - } - - @Override - public void serialize(long[] obj, JsonGenerator generator, SerializationContext ctx) { - throw new UnsupportedOperationException(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveShortArrayJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveShortArrayJsonSerializer.java deleted file mode 100644 index 8e4fda6d3fb..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/array/PrimitiveShortArrayJsonSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; - -import static org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer.ShortJsonSerializer; - -public class PrimitiveShortArrayJsonSerializer extends BasicArrayJsonSerializer { - - private final ShortJsonSerializer serializer = - new ShortJsonSerializer(); - - @Override - public void serialize( - short[] obj, String property, JsonGenerator generator, SerializationContext ctx) { - if (obj != null) { - JsonGenerator builder = generator.writeStartArray(property); - for (int i = 0; i < obj.length; i++) { - serializer.serialize(obj[i], builder, ctx); - } - builder.writeEnd(); - } - } - - @Override - public void serialize(short[] obj, JsonGenerator generator, SerializationContext ctx) { - throw new UnsupportedOperationException(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/collection/BoxedTypeCollectionJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/collection/BoxedTypeCollectionJsonSerializer.java deleted file mode 100644 index 47dc66401b9..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/collection/BoxedTypeCollectionJsonSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.collection; - -import java.util.Collection; - -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.JsonSerializer; - -public class BoxedTypeCollectionJsonSerializer extends JsonSerializer> { - - protected final JsonSerializer serializer; - - public BoxedTypeCollectionJsonSerializer(JsonSerializer serializer) { - this.serializer = serializer; - } - - @Override - public void serialize( - Collection collection, - String property, - JsonGenerator generator, - SerializationContext ctx) { - if (collection != null && !collection.isEmpty()) { - JsonGenerator builder = generator.writeStartArray(property); - for (T obj : collection) { - serializer.serialize(obj, builder, ctx); - } - builder.writeEnd(); - } - } - - @Override - public void serialize(Collection obj, JsonGenerator generator, SerializationContext ctx) { - throw new UnsupportedOperationException(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/collection/CollectionJsonSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/collection/CollectionJsonSerializer.java deleted file mode 100644 index 669ff95933f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/internal/serializer/collection/CollectionJsonSerializer.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.collection; - -import java.util.Collection; - -import jakarta.json.bind.serializer.JsonSerializationContext; -import jakarta.json.bind.serializer.JsonbSerializer; -import jakarta.json.bind.serializer.SerializationContext; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonGeneratorDecorator; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.JsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.JsonSerializerAdapter; - -public class CollectionJsonSerializer extends JsonSerializer> { - - protected final JsonSerializer serializer; - - public CollectionJsonSerializer(JsonSerializer serializer) { - this.serializer = serializer; - } - - public CollectionJsonSerializer(JsonbSerializer serializer) { - this(new JsonSerializerAdapter<>(serializer)); - } - - @Override - public void serialize( - Collection collection, - String property, - JsonGenerator generator, - SerializationContext ctx) { - if (collection != null && !collection.isEmpty()) { - JsonGenerator builder = generator.writeStartArray(property); - JsonSerializationContext jsonSerializationContext = (JsonSerializationContext) ctx; - - for (T t : collection) { - JsonGeneratorDecorator arrayElmBuilder = jsonSerializationContext.createGenerator(); - serializer.serialize(t, arrayElmBuilder, ctx); - builder.write(arrayElmBuilder.builder().build()); - } - builder.writeEnd(); - } - } - - @Override - public void serialize(Collection obj, JsonGenerator generator, SerializationContext ctx) { - throw new UnsupportedOperationException(); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/resources/jakarta/Common.gwt.xml b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/resources/jakarta/Common.gwt.xml deleted file mode 100644 index 917eb652c98..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/resources/jakarta/Common.gwt.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/resources/org/kie/workbench/common/stunner/client/json/Internal.gwt.xml b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/resources/org/kie/workbench/common/stunner/client/json/Internal.gwt.xml deleted file mode 100644 index 71446254305..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/common/src/main/resources/org/kie/workbench/common/stunner/client/json/Internal.gwt.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/pom.xml b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/pom.xml deleted file mode 100644 index 431d14dfaae..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/pom.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - 4.0.0 - - marshalling-parent - org.kie.kogito.stunner.serverless.editor.third_party.tooling.marshalling - ${revision} - - pom - - common - processor - - - org.kie.kogito.stunner.serverless.editor.third_party.tooling.marshalling.json - parent - - GWT/J2CL Jakarta JSON Binding parent - GWT/J2CL Jakarta JSON Binding parent - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/pom.xml b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/pom.xml deleted file mode 100644 index 953c9a5857e..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/pom.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - org.kie.kogito.stunner.serverless.editor.third_party.tooling.marshalling.json - parent - ${revision} - - 4.0.0 - - processor - GWT/J2CL Jakarta JSON Binding processor - GWT/J2CL Jakarta JSON Binding processor - jar - - - - org.kie.kogito.stunner.serverless.editor.third_party.tooling.marshalling.json - common - - - com.google.auto - auto-common - - - com.google.auto.service - auto-service - - - com.github.javaparser - javaparser-core - - - - - - - src/main/resources - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - package - - jar - - - - - - org.apache.maven.plugins - maven-shade-plugin - - - package - - shade - - - true - - - *:*:*:* - - **/*.java - - - - - - - - - - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/GenerationProcessor.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/GenerationProcessor.java deleted file mode 100644 index e1dc10d6802..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/GenerationProcessor.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.apt; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.Processor; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedSourceVersion; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.MirroredTypeException; - -import com.google.auto.common.MoreElements; -import com.google.auto.common.MoreTypes; -import com.google.auto.service.AutoService; -import com.google.common.collect.Streams; -import jakarta.json.bind.annotation.JsonbSubtype; -import jakarta.json.bind.annotation.JsonbTypeInfo; -import org.kie.workbench.common.stunner.client.json.mapper.annotation.JSONMapper; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.apt.logger.PrintWriterTreeLogger; -import org.kie.workbench.common.stunner.client.json.mapper.apt.logger.TreeLogger; -import org.kie.workbench.common.stunner.client.json.mapper.apt.processor.BeanProcessor; - -@AutoService(Processor.class) -@SupportedSourceVersion(SourceVersion.RELEASE_8) -public class GenerationProcessor extends AbstractProcessor { - - private final Set beans = new HashSet<>(); - - private final TreeLogger logger = new PrintWriterTreeLogger(); - - @Override - public boolean process( - Set annotations, RoundEnvironment roundEnvironment) { - if (!annotations.isEmpty()) { - GenerationContext context = new GenerationContext(roundEnvironment, processingEnv); - - Stream stream = - Streams.concat( - roundEnvironment.getElementsAnnotatedWith(JSONMapper.class).stream(), - roundEnvironment.getElementsAnnotatedWith(JsonbTypeInfo.class).stream() - .map(type -> type.getAnnotation(JsonbTypeInfo.class)) - .map(JsonbTypeInfo::value) - .flatMap(Arrays::stream) - .map(this::get)); - processJsonMapper(stream); - new BeanProcessor(context, logger, beans).process(); - } - beans.clear(); - return false; - } - - private void processJsonMapper(Stream stream) { - stream.map(MoreElements::asType).forEach(beans::add); - } - - @Override - public Set getSupportedAnnotationTypes() { - return supportedAnnotations().stream().map(Class::getCanonicalName).collect(Collectors.toSet()); - } - - private List> supportedAnnotations() { - return Arrays.asList(JSONMapper.class); - } - - private TypeElement get(JsonbSubtype jsonbSubtype) { - try { - jsonbSubtype.type(); - } catch (MirroredTypeException e) { - return MoreTypes.asTypeElement(e.getTypeMirror()); - } - return null; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/context/GenerationContext.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/context/GenerationContext.java deleted file mode 100644 index 3a3a487be86..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/context/GenerationContext.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.apt.context; - -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.RoundEnvironment; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeMirror; - -import com.google.auto.common.MoreTypes; -import org.kie.workbench.common.stunner.client.json.mapper.apt.definition.BeanDefinition; -import org.kie.workbench.common.stunner.client.json.mapper.apt.definition.FieldDefinitionFactory; -import org.kie.workbench.common.stunner.client.json.mapper.apt.utils.TypeRegistry; -import org.kie.workbench.common.stunner.client.json.mapper.apt.utils.TypeUtils; - -public class GenerationContext { - - private final RoundEnvironment roundEnvironment; - private final ProcessingEnvironment processingEnv; - private final TypeRegistry typeRegistry; - private final TypeUtils typeUtils; - private final Map beans = new ConcurrentHashMap<>(); - - private final FieldDefinitionFactory fieldDefinitionFactory; - - public GenerationContext(RoundEnvironment roundEnvironment, ProcessingEnvironment processingEnv) { - this.processingEnv = processingEnv; - this.roundEnvironment = roundEnvironment; - this.typeRegistry = new TypeRegistry(this); - this.typeUtils = new TypeUtils(this); - this.fieldDefinitionFactory = new FieldDefinitionFactory(this); - } - - public RoundEnvironment getRoundEnvironment() { - return roundEnvironment; - } - - public ProcessingEnvironment getProcessingEnv() { - return processingEnv; - } - - public TypeRegistry getTypeRegistry() { - return typeRegistry; - } - - public TypeUtils getTypeUtils() { - return typeUtils; - } - - public BeanDefinition getBeanDefinition(TypeMirror type) { - if (beans.containsKey(type)) { - return beans.get(type); - } else { - BeanDefinition beanDefinition = new BeanDefinition(MoreTypes.asTypeElement(type), this); - beans.put(type, beanDefinition); - return beanDefinition; - } - } - - public void addBeanDefinition(TypeElement type) { - if (!beans.containsKey(type.asType())) { - BeanDefinition beanDefinition = new BeanDefinition(type, this); - beans.put(type.asType(), beanDefinition); - } - } - - public Collection getBeans() { - return beans.values(); - } - - public FieldDefinitionFactory getFieldDefinitionFactory() { - return fieldDefinitionFactory; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/ArrayBeanFieldDefinition.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/ArrayBeanFieldDefinition.java deleted file mode 100644 index 0c5f5c4cd8d..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/ArrayBeanFieldDefinition.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.apt.definition; - -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.TypeMirror; - -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.expr.CastExpr; -import com.github.javaparser.ast.expr.Expression; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.ObjectCreationExpr; -import com.github.javaparser.ast.expr.StringLiteralExpr; -import com.github.javaparser.ast.stmt.ExpressionStmt; -import com.github.javaparser.ast.stmt.Statement; -import com.github.javaparser.ast.type.ClassOrInterfaceType; -import com.google.auto.common.MoreTypes; -import jakarta.json.bind.annotation.JsonbTypeInfo; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array.ArrayJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array.ArrayBeanJsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array.ArrayJsonSerializer; - -public class ArrayBeanFieldDefinition extends FieldDefinition { - - public ArrayBeanFieldDefinition(TypeMirror property, GenerationContext context) { - super(property, context); - } - - @Override - public Statement getFieldDeserializer(PropertyDefinition field, CompilationUnit cu) { - cu.addImport(ArrayJsonDeserializer.ArrayCreator.class); - cu.addImport(ArrayJsonDeserializer.class); - - ArrayType arrayType = (ArrayType) property; - - if (arrayType.getComponentType().getKind().isPrimitive()) { - return generatePrimitiveArrayDeserCall(field, arrayType); - } - - Expression deser; - if (context.getTypeRegistry().has(arrayType.getComponentType())) { - deser = - new ObjectCreationExpr() - .setType( - context - .getTypeRegistry() - .getDeserializer(arrayType.getComponentType().toString()) - .getQualifiedName() - .toString()); - } else if (context.getTypeUtils().isJsonbTypeSerializer(field.getVariableElement())) { - deser = - new JsonbTypeSerFieldDefinition(arrayType.getComponentType(), context) - .getFieldDeserializerCreationExpr(field, cu); - } else if (MoreTypes.asTypeElement(arrayType.getComponentType()) - .getAnnotation(JsonbTypeInfo.class) - != null) { - deser = - new JsonbTypeInfoDefinition( - MoreTypes.asTypeElement(arrayType.getComponentType()) - .getAnnotation(JsonbTypeInfo.class), - arrayType.getComponentType(), - context) - .getDeserializerCreationExpr(arrayType.getComponentType(), cu); - } else if (MoreTypes.asTypeElement(arrayType.getComponentType()) - .getKind() - .equals(ElementKind.ENUM)) { - deser = - new EnumBeanFieldDefinition(arrayType.getComponentType(), context) - .getDeserializerCreationExpr(cu); - } else { - deser = - new ObjectCreationExpr() - .setType( - context - .getTypeUtils() - .getJsonDeserializerImplQualifiedName( - MoreTypes.asTypeElement(arrayType.getComponentType()), cu)); - } - - ObjectCreationExpr arrayJsonDeserializer = new ObjectCreationExpr(); - ClassOrInterfaceType type = new ClassOrInterfaceType(); - type.setName(ArrayJsonDeserializer.class.getSimpleName()); - type.setTypeArguments( - new ClassOrInterfaceType().setName(arrayType.getComponentType().toString())); - arrayJsonDeserializer.setType(type); - - return new ExpressionStmt( - new MethodCallExpr(new NameExpr("bean"), field.getSetter().getSimpleName().toString()) - .addArgument( - new MethodCallExpr( - arrayJsonDeserializer - .addArgument(deser) - .addArgument(createArrayCreatorCall(arrayType.getComponentType())), - "deserialize") - .addArgument( - new MethodCallExpr(new NameExpr("jsonObject"), "getJsonArray") - .addArgument(new StringLiteralExpr(field.getName()))) - .addArgument(new NameExpr("ctx")))); - } - - private Expression createArrayCreatorCall(TypeMirror array) { - ClassOrInterfaceType typeOf = - new ClassOrInterfaceType() - .setName(ArrayJsonDeserializer.ArrayCreator.class.getSimpleName()) - .setTypeArguments(new ClassOrInterfaceType().setName(array.toString())); - - return new CastExpr() - .setType(typeOf) - .setExpression( - new NameExpr(context.getProcessingEnv().getTypeUtils().erasure(array) + "[]::new")); - } - - private ExpressionStmt generatePrimitiveArrayDeserCall( - PropertyDefinition field, ArrayType array) { - TypeElement deser = context.getTypeRegistry().getDeserializer(array.toString()); - - return new ExpressionStmt( - new MethodCallExpr(new NameExpr("bean"), field.getSetter().getSimpleName().toString()) - .addArgument( - new MethodCallExpr( - new ObjectCreationExpr().setType(deser.getQualifiedName().toString()), - "deserialize") - .addArgument( - new MethodCallExpr(new NameExpr("jsonObject"), "getJsonArray") - .addArgument(new StringLiteralExpr(field.getName()))) - .addArgument(new NameExpr("ctx")))); - } - - @Override - public Statement getFieldSerializer(PropertyDefinition field, CompilationUnit cu) { - cu.addImport(ArrayJsonSerializer.class); - cu.addImport(ArrayBeanJsonSerializer.class); - - ArrayType arrayType = (ArrayType) property; - - if (arrayType.getComponentType().getKind().isPrimitive()) { - return generatePrimitiveArraySerCall(field, arrayType); - } - - ObjectCreationExpr arrayJsonSerializer = new ObjectCreationExpr(); - ClassOrInterfaceType type = new ClassOrInterfaceType(); - - Expression ser; - if (context.getTypeRegistry().has(arrayType.getComponentType())) { - type.setName(ArrayJsonSerializer.class.getSimpleName()); - ser = - new ObjectCreationExpr() - .setType( - context - .getTypeRegistry() - .getSerializer(arrayType.getComponentType().toString()) - .getQualifiedName() - .toString()); - } else if (context.getTypeUtils().isJsonbTypeSerializer(field.getVariableElement())) { - type.setName(ArrayBeanJsonSerializer.class.getSimpleName()); - ser = - new JsonbTypeSerFieldDefinition(arrayType.getComponentType(), context) - .getFieldSerializerCreationExpr(field, cu); - } else if (MoreTypes.asTypeElement(arrayType.getComponentType()) - .getAnnotation(JsonbTypeInfo.class) - != null) { - type.setName(ArrayBeanJsonSerializer.class.getSimpleName()); - ser = - new JsonbTypeInfoDefinition( - MoreTypes.asTypeElement(arrayType.getComponentType()) - .getAnnotation(JsonbTypeInfo.class), - arrayType.getComponentType(), - context) - .getSerializerCreationExpr(cu); - } else if (MoreTypes.asTypeElement(arrayType.getComponentType()) - .getKind() - .equals(ElementKind.ENUM)) { - cu.addImport(ArrayJsonSerializer.class); - type.setName(ArrayJsonSerializer.class.getSimpleName()); - ser = - new EnumBeanFieldDefinition(arrayType.getComponentType(), context) - .getSerializerCreationExpr(cu); - } else { - type.setName(ArrayBeanJsonSerializer.class.getSimpleName()); - ser = - new ObjectCreationExpr() - .setType( - context - .getTypeUtils() - .getJsonSerializerImplQualifiedName( - MoreTypes.asTypeElement(arrayType.getComponentType()))); - } - - type.setTypeArguments( - new ClassOrInterfaceType().setName(arrayType.getComponentType().toString())); - arrayJsonSerializer.setType(type); - - return new ExpressionStmt( - new MethodCallExpr(arrayJsonSerializer.addArgument(ser), "serialize") - .addArgument( - new MethodCallExpr( - new NameExpr("bean"), field.getGetter().getSimpleName().toString())) - .addArgument(new StringLiteralExpr(field.getName())) - .addArgument(new NameExpr("generator")) - .addArgument(new NameExpr("ctx"))); - } - - private Statement generatePrimitiveArraySerCall(PropertyDefinition field, ArrayType array) { - TypeElement ser = context.getTypeRegistry().getSerializer(array.toString()); - - return new ExpressionStmt( - new MethodCallExpr( - new ObjectCreationExpr().setType(ser.getQualifiedName().toString()), "serialize") - .addArgument( - new MethodCallExpr( - new NameExpr("bean"), field.getGetter().getSimpleName().toString())) - .addArgument(new StringLiteralExpr(field.getName())) - .addArgument(new NameExpr("generator")) - .addArgument(new NameExpr("ctx"))); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/BasicTypeFieldDefinition.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/BasicTypeFieldDefinition.java deleted file mode 100644 index 66b47da5d44..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/BasicTypeFieldDefinition.java +++ /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. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.apt.definition; - -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeMirror; - -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.expr.Expression; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.ObjectCreationExpr; -import com.github.javaparser.ast.expr.StringLiteralExpr; -import com.github.javaparser.ast.stmt.ExpressionStmt; -import com.github.javaparser.ast.stmt.Statement; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; - -public class BasicTypeFieldDefinition extends FieldDefinition { - - protected BasicTypeFieldDefinition(TypeMirror property, GenerationContext context) { - super(property, context); - } - - @Override - public Statement getFieldDeserializer(PropertyDefinition field, CompilationUnit cu) { - String setter = field.getSetter().getSimpleName().toString(); - Expression jsonGetter = getPropertyAccessor(field); - - MethodCallExpr method = new MethodCallExpr(new NameExpr("bean"), setter); - method.addArgument(jsonGetter); - return new ExpressionStmt(method); - } - - @Override - public Statement getFieldSerializer(PropertyDefinition field, CompilationUnit cu) { - return new ExpressionStmt( - new MethodCallExpr(new NameExpr("generator"), "write") - .addArgument(new StringLiteralExpr(field.getName())) - .addArgument( - new MethodCallExpr( - new NameExpr("bean"), field.getGetter().getSimpleName().toString()))); - } - - private Expression getPropertyAccessor(PropertyDefinition field) { - TypeElement deser = context.getTypeRegistry().getDeserializer(field.getType()); - - NameExpr jsonObject = new NameExpr("jsonObject"); - StringLiteralExpr name = new StringLiteralExpr(field.getName()); - - return new MethodCallExpr( - new ObjectCreationExpr().setType(deser.getQualifiedName().toString()), "deserialize") - .addArgument(new MethodCallExpr(jsonObject, "get").addArgument(name)) - .addArgument(new NameExpr("ctx")); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/BeanDefinition.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/BeanDefinition.java deleted file mode 100644 index 1f771532e61..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/BeanDefinition.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.apt.definition; - -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; - -import com.google.auto.common.MoreElements; -import jakarta.json.bind.annotation.JsonbPropertyOrder; -import jakarta.json.bind.annotation.JsonbTransient; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; - -public class BeanDefinition { - - private final TypeElement element; - private final GenerationContext context; - - public BeanDefinition(TypeElement asTypeElement, GenerationContext generationContext) { - this.element = asTypeElement; - this.context = generationContext; - } - - public Stream getPropertyDefinitionsAsStream() { - Stream asStream = - context.getTypeUtils().getAllFieldsIn(element).stream() - .filter(field -> !field.getModifiers().contains(Modifier.STATIC)) - .filter(field -> !field.getModifiers().contains(Modifier.FINAL)) - .filter(field -> !field.getModifiers().contains(Modifier.TRANSIENT)) - .filter(field -> field.getAnnotation(JsonbTransient.class) == null); - - if (element.getAnnotation(JsonbPropertyOrder.class) != null - && element.getAnnotation(JsonbPropertyOrder.class).value() != null) { - LinkedHashSet properties = new LinkedHashSet<>(); - String[] order = element.getAnnotation(JsonbPropertyOrder.class).value(); - Map asMap = - asStream.collect( - Collectors.toMap( - variableElement -> variableElement.getSimpleName().toString(), - variableElement -> new PropertyDefinition(variableElement, context), - (o1, o2) -> o1, - java.util.LinkedHashMap::new)); - - for (String s : order) { - if (asMap.containsKey(s)) { - properties.add(asMap.remove(s)); - } - } - properties.addAll(asMap.values()); - return properties.stream(); - } - return asStream.map(field -> new PropertyDefinition(field, context)); - } - - public String getPackageQualifiedName() { - return MoreElements.getPackage(element).getQualifiedName().toString(); - } - - public TypeElement getElement() { - return element; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/CollectionsFieldDefinition.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/CollectionsFieldDefinition.java deleted file mode 100644 index 4e0ccc258a0..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/CollectionsFieldDefinition.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.apt.definition; - -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeMirror; - -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.expr.Expression; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.ObjectCreationExpr; -import com.github.javaparser.ast.expr.StringLiteralExpr; -import com.github.javaparser.ast.stmt.ExpressionStmt; -import com.github.javaparser.ast.stmt.Statement; -import com.github.javaparser.ast.type.ClassOrInterfaceType; -import com.google.auto.common.MoreTypes; -import jakarta.json.bind.annotation.JsonbTypeInfo; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.collection.BoxedTypeCollectionJsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.collection.CollectionJsonSerializer; - -public class CollectionsFieldDefinition extends FieldDefinition { - - protected CollectionsFieldDefinition(TypeMirror property, GenerationContext context) { - super(property, context); - } - - @Override - public Statement getFieldDeserializer(PropertyDefinition field, CompilationUnit cu) { - TypeElement deserializer = - context - .getTypeRegistry() - .getDeserializer(context.getProcessingEnv().getTypeUtils().erasure(property)); - - cu.addImport(deserializer.getQualifiedName().toString()); - TypeMirror typeMirror = MoreTypes.asDeclared(field.getType()).getTypeArguments().get(0); - - Expression deser; - if (context.getTypeRegistry().has(typeMirror)) { - deser = - new ObjectCreationExpr() - .setType( - context - .getTypeRegistry() - .getDeserializer(typeMirror) - .getQualifiedName() - .toString()); - - } else if (context.getTypeUtils().isJsonbTypeSerializer(field.getVariableElement())) { - deser = - new JsonbTypeSerFieldDefinition(typeMirror, context) - .getFieldDeserializerCreationExpr(field, cu); - } else if (MoreTypes.asTypeElement(typeMirror).getAnnotation(JsonbTypeInfo.class) != null) { - deser = - new JsonbTypeInfoDefinition( - MoreTypes.asTypeElement(typeMirror).getAnnotation(JsonbTypeInfo.class), - typeMirror, - context) - .getDeserializerCreationExpr(typeMirror, cu); - } else if (MoreTypes.asTypeElement(typeMirror).getKind().equals(ElementKind.ENUM)) { - deser = new EnumBeanFieldDefinition(typeMirror, context).getDeserializerCreationExpr(cu); - } else { - deser = - new ObjectCreationExpr() - .setType( - context - .getTypeUtils() - .getJsonDeserializerImplQualifiedName( - MoreTypes.asTypeElement(typeMirror), cu)); - } - - ClassOrInterfaceType type = new ClassOrInterfaceType(); - type.setName(deserializer.getSimpleName().toString()); - type.setTypeArguments(new ClassOrInterfaceType().setName(typeMirror.toString())); - ObjectCreationExpr deserializerCreationExpr = new ObjectCreationExpr(); - deserializerCreationExpr.setType(type); - - return new ExpressionStmt( - new MethodCallExpr(new NameExpr("bean"), field.getSetter().getSimpleName().toString()) - .addArgument( - new MethodCallExpr(deserializerCreationExpr.addArgument(deser), "deserialize") - .addArgument( - new MethodCallExpr(new NameExpr("jsonObject"), "getJsonArray") - .addArgument(new StringLiteralExpr(field.getName()))) - .addArgument(new NameExpr("ctx")))); - } - - @Override - public Statement getFieldSerializer(PropertyDefinition field, CompilationUnit cu) { - ObjectCreationExpr serializerCreationExpr = new ObjectCreationExpr(); - ClassOrInterfaceType type = new ClassOrInterfaceType(); - TypeMirror typeMirror = MoreTypes.asDeclared(field.getType()).getTypeArguments().get(0); - boolean isBoxedTypeOrString = context.getTypeUtils().isBoxedTypeOrString(typeMirror); - - if (isBoxedTypeOrString - || MoreTypes.asTypeElement(typeMirror).getKind().equals(ElementKind.ENUM)) { - cu.addImport(BoxedTypeCollectionJsonSerializer.class); - type.setName(BoxedTypeCollectionJsonSerializer.class.getSimpleName()); - } else { - cu.addImport(CollectionJsonSerializer.class); - type.setName(CollectionJsonSerializer.class.getSimpleName()); - } - - type.setTypeArguments(new ClassOrInterfaceType().setName(typeMirror.toString())); - ObjectCreationExpr deserializerCreationExpr = new ObjectCreationExpr(); - deserializerCreationExpr.setType(type); - type.setTypeArguments(new ClassOrInterfaceType().setName(typeMirror.toString())); - serializerCreationExpr.setType(type); - - Expression ser; - if (context.getTypeRegistry().has(typeMirror)) { - ser = - new ObjectCreationExpr() - .setType( - new ClassOrInterfaceType() - .setName( - context - .getTypeRegistry() - .getSerializer(typeMirror) - .getQualifiedName() - .toString())); - - } else if (context.getTypeUtils().isJsonbTypeSerializer(field.getVariableElement())) { - ser = - new JsonbTypeSerFieldDefinition(typeMirror, context) - .getFieldSerializerCreationExpr(field, cu); - } else if (MoreTypes.asTypeElement(typeMirror).getAnnotation(JsonbTypeInfo.class) != null) { - ser = - new JsonbTypeInfoDefinition( - MoreTypes.asTypeElement(typeMirror).getAnnotation(JsonbTypeInfo.class), - typeMirror, - context) - .getSerializerCreationExpr(cu); - } else if (MoreTypes.asTypeElement(typeMirror).getKind().equals(ElementKind.ENUM)) { - ser = new EnumBeanFieldDefinition(typeMirror, context).getSerializerCreationExpr(cu); - } else { - ser = - new ObjectCreationExpr() - .setType( - new ClassOrInterfaceType() - .setName( - context - .getTypeUtils() - .getJsonSerializerImplQualifiedName( - MoreTypes.asTypeElement(typeMirror)))); - } - return new ExpressionStmt( - new MethodCallExpr(serializerCreationExpr.addArgument(ser), "serialize") - .addArgument( - new MethodCallExpr( - new NameExpr("bean"), field.getGetter().getSimpleName().toString())) - .addArgument(new StringLiteralExpr(field.getName())) - .addArgument(new NameExpr("generator")) - .addArgument(new NameExpr("ctx"))); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/DefaultBeanFieldDefinition.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/DefaultBeanFieldDefinition.java deleted file mode 100644 index 41c223920ae..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/DefaultBeanFieldDefinition.java +++ /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. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.apt.definition; - -import javax.lang.model.type.TypeMirror; - -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.ObjectCreationExpr; -import com.github.javaparser.ast.expr.StringLiteralExpr; -import com.github.javaparser.ast.stmt.ExpressionStmt; -import com.github.javaparser.ast.stmt.Statement; -import com.google.auto.common.MoreTypes; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; - -public class DefaultBeanFieldDefinition extends FieldDefinition { - public DefaultBeanFieldDefinition(TypeMirror property, GenerationContext context) { - super(property, context); - } - - @Override - public Statement getFieldDeserializer(PropertyDefinition field, CompilationUnit cu) { - TypeMirror type = field.getType(); - String deser = - context - .getTypeUtils() - .getJsonDeserializerImplQualifiedName(MoreTypes.asTypeElement(type), cu); - - return new ExpressionStmt( - new MethodCallExpr(new NameExpr("bean"), field.getSetter().getSimpleName().toString()) - .addArgument( - new MethodCallExpr(new ObjectCreationExpr().setType(deser), "deserialize") - .addArgument( - new MethodCallExpr(new NameExpr("jsonObject"), "getJsonObject") - .addArgument(new StringLiteralExpr(field.getName()))) - .addArgument(new NameExpr("ctx")))); - } - - @Override - public Statement getFieldSerializer(PropertyDefinition field, CompilationUnit cu) { - TypeMirror type = field.getType(); - String ser = - context.getTypeUtils().getJsonSerializerImplQualifiedName(MoreTypes.asTypeElement(type)); - - return new ExpressionStmt( - new MethodCallExpr(new ObjectCreationExpr().setType(ser), "serialize") - .addArgument( - new MethodCallExpr( - new NameExpr("bean"), field.getGetter().getSimpleName().toString())) - .addArgument(new StringLiteralExpr(field.getName())) - .addArgument(new NameExpr("generator")) - .addArgument(new NameExpr("ctx"))); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/EnumBeanFieldDefinition.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/EnumBeanFieldDefinition.java deleted file mode 100644 index 23873b5787d..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/EnumBeanFieldDefinition.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.apt.definition; - -import java.util.function.Function; - -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.type.TypeMirror; - -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.Modifier; -import com.github.javaparser.ast.NodeList; -import com.github.javaparser.ast.body.BodyDeclaration; -import com.github.javaparser.ast.body.MethodDeclaration; -import com.github.javaparser.ast.expr.CastExpr; -import com.github.javaparser.ast.expr.Expression; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.NullLiteralExpr; -import com.github.javaparser.ast.expr.ObjectCreationExpr; -import com.github.javaparser.ast.expr.StringLiteralExpr; -import com.github.javaparser.ast.stmt.ExpressionStmt; -import com.github.javaparser.ast.stmt.IfStmt; -import com.github.javaparser.ast.stmt.ReturnStmt; -import com.github.javaparser.ast.stmt.Statement; -import com.github.javaparser.ast.type.ClassOrInterfaceType; -import com.github.javaparser.ast.type.Type; -import com.google.auto.common.MoreTypes; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.EnumJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.EnumJsonSerializer; - -public class EnumBeanFieldDefinition extends FieldDefinition { - - protected EnumBeanFieldDefinition(TypeMirror property, GenerationContext context) { - super(property, context); - } - - @Override - public Statement getFieldDeserializer(PropertyDefinition field, CompilationUnit cu) { - return new ExpressionStmt( - new MethodCallExpr(new NameExpr("bean"), field.getSetter().getSimpleName().toString()) - .addArgument( - new CastExpr() - .setType(new ClassOrInterfaceType().setName(field.getType().toString())) - .setExpression( - new MethodCallExpr(this.getDeserializerCreationExpr(cu), "deserialize") - .addArgument( - new MethodCallExpr(new NameExpr("jsonObject"), "getJsonString") - .addArgument(new StringLiteralExpr(field.getName()))) - .addArgument(new NameExpr("ctx"))))); - } - - @Override - public Statement getFieldSerializer(PropertyDefinition field, CompilationUnit cu) { - return new ExpressionStmt( - new MethodCallExpr(getSerializerCreationExpr(cu), "serialize") - .addArgument( - new MethodCallExpr( - new NameExpr("bean"), field.getGetter().getSimpleName().toString())) - .addArgument(new StringLiteralExpr(field.getName())) - .addArgument(new NameExpr("generator")) - .addArgument(new NameExpr("ctx"))); - } - - private String getEnumName(Element enumConstant) { - String enumName = enumConstant.toString(); - return enumName; - } - - public Expression getSerializerCreationExpr(CompilationUnit cu) { - cu.addImport(EnumJsonSerializer.class); - cu.addImport(Function.class); - - NodeList> anonymousClassBody = new NodeList<>(); - NodeList typeArguments = new NodeList<>(); - typeArguments.add(new ClassOrInterfaceType().setName(this.property.toString())); - typeArguments.add(new ClassOrInterfaceType().setName("String")); - - ClassOrInterfaceType type = new ClassOrInterfaceType().setName("Function"); - type.setTypeArguments(typeArguments); - - ObjectCreationExpr function = new ObjectCreationExpr().setType(type); - function.setAnonymousClassBody(anonymousClassBody); - - MethodDeclaration apply = new MethodDeclaration(); - apply.setModifiers(Modifier.Keyword.PUBLIC); - apply.addAnnotation(Override.class); - apply.setName("apply"); - apply.setType(new ClassOrInterfaceType().setName("String")); - apply.addParameter(this.property.toString(), "value"); - - anonymousClassBody.add(apply); - - for (Element enumConstant : MoreTypes.asTypeElement(this.property).getEnclosedElements()) { - if (enumConstant.getKind().equals(ElementKind.ENUM_CONSTANT)) { - apply - .getBody() - .ifPresent( - body -> - body.addAndGetStatement( - new IfStmt() - .setCondition( - new MethodCallExpr( - new NameExpr( - this.property.toString() + "." + enumConstant), - "equals") - .addArgument(new NameExpr("value")))) - .setThenStmt( - new ReturnStmt(new StringLiteralExpr(getEnumName(enumConstant))))); - } - } - - apply - .getBody() - .ifPresent(body -> body.addAndGetStatement(new ReturnStmt(new NullLiteralExpr()))); - - ObjectCreationExpr ser = - new ObjectCreationExpr() - .setType(new ClassOrInterfaceType().setName(EnumJsonSerializer.class.getSimpleName())) - .addArgument(function); - return ser; - } - - public Expression getDeserializerCreationExpr(CompilationUnit cu) { - cu.addImport(EnumJsonDeserializer.class); - cu.addImport(Function.class); - cu.addImport(MoreTypes.asTypeElement(this.property).getQualifiedName().toString()); - - ObjectCreationExpr deser = - new ObjectCreationExpr() - .setType(new ClassOrInterfaceType().setName(EnumJsonDeserializer.class.getSimpleName())) - .addArgument( - MoreTypes.asTypeElement(this.property).getSimpleName().toString() + ".class"); - - NodeList> anonymousClassBody = new NodeList<>(); - NodeList typeArguments = new NodeList<>(); - typeArguments.add(new ClassOrInterfaceType().setName("String")); - typeArguments.add(new ClassOrInterfaceType().setName(this.property.toString())); - - ClassOrInterfaceType type = new ClassOrInterfaceType().setName("Function"); - type.setTypeArguments(typeArguments); - - ObjectCreationExpr function = new ObjectCreationExpr().setType(type); - function.setAnonymousClassBody(anonymousClassBody); - - MethodDeclaration apply = new MethodDeclaration(); - apply.setModifiers(Modifier.Keyword.PUBLIC); - apply.addAnnotation(Override.class); - apply.setName("apply"); - apply.setType(this.property.toString()); - apply.addParameter("String", "value"); - - anonymousClassBody.add(apply); - - for (Element enumConstant : MoreTypes.asTypeElement(this.property).getEnclosedElements()) { - if (enumConstant.getKind().equals(ElementKind.ENUM_CONSTANT)) { - apply - .getBody() - .ifPresent( - body -> - body.addAndGetStatement( - new IfStmt() - .setCondition( - new MethodCallExpr( - new StringLiteralExpr(getEnumName(enumConstant)), - "equals") - .addArgument(new NameExpr("value")))) - .setThenStmt( - new ReturnStmt( - new NameExpr(this.property.toString() + "." + enumConstant)))); - } - } - - apply - .getBody() - .ifPresent(body -> body.addAndGetStatement(new ReturnStmt(new NullLiteralExpr()))); - - deser.addArgument(function); - return deser; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/FieldDefinition.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/FieldDefinition.java deleted file mode 100644 index 632dab89b68..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/FieldDefinition.java +++ /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. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.apt.definition; - -import javax.lang.model.type.TypeMirror; - -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.stmt.Statement; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; - -public abstract class FieldDefinition { - - protected final GenerationContext context; - protected final TypeMirror property; - - protected FieldDefinition(TypeMirror property, GenerationContext context) { - this.context = context; - this.property = property; - } - - public abstract Statement getFieldDeserializer(PropertyDefinition field, CompilationUnit cu); - - public abstract Statement getFieldSerializer(PropertyDefinition field, CompilationUnit cu); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/FieldDefinitionFactory.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/FieldDefinitionFactory.java deleted file mode 100644 index a2564080296..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/FieldDefinitionFactory.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.apt.definition; - -import java.util.HashMap; -import java.util.Map; - -import javax.lang.model.element.ElementKind; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; - -import com.google.auto.common.MoreTypes; -import jakarta.json.bind.annotation.JsonbTypeDeserializer; -import jakarta.json.bind.annotation.JsonbTypeInfo; -import jakarta.json.bind.annotation.JsonbTypeSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.apt.exception.GenerationException; -import org.kie.workbench.common.stunner.client.json.mapper.apt.utils.TypeUtils; - -public class FieldDefinitionFactory { - - private final GenerationContext context; - private final TypeUtils typeUtils; - private final Map holder = new HashMap<>(); - - public FieldDefinitionFactory(GenerationContext context) { - this.context = context; - this.typeUtils = context.getTypeUtils(); - } - - public FieldDefinition getFieldDefinition(TypeMirror type) { - TypeMirror property = context.getProcessingEnv().getTypeUtils().erasure(type); - FieldDefinition result = null; - - if (holder.containsKey(property)) { - result = holder.get(property); - } else if (typeUtils.isSimpleType(property)) { - result = new BasicTypeFieldDefinition(property, context); - } else if (type.getKind().equals(TypeKind.ARRAY)) { - result = new ArrayBeanFieldDefinition(property, context); - } else if (MoreTypes.asElement(property).getKind().equals(ElementKind.ENUM)) { - result = new EnumBeanFieldDefinition(property, context); - } else if (MoreTypes.asTypeElement(type).getAnnotation(JsonbTypeInfo.class) != null) { - result = new JsonbTypeSerFieldDefinition(type, context); - } else if (context.getTypeUtils().isIterable(property)) { - result = new CollectionsFieldDefinition(property, context); - } else if (MoreTypes.asTypeElement(type).getAnnotation(JsonbTypeSerializer.class) != null - && MoreTypes.asTypeElement(type).getAnnotation(JsonbTypeDeserializer.class) != null) { - return new JsonbTypeSerFieldDefinition(type, context); - } else { - result = new DefaultBeanFieldDefinition(property, context); - } - - if (result == null) { - throw new GenerationException("Unsupported type: " + type); - } - - holder.put(property, result); - return result; - } - - public FieldDefinition getFieldDefinition(PropertyDefinition propertyDefinition) { - TypeMirror jsonbTypeSerializerType = propertyDefinition.getType(); - - if (!(context.getTypeUtils().isIterable(jsonbTypeSerializerType) - || jsonbTypeSerializerType.getKind().equals(TypeKind.ARRAY))) { - JsonbTypeSerializer jsonbTypeSerializer = - propertyDefinition.getVariableElement().getAnnotation(JsonbTypeSerializer.class); - JsonbTypeDeserializer jsonbTypeDeserializer = - propertyDefinition.getVariableElement().getAnnotation(JsonbTypeDeserializer.class); - - if (jsonbTypeSerializer == null && jsonbTypeDeserializer == null) { - TypeMirror typeMirror = propertyDefinition.getVariableElement().asType(); - if (!typeMirror.getKind().isPrimitive()) { - if (typeMirror.getKind().equals(TypeKind.ARRAY)) { - typeMirror = MoreTypes.asArray(typeMirror).getComponentType(); - } - if (MoreTypes.asTypeElement(typeMirror).getAnnotation(JsonbTypeSerializer.class) != null - && MoreTypes.asTypeElement(typeMirror).getAnnotation(JsonbTypeDeserializer.class) - != null) { - jsonbTypeSerializer = - MoreTypes.asTypeElement(typeMirror).getAnnotation(JsonbTypeSerializer.class); - jsonbTypeDeserializer = - MoreTypes.asTypeElement(typeMirror).getAnnotation(JsonbTypeDeserializer.class); - jsonbTypeSerializerType = typeMirror; - } - } - } - - if (jsonbTypeSerializer != null || jsonbTypeDeserializer != null) { - if (jsonbTypeSerializer == null || jsonbTypeDeserializer == null) { - throw new GenerationException( - "@JsonbTypeSerializer and @JsonbTypeDeserializer MUST be used together"); - } - return new JsonbTypeSerFieldDefinition(jsonbTypeSerializerType, context); - } - } - TypeMirror type = propertyDefinition.getVariableElement().asType(); - if (!(type.getKind().isPrimitive() || type.getKind().equals(TypeKind.ARRAY))) { - JsonbTypeInfo jsonbTypeInfo = - MoreTypes.asTypeElement(propertyDefinition.getVariableElement().asType()) - .getAnnotation(JsonbTypeInfo.class); - if (jsonbTypeInfo != null) { - return new JsonbTypeInfoDefinition( - jsonbTypeInfo, propertyDefinition.getVariableElement().asType(), context); - } - } - - return getFieldDefinition(propertyDefinition.getType()); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/JsonbTypeInfoDefinition.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/JsonbTypeInfoDefinition.java deleted file mode 100644 index 22da732f10b..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/JsonbTypeInfoDefinition.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.apt.definition; - -import java.util.HashMap; -import java.util.Map; - -import javax.lang.model.type.MirroredTypeException; -import javax.lang.model.type.TypeMirror; - -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.expr.FieldAccessExpr; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.ObjectCreationExpr; -import com.github.javaparser.ast.expr.StringLiteralExpr; -import com.github.javaparser.ast.stmt.ExpressionStmt; -import com.github.javaparser.ast.stmt.Statement; -import com.github.javaparser.ast.type.ClassOrInterfaceType; -import com.github.javaparser.ast.type.UnknownType; -import com.google.auto.common.MoreTypes; -import jakarta.json.bind.annotation.JsonbSubtype; -import jakarta.json.bind.annotation.JsonbTypeInfo; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.Pair; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.JsonbSubtypeDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.JsonbSubtypeSerializer; - - -public class JsonbTypeInfoDefinition extends FieldDefinition { - - private final Map types = new HashMap<>(); - - private final String typeFieldName; - - public JsonbTypeInfoDefinition( - JsonbTypeInfo jsonbTypeInfo, TypeMirror property, GenerationContext context) { - super(property, context); - this.typeFieldName = jsonbTypeInfo.key(); - for (JsonbSubtype jsonbSubtype : jsonbTypeInfo.value()) { - getJsonbSubtype(jsonbSubtype); - } - } - - @Override - public Statement getFieldDeserializer(PropertyDefinition field, CompilationUnit cu) { - ObjectCreationExpr deserializerCreationExpr = getDeserializerCreationExpr(field.getType(), cu); - - return new ExpressionStmt( - new MethodCallExpr(new NameExpr("bean"), field.getSetter().getSimpleName().toString()) - .addArgument( - new MethodCallExpr(deserializerCreationExpr, "deserialize") - .addArgument( - new MethodCallExpr(new NameExpr("jsonObject"), "getJsonObject") - .addArgument(new StringLiteralExpr(field.getName()))) - .addArgument(new NameExpr("ctx")))); - } - - @Override - public Statement getFieldSerializer(PropertyDefinition field, CompilationUnit cu) { - ObjectCreationExpr serializerCreationExpr = getSerializerCreationExpr(cu); - return new ExpressionStmt( - new MethodCallExpr(serializerCreationExpr, "serialize") - .addArgument( - new MethodCallExpr( - new NameExpr("bean"), field.getGetter().getSimpleName().toString())) - .addArgument(new StringLiteralExpr(field.getName())) - .addArgument(new NameExpr("generator")) - .addArgument(new NameExpr("ctx"))); - } - - public ObjectCreationExpr getSerializerCreationExpr(CompilationUnit cu) { - cu.addImport(JsonbSubtypeSerializer.class); - cu.addImport(JsonbSubtypeSerializer.Info.class); - - ClassOrInterfaceType type = new ClassOrInterfaceType(); - type.setName(JsonbSubtypeSerializer.class.getSimpleName()); - - ObjectCreationExpr serializerCreationExpr = new ObjectCreationExpr(); - type.setTypeArguments(new UnknownType()); - serializerCreationExpr.setType(type); - - serializerCreationExpr.addArgument(new StringLiteralExpr(typeFieldName)); - - types.forEach( - (alias, mirror) -> { - ObjectCreationExpr info = new ObjectCreationExpr(); - info.setType( - new ClassOrInterfaceType() - .setName(JsonbSubtypeSerializer.Info.class.getSimpleName())); - info.addArgument(new StringLiteralExpr(alias)); - info.addArgument(new FieldAccessExpr(new NameExpr(mirror.toString()), "class")); - info.addArgument( - new ObjectCreationExpr() - .setType( - new ClassOrInterfaceType() - .setName( - context - .getTypeUtils() - .getJsonSerializerImplQualifiedName( - MoreTypes.asTypeElement(mirror))))); - serializerCreationExpr.addArgument(info); - }); - return serializerCreationExpr; - } - - private void getJsonbSubtype(JsonbSubtype jsonbSubtype) { - try { - jsonbSubtype.type(); - } catch (MirroredTypeException e) { - types.put(jsonbSubtype.alias(), e.getTypeMirror()); - } - } - - public ObjectCreationExpr getDeserializerCreationExpr(TypeMirror fieldType, CompilationUnit cu) { - cu.addImport(JsonbSubtypeDeserializer.class); - cu.addImport(Pair.class); - - ClassOrInterfaceType type = new ClassOrInterfaceType(); - type.setName(JsonbSubtypeDeserializer.class.getSimpleName()); - - ObjectCreationExpr deserializerCreationExpr = new ObjectCreationExpr(); - type.setTypeArguments(new ClassOrInterfaceType().setName(fieldType.toString())); - deserializerCreationExpr.setType(type); - - deserializerCreationExpr.addArgument(new StringLiteralExpr(typeFieldName)); - - types.forEach( - (alias, ser) -> { - ObjectCreationExpr pairCreationExpr = new ObjectCreationExpr(); - pairCreationExpr.setType(new ClassOrInterfaceType().setName("Pair")); - pairCreationExpr.addArgument(new StringLiteralExpr(alias)); - pairCreationExpr.addArgument( - new ObjectCreationExpr() - .setType( - new ClassOrInterfaceType() - .setName( - context - .getTypeUtils() - .getJsonDeserializerImplQualifiedName( - MoreTypes.asTypeElement(ser), cu)))); - deserializerCreationExpr.addArgument(pairCreationExpr); - }); - return deserializerCreationExpr; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/JsonbTypeSerFieldDefinition.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/JsonbTypeSerFieldDefinition.java deleted file mode 100644 index d8226892013..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/JsonbTypeSerFieldDefinition.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.apt.definition; - -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.MirroredTypeException; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; - -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.expr.Expression; -import com.github.javaparser.ast.expr.FieldAccessExpr; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.ObjectCreationExpr; -import com.github.javaparser.ast.expr.StringLiteralExpr; -import com.github.javaparser.ast.stmt.ExpressionStmt; -import com.github.javaparser.ast.stmt.Statement; -import com.github.javaparser.ast.type.ClassOrInterfaceType; -import com.github.javaparser.ast.type.UnknownType; -import com.google.auto.common.MoreTypes; -import jakarta.json.bind.annotation.JsonbTypeDeserializer; -import jakarta.json.bind.annotation.JsonbTypeSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.DeserializerJsonbTypeSerializerWrapper; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.JsonbDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.SerializerJsonbTypeSerializerWrapper; - - -public class JsonbTypeSerFieldDefinition extends FieldDefinition { - - private TypeMirror jsonbDeserializer; - - protected JsonbTypeSerFieldDefinition(TypeMirror property, GenerationContext context) { - super(property, context); - TypeElement jsonbDeserializer = - context - .getProcessingEnv() - .getElementUtils() - .getTypeElement( - JsonbDeserializer.class - .getCanonicalName()); - this.jsonbDeserializer = - context.getProcessingEnv().getTypeUtils().erasure(jsonbDeserializer.asType()); - } - - @Override - public Statement getFieldDeserializer(PropertyDefinition field, CompilationUnit cu) { - JsonbTypeDeserializer jsonbTypeDeserializer = - field.getVariableElement().getAnnotation(JsonbTypeDeserializer.class) != null - ? field.getVariableElement().getAnnotation(JsonbTypeDeserializer.class) - : MoreTypes.asTypeElement(property).getAnnotation(JsonbTypeDeserializer.class); - try { - jsonbTypeDeserializer.value(); - } catch (MirroredTypeException e) { - Expression deserializerCreationExpr = getFieldDeserializerCreationExpr(field, cu); - return new ExpressionStmt( - new MethodCallExpr(new NameExpr("bean"), field.getSetter().getSimpleName().toString()) - .addArgument( - new MethodCallExpr(deserializerCreationExpr, "deserialize") - .addArgument( - new MethodCallExpr(new NameExpr("jsonObject"), "get") - .addArgument(new StringLiteralExpr(field.getName()))) - .addArgument(new NameExpr("ctx")))); - } - return null; - } - - @Override - public Statement getFieldSerializer(PropertyDefinition field, CompilationUnit cu) { - JsonbTypeSerializer jsonbTypeSerializer = - field.getVariableElement().getAnnotation(JsonbTypeSerializer.class) != null - ? field.getVariableElement().getAnnotation(JsonbTypeSerializer.class) - : MoreTypes.asTypeElement(property).getAnnotation(JsonbTypeSerializer.class); - try { - jsonbTypeSerializer.value(); - } catch (MirroredTypeException e) { - return new ExpressionStmt( - new MethodCallExpr( - new ObjectCreationExpr() - .setType(SerializerJsonbTypeSerializerWrapper.class.getCanonicalName()) - .addArgument(new ObjectCreationExpr().setType(e.getTypeMirror().toString())) - .addArgument(new StringLiteralExpr(field.getName())), - "serialize") - .addArgument( - new MethodCallExpr( - new NameExpr("bean"), field.getGetter().getSimpleName().toString())) - .addArgument(new NameExpr("generator")) - .addArgument(new NameExpr("ctx"))); - } - - return null; - } - - public Expression getFieldSerializerCreationExpr(PropertyDefinition field, CompilationUnit cu) { - JsonbTypeSerializer jsonbTypeSerializer = - field.getVariableElement().getAnnotation(JsonbTypeSerializer.class) != null - ? field.getVariableElement().getAnnotation(JsonbTypeSerializer.class) - : MoreTypes.asTypeElement(property).getAnnotation(JsonbTypeSerializer.class); - try { - jsonbTypeSerializer.value(); - } catch (MirroredTypeException e) { - return new ObjectCreationExpr().setType(e.getTypeMirror().toString()); - } - return null; - } - - public Expression getFieldDeserializerCreationExpr(PropertyDefinition field, CompilationUnit cu) { - JsonbTypeDeserializer jsonbTypeDeserializer = - field.getVariableElement().getAnnotation(JsonbTypeDeserializer.class) != null - ? field.getVariableElement().getAnnotation(JsonbTypeDeserializer.class) - : MoreTypes.asTypeElement(property).getAnnotation(JsonbTypeDeserializer.class); - try { - jsonbTypeDeserializer.value(); - } catch (MirroredTypeException e) { - - TypeMirror typeMirror = field.getType(); - if (context.getTypeUtils().isIterable(typeMirror)) { - typeMirror = MoreTypes.asDeclared(field.getType()).getTypeArguments().get(0); - } else if (typeMirror.getKind().equals(TypeKind.ARRAY)) { - typeMirror = MoreTypes.asArray(typeMirror).getComponentType(); - } - - ClassOrInterfaceType type = new ClassOrInterfaceType(); - type.setName(DeserializerJsonbTypeSerializerWrapper.class.getCanonicalName()); - type.setTypeArguments(new UnknownType()); - - return new ObjectCreationExpr() - .setType(type) - .addArgument(new ObjectCreationExpr().setType(e.getTypeMirror().toString())) - .addArgument(new FieldAccessExpr(new NameExpr(typeMirror.toString()), "class")); - } - return null; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/PropertyDefinition.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/PropertyDefinition.java deleted file mode 100644 index 40a8b9a1594..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/definition/PropertyDefinition.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.apt.definition; - -import java.util.Objects; - -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeMirror; - -import jakarta.json.bind.annotation.JsonbProperty; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; - -public class PropertyDefinition { - - private final VariableElement property; - private final GenerationContext context; - - protected PropertyDefinition(VariableElement property, GenerationContext context) { - this.property = property; - this.context = context; - } - - public String getName() { - if (property.getAnnotation(JsonbProperty.class) != null - && !property.getAnnotation(JsonbProperty.class).value().isEmpty()) { - return property.getAnnotation(JsonbProperty.class).value(); - } - return property.getSimpleName().toString(); - } - - public TypeMirror getType() { - return property.asType(); - } - - public ExecutableElement getGetter() { - return context.getTypeUtils().getGetter(property); - } - - public ExecutableElement getSetter() { - return context.getTypeUtils().getSetter(property); - } - - public VariableElement getVariableElement() { - return property; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - PropertyDefinition that = (PropertyDefinition) o; - return Objects.equals(property, that.property); - } - - @Override - public int hashCode() { - return Objects.hash(property); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/GenerationException.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/GenerationException.java deleted file mode 100644 index 833f63293ba..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/GenerationException.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.apt.exception; - -public class GenerationException extends RuntimeException { - private static final long serialVersionUID = 1L; - private String additionalFailureInfo = ""; - - public GenerationException() {} - - public GenerationException(String msg) { - super(msg); - } - - public GenerationException(Throwable t) { - super(t); - } - - public GenerationException(String message, Throwable cause) { - super(message, cause); - } - - public void appendFailureInfo(String info) { - this.additionalFailureInfo = this.additionalFailureInfo + "\n" + info; - } - - @Override - public String getMessage() { - return super.getMessage() + this.additionalFailureInfo; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/TypeDeserializerNotFoundException.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/TypeDeserializerNotFoundException.java deleted file mode 100644 index 7b162b7371a..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/TypeDeserializerNotFoundException.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.apt.exception; - -public class TypeDeserializerNotFoundException extends RuntimeException { - - public TypeDeserializerNotFoundException(String typeName) { - super(typeName); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/TypeMapperNotFoundException.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/TypeMapperNotFoundException.java deleted file mode 100644 index bab0a4a8d20..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/TypeMapperNotFoundException.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.apt.exception; - -public class TypeMapperNotFoundException extends RuntimeException { - - public TypeMapperNotFoundException(String typeName) { - super(typeName); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/TypeSerializerNotFoundException.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/TypeSerializerNotFoundException.java deleted file mode 100644 index 011723f7725..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/TypeSerializerNotFoundException.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.apt.exception; - -public class TypeSerializerNotFoundException extends RuntimeException { - - public TypeSerializerNotFoundException(String typeName) { - super(typeName); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/UnableToCompleteException.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/UnableToCompleteException.java deleted file mode 100644 index e8810379c11..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/exception/UnableToCompleteException.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2006 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.kie.workbench.common.stunner.client.json.mapper.apt.exception; - -/** - * Used to indicate that some part of a multi-step process failed. Typically, operation can continue - * after this exception is caught. - * - *

    Before throwing an object of this type, the thrower - * - *

      - *
    • must log a detailed user-facing message describing the failure, - *
    • must report any caught exception using the logger that contributed to the failure, and - *
    • must not include the cause of the failure in the thrown exception because (1) it will - * already have been associated with the detailed log entry above and (2) doing so would - * create a misunderstanding of how to find the causes of low-level errors in that sometimes - * there is an underlying an exception, sometimes not, but there can always be a - * preceding log entry. - *
    - * - *

    After catching an object of this type, the catcher - * - *

      - *
    • can be assured that the thrower has already logged a message about the lower-level problem - *
    • can optionally itself log a higher-level description of the process that was interrupted - * and the implications of the failure, and if so, - *
    • should report this caught exception via the logger as well. - *
    - * - *
    - *  void lowLevel(Logger logger) throws UnableToCompleteException {
    - *      try {
    - *          doSomethingThatMightFail();
    - *      catch (SomeException e) {
    - *          // Log low-level detail and the caught exception.
    - *          //
    - *          logger.log("detailed problem explanation for user eyes...", e);
    - *
    - *          // Do not include the caught exception.
    - *          //
    - *          throw new UnableToCompleteException();
    - *      }
    - *  }
    - *
    - *  void highLevel(Logger logger) {
    - *      try {
    - *          // Multiple calls are shown to indicate that the process can
    - *          // include any number of steps.
    - *          //
    - *          lowLevel(logger);
    - *          lowLevel(logger);
    - *          lowLevel(logger);
    - *      }
    - *      catch (UnableToCompleteException e) {
    - *          logger.log("high-level thing failed", e);
    - *      }
    - *  }
    - * 
    - */ -public class UnableToCompleteException extends Exception { - public UnableToCompleteException(String msg, Exception e) { - super(msg, e); - } - - public UnableToCompleteException(Exception e) { - super(e); - } - - public UnableToCompleteException(String e) { - super(e); - } - - public UnableToCompleteException() {} -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/generator/AbstractGenerator.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/generator/AbstractGenerator.java deleted file mode 100644 index 583af492d7f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/generator/AbstractGenerator.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.apt.generator; - -import java.io.IOException; -import java.io.PrintWriter; - -import javax.annotation.processing.FilerException; -import javax.lang.model.element.TypeElement; -import javax.tools.JavaFileObject; - -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.Modifier; -import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; -import com.github.javaparser.ast.expr.NormalAnnotationExpr; -import com.github.javaparser.ast.expr.ObjectCreationExpr; -import com.github.javaparser.ast.expr.StringLiteralExpr; -import com.github.javaparser.ast.type.ClassOrInterfaceType; -import com.google.auto.common.MoreElements; -import jakarta.json.bind.annotation.JsonbTypeDeserializer; -import jakarta.json.bind.annotation.JsonbTypeSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.apt.definition.BeanDefinition; -import org.kie.workbench.common.stunner.client.json.mapper.apt.exception.GenerationException; -import org.kie.workbench.common.stunner.client.json.mapper.apt.logger.TreeLogger; -import org.kie.workbench.common.stunner.client.json.mapper.apt.utils.TypeUtils; - -public abstract class AbstractGenerator { - - protected final GenerationContext context; - protected final TypeUtils typeUtils; - protected final TreeLogger logger; - protected CompilationUnit cu; - protected ClassOrInterfaceDeclaration declaration; - - public AbstractGenerator(GenerationContext context, TreeLogger logger) { - this.context = context; - this.logger = logger; - this.typeUtils = context.getTypeUtils(); - } - - public void generate(BeanDefinition type) { - if (type.getElement().getQualifiedName().toString().equals(Object.class.getCanonicalName())) { - return; - } - if (type.getElement().getAnnotation(JsonbTypeSerializer.class) != null - && type.getElement().getAnnotation(JsonbTypeDeserializer.class) != null) { - return; - } - - cu = new CompilationUnit(); - cu.setPackageDeclaration(type.getPackageQualifiedName()); - declaration = cu.addClass(getMapperName(type.getElement())); - - // addGeneratedAnnotation(declaration); - configureClassType(type); - addTypeParam(type, declaration); - getType(type); - init(type); - write(type.getElement()); - } - - private void addGeneratedAnnotation(ClassOrInterfaceDeclaration declaration) { - NormalAnnotationExpr generated = new NormalAnnotationExpr(); - generated.setName("javax.annotation.processing.Generated"); - generated.addPair("value", new StringLiteralExpr(this.getClass().getCanonicalName())); - declaration.addAnnotation(generated); - } - - protected abstract String getMapperName(TypeElement type); - - protected abstract void configureClassType(BeanDefinition type); - - protected void addTypeParam(BeanDefinition type, ClassOrInterfaceDeclaration declaration) {} - - protected void getType(BeanDefinition type) {} - - protected abstract void init(BeanDefinition type); - - protected void write(TypeElement type) { - logger.branch(TreeLogger.INFO, "Writing " + getMapperName(type)); - // TypeMirror property = context.getProcessingEnv().getTypeUtils().erasure(type.asType()); - try { - build(MoreElements.getPackage(type) + "." + getMapperName(type), cu.toString()); - } catch (FilerException e1) { - logger.log(TreeLogger.ERROR, e1.getMessage()); - } catch (IOException e1) { - throw new GenerationException(e1); - } - } - - private void build(String fileName, String source) throws IOException { - JavaFileObject builderFile = context.getProcessingEnv().getFiler().createSourceFile(fileName); - - try (PrintWriter out = new PrintWriter(builderFile.openWriter())) { - out.append(source); - } catch (FilerException e) { - throw new GenerationException(e); - } - } - - protected void addStaticInstance(BeanDefinition type) { - declaration.addFieldWithInitializer( - new ClassOrInterfaceType().setName(getMapperName(type.getElement())), - "INSTANCE", - new ObjectCreationExpr() - .setType(new ClassOrInterfaceType().setName(getMapperName(type.getElement()))), - Modifier.Keyword.FINAL, - Modifier.Keyword.PUBLIC, - Modifier.Keyword.STATIC); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/generator/DeserializerGenerator.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/generator/DeserializerGenerator.java deleted file mode 100644 index 427472d6ab6..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/generator/DeserializerGenerator.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.apt.generator; - -import javax.lang.model.element.TypeElement; - -import com.github.javaparser.ast.Modifier; -import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; -import com.github.javaparser.ast.body.ConstructorDeclaration; -import com.github.javaparser.ast.body.MethodDeclaration; -import com.github.javaparser.ast.body.Parameter; -import com.github.javaparser.ast.expr.LambdaExpr; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.ObjectCreationExpr; -import com.github.javaparser.ast.expr.StringLiteralExpr; -import com.github.javaparser.ast.stmt.BlockStmt; -import com.github.javaparser.ast.stmt.ReturnStmt; -import com.github.javaparser.ast.stmt.Statement; -import com.github.javaparser.ast.type.ClassOrInterfaceType; -import com.github.javaparser.ast.type.UnknownType; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.apt.definition.BeanDefinition; -import org.kie.workbench.common.stunner.client.json.mapper.apt.definition.FieldDefinition; -import org.kie.workbench.common.stunner.client.json.mapper.apt.definition.FieldDefinitionFactory; -import org.kie.workbench.common.stunner.client.json.mapper.apt.definition.PropertyDefinition; -import org.kie.workbench.common.stunner.client.json.mapper.apt.logger.TreeLogger; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.AbstractBeanJsonDeserializer; - - -public class DeserializerGenerator extends AbstractGenerator { - - private ConstructorDeclaration constructor; - - private final FieldDefinitionFactory fieldDefinitionFactory; - - public DeserializerGenerator(GenerationContext context, TreeLogger logger) { - super(context, logger); - fieldDefinitionFactory = context.getFieldDefinitionFactory(); - } - - @Override - protected String getMapperName(TypeElement type) { - return context.getTypeUtils().getJsonDeserializerImplName(type); - } - - @Override - protected void configureClassType(BeanDefinition type) { - cu.addImport(AbstractBeanJsonDeserializer.class); - - declaration - .getExtendedTypes() - .add( - new ClassOrInterfaceType() - .setName(AbstractBeanJsonDeserializer.class.getSimpleName()) - .setTypeArguments( - new ClassOrInterfaceType() - .setName(type.getElement().getQualifiedName().toString()))); - - constructor = declaration.addConstructor(Modifier.Keyword.PUBLIC); - } - - @Override - protected void init(BeanDefinition type) { - logger.branch( - TreeLogger.INFO, "Generating deserializer for " + type.getElement().getSimpleName()); - - addStaticInstance(type); - addNewInstance(declaration, type); - - type.getPropertyDefinitionsAsStream() - .forEach( - propertyDefinition -> { - FieldDefinition fieldDefinition = - fieldDefinitionFactory.getFieldDefinition(propertyDefinition); - addGetter( - propertyDefinition, - constructor.getBody(), - fieldDefinition.getFieldDeserializer(propertyDefinition, cu)); - }); - } - - private void addNewInstance(ClassOrInterfaceDeclaration declaration, BeanDefinition type) { - MethodDeclaration methodDeclaration = - declaration.addMethod("newInstance", Modifier.Keyword.PUBLIC); - methodDeclaration.setType( - new ClassOrInterfaceType().setName(type.getElement().getQualifiedName().toString())); - methodDeclaration - .getBody() - .get() - .addAndGetStatement( - new ReturnStmt( - new ObjectCreationExpr().setType(type.getElement().getQualifiedName().toString()))); - } - - private void addGetter(PropertyDefinition propertyDefinition, BlockStmt body, Statement call) { - - LambdaExpr lambda = new LambdaExpr(); - lambda.setEnclosingParameters(true); - lambda.getParameters().add(new Parameter().setType(new UnknownType()).setName("bean")); - lambda.getParameters().add(new Parameter().setType(new UnknownType()).setName("jsonObject")); - lambda.getParameters().add(new Parameter().setType(new UnknownType()).setName("ctx")); - lambda.setBody(call); - body.addStatement( - new MethodCallExpr(new NameExpr("properties"), "put") - .addArgument(new StringLiteralExpr(propertyDefinition.getName())) - .addArgument(lambda)); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/generator/MapperGenerator.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/generator/MapperGenerator.java deleted file mode 100644 index 4d2e492194f..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/generator/MapperGenerator.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.apt.generator; - -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.TypeElement; - -import com.github.javaparser.ast.Modifier; -import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; -import com.github.javaparser.ast.expr.FieldAccessExpr; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.expr.SimpleName; -import com.github.javaparser.ast.stmt.ReturnStmt; -import com.github.javaparser.ast.type.ClassOrInterfaceType; -import com.github.javaparser.ast.type.TypeParameter; -import com.google.auto.common.MoreElements; -import jakarta.json.bind.serializer.JsonbDeserializer; -import jakarta.json.bind.serializer.JsonbSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.AbstractObjectMapper; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.apt.definition.BeanDefinition; -import org.kie.workbench.common.stunner.client.json.mapper.apt.logger.TreeLogger; - - -public class MapperGenerator extends AbstractGenerator { - - private static final String MAPPER_IMPL = "_JsonMapperImpl"; - - private final DeserializerGenerator deserializerGenerator; - private final SerializerGenerator serializerGenerator; - - public MapperGenerator(GenerationContext context, TreeLogger logger) { - super(context, logger); - this.deserializerGenerator = new DeserializerGenerator(context, logger); - this.serializerGenerator = new SerializerGenerator(context, logger); - } - - @Override - protected void configureClassType(BeanDefinition type) { - cu.addImport(JsonbDeserializer.class); - cu.addImport(JsonbSerializer.class); - - setExtendedType(type); - } - - private void setExtendedType(BeanDefinition type) { - String typeMapperName = getTypeMapperName(type); - declaration - .getExtendedTypes() - .add( - new ClassOrInterfaceType() - .setName(AbstractObjectMapper.class.getCanonicalName()) - .setTypeArguments(new ClassOrInterfaceType().setName(typeMapperName))); - } - - private String getTypeMapperName(BeanDefinition type) { - return type.getElement().getQualifiedName().toString(); - } - - @Override - protected void init(BeanDefinition type) { - serializerGenerator.generate(type); - deserializerGenerator.generate(type); - - addStaticInstance(type); - addDeserializer(type); - addSerializer(type); - } - - private void addSerializer(BeanDefinition type) { - ClassOrInterfaceType returnType = - new ClassOrInterfaceType() - .setName(JsonbSerializer.class.getSimpleName()) - .setTypeArguments(new ClassOrInterfaceType().setName(getTypeMapperName(type))); - declaration - .addMethod("newSerializer", Modifier.Keyword.PROTECTED) - .addAnnotation(Override.class) - .setType(returnType) - .getBody() - .ifPresent( - body -> - body.addStatement( - new ReturnStmt( - new FieldAccessExpr( - new NameExpr(serializerGenerator.getMapperName(type.getElement())), - "INSTANCE")))); - } - - private void addDeserializer(BeanDefinition type) { - ClassOrInterfaceType returnType = - new ClassOrInterfaceType() - .setName(JsonbDeserializer.class.getSimpleName()) - .setTypeArguments(new ClassOrInterfaceType().setName(getTypeMapperName(type))); - declaration - .addMethod("newDeserializer", Modifier.Keyword.PROTECTED) - .addAnnotation(Override.class) - .setType(returnType) - .getBody() - .ifPresent( - body -> - body.addStatement( - new ReturnStmt( - new FieldAccessExpr( - new NameExpr(deserializerGenerator.getMapperName(type.getElement())), - "INSTANCE")))); - } - - @Override - protected String getMapperName(TypeElement type) { - return (type.getEnclosingElement().getKind().equals(ElementKind.PACKAGE) - ? "" - : MoreElements.asType(type.getEnclosingElement()).getSimpleName().toString() + "_") - + type.getSimpleName() - + MAPPER_IMPL; - } - - @Override - protected void addTypeParam(BeanDefinition type, ClassOrInterfaceDeclaration declaration) { - if (!type.getElement().getKind().isClass()) { - declaration - .getTypeParameters() - .add( - new TypeParameter() - .setName(new SimpleName("T extends " + type.getElement().getSimpleName()))); - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/generator/SerializerGenerator.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/generator/SerializerGenerator.java deleted file mode 100644 index cb7238df34b..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/generator/SerializerGenerator.java +++ /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 org.kie.workbench.common.stunner.client.json.mapper.apt.generator; - -import javax.lang.model.element.TypeElement; - -import com.github.javaparser.ast.Modifier; -import com.github.javaparser.ast.body.ConstructorDeclaration; -import com.github.javaparser.ast.body.Parameter; -import com.github.javaparser.ast.expr.LambdaExpr; -import com.github.javaparser.ast.expr.MethodCallExpr; -import com.github.javaparser.ast.expr.NameExpr; -import com.github.javaparser.ast.stmt.BlockStmt; -import com.github.javaparser.ast.stmt.Statement; -import com.github.javaparser.ast.type.ClassOrInterfaceType; -import com.github.javaparser.ast.type.UnknownType; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.apt.definition.BeanDefinition; -import org.kie.workbench.common.stunner.client.json.mapper.apt.definition.FieldDefinition; -import org.kie.workbench.common.stunner.client.json.mapper.apt.definition.FieldDefinitionFactory; -import org.kie.workbench.common.stunner.client.json.mapper.apt.logger.TreeLogger; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.AbstractBeanJsonSerializer; - - -public class SerializerGenerator extends AbstractGenerator { - - private final FieldDefinitionFactory fieldDefinitionFactory; - - private ConstructorDeclaration constructor; - - public SerializerGenerator(GenerationContext context, TreeLogger logger) { - super(context, logger); - fieldDefinitionFactory = context.getFieldDefinitionFactory(); - } - - @Override - protected String getMapperName(TypeElement type) { - return context.getTypeUtils().getJsonSerializerImplName(type); - } - - @Override - protected void configureClassType(BeanDefinition type) { - cu.addImport(AbstractBeanJsonSerializer.class); - - declaration - .getExtendedTypes() - .add( - new ClassOrInterfaceType() - .setName(AbstractBeanJsonSerializer.class.getSimpleName()) - .setTypeArguments( - new ClassOrInterfaceType() - .setName(type.getElement().getQualifiedName().toString()))); - constructor = declaration.addConstructor(Modifier.Keyword.PUBLIC); - } - - @Override - protected void init(BeanDefinition type) { - logger.branch( - TreeLogger.INFO, "Generating serializer for " + type.getElement().getSimpleName()); - - addStaticInstance(type); - - type.getPropertyDefinitionsAsStream() - .forEach( - propertyDefinition -> { - FieldDefinition fieldDefinition = - fieldDefinitionFactory.getFieldDefinition(propertyDefinition); - addSetter( - type, - constructor.getBody(), - fieldDefinition.getFieldSerializer(propertyDefinition, cu)); - }); - } - - private void addSetter(BeanDefinition type, BlockStmt body, Statement call) { - LambdaExpr lambda = new LambdaExpr(); - lambda.setEnclosingParameters(true); - lambda.getParameters().add(new Parameter().setType(new UnknownType()).setName("bean")); - lambda.getParameters().add(new Parameter().setType(new UnknownType()).setName("generator")); - lambda.getParameters().add(new Parameter().setType(new UnknownType()).setName("ctx")); - - lambda.setBody(call); - - body.addStatement(new MethodCallExpr(new NameExpr("properties"), "add").addArgument(lambda)); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/logger/AbstractTreeLogger.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/logger/AbstractTreeLogger.java deleted file mode 100644 index 45439c740e0..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/logger/AbstractTreeLogger.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright 2007 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.kie.workbench.common.stunner.client.json.mapper.apt.logger; - -import java.util.HashSet; - -import org.kie.workbench.common.stunner.client.json.mapper.apt.exception.UnableToCompleteException; - -/** Abstract base class for TreeLoggers. */ -public abstract class AbstractTreeLogger extends TreeLogger { - - // This message is package-protected so that the unit test can access it. - static final String OUT_OF_MEMORY_MSG = - "Out of memory; to increase the " - + "amount of memory, use the -Xmx flag at startup (java -Xmx128M ...)"; - // This message is package-protected so that the unit test can access it. - static final String STACK_OVERFLOW_MSG = - "Stack overflow; to increase the " - + "stack size, use the -Xss flag at startup (java -Xss1M ...)"; - private final Object nextChildIndexLock = new Object(); - protected Type logLevel = ALL; - protected AbstractTreeLogger parent; - private int indexWithinMyParent; - private int nextChildIndex; - private UncommittedBranchData uncommitted; - - /** The constructor used when creating a top-level logger. */ - protected AbstractTreeLogger() {} - - public static String getStackTraceAsString(Throwable e) { - // Show the exception info for anything other than "UnableToComplete". - if (e == null || e instanceof UnableToCompleteException) { - return null; - } - // For each cause, print the requested number of entries of its stack - // trace, being careful to avoid getting stuck in an infinite loop. - // - StringBuffer message = new StringBuffer(); - Throwable currentCause = e; - String causedBy = ""; - HashSet seenCauses = new HashSet<>(); - while (currentCause != null && !seenCauses.contains(currentCause)) { - seenCauses.add(currentCause); - - message.append(causedBy); - causedBy = "\nCaused by: "; // after 1st, all say "caused by" - message.append(currentCause.getClass().getName()); - message.append(": " + currentCause.getMessage()); - StackTraceElement[] stackElems = currentCause.getStackTrace(); - if (stackElems != null) { - for (int i = 0; i < stackElems.length; ++i) { - message.append("\n\tat "); - message.append(stackElems[i].toString()); - } - } - - currentCause = currentCause.getCause(); - } - return message.toString(); - } - - protected static String getExceptionName(Throwable e) { - if (e == null || e instanceof UnableToCompleteException) { - return null; - } - return e.getClass().getSimpleName(); - } - - /** Implements branching behavior that supports lazy logging for low-priority branched loggers. */ - @Override - public final synchronized TreeLogger branch( - Type type, String msg, Throwable caught, HelpInfo helpInfo) { - - if (msg == null) { - msg = "(Null branch message)"; - } - - // Compute at which index the new child will be placed. - // - int childIndex = allocateNextChildIndex(); - - // The derived class creates the child logger. - AbstractTreeLogger childLogger = doBranch(); - - // Set up the child logger. - // - // Unsynchronized operations on childLogger are safe since no other - // thread could have a reference to it yet. - childLogger.logLevel = logLevel; - - // Take a snapshot of the index that the branched child should have. - // - childLogger.indexWithinMyParent = childIndex; - - // Have the child hang onto this (its parent logger). - // - childLogger.parent = this; - - // We can avoid committing this branch entry until and unless some - // child (or grandchild) tries to log something that is loggable, - // in which case there will be cascading commits of the parent branches. - // - childLogger.uncommitted = new UncommittedBranchData(type, msg, caught, helpInfo); - - // This logic is intertwined with log(). If a log message is associated - // with a special error condition, then we turn it into a branch, - // so this method can be called directly from log(). It is of course - // also possible for someone to call branch() directly. In either case, we - // (1) turn the original message into an ERROR and - // (2) drop an extra log message that explains how to recover - String specialErrorMessage = causedBySpecialError(caught); - if (specialErrorMessage != null) { - type = ERROR; - childLogger.log(type, specialErrorMessage, null); - } - - // Decide whether we want to log the branch message eagerly or lazily. - // - if (isLoggable(type)) { - // We can commit this branch entry eagerly since it is a-priori loggable. - // Commit the parent logger if necessary before continuing. - // - childLogger.commitMyBranchEntryInMyParentLogger(); - } - - return childLogger; - } - - @Override - public final synchronized boolean isLoggable(Type type) { - return !type.isLowerPriorityThan(logLevel); - } - - /** - * Immediately logs or ignores the specified messages, based on the specified message type and - * this logger's settings. If the message is loggable, then parent branches may be lazily created - * before the log can take place. - */ - @Override - public final synchronized void log(Type type, String msg, Throwable caught, HelpInfo helpInfo) { - - if (msg == null) { - msg = "(Null log message)"; - } - - // If this log message is caused by out of memory or stack overflow, we - // provide a little extra help by creating a child log message. - if (causedBySpecialError(caught) != null) { - branch(ERROR, msg, caught); - return; - } - - int childIndex = allocateNextChildIndex(); - if (isLoggable(type)) { - commitMyBranchEntryInMyParentLogger(); - doLog(childIndex, type, msg, caught, helpInfo); - } - } - - public final int getBranchedIndex() { - return indexWithinMyParent; - } - - public final synchronized Type getMaxDetail() { - return logLevel; - } - - /** - * @param type the log type representing the most detailed level of logging that the caller is - * interested in, or null to choose the default level. - */ - public final synchronized void setMaxDetail(Type type) { - if (type == null) { - type = INFO; - } - logLevel = type; - } - - public final AbstractTreeLogger getParentLogger() { - return parent; - } - - @Override - public String toString() { - return getLoggerId(); - } - - protected int allocateNextChildIndex() { - synchronized (nextChildIndexLock) { - // postincrement because we want indices to start at 0 - return nextChildIndex++; - } - } - - /** - * Commits the branch after ensuring that the parent logger (if there is one) has been committed - * first. - */ - protected synchronized void commitMyBranchEntryInMyParentLogger() { - // (Only the root logger doesn't have a parent.) - // - if (parent != null) { - if (uncommitted != null) { - // Commit the parent first. - // - parent.commitMyBranchEntryInMyParentLogger(); - - // Let the subclass do its thing to commit this branch. - // - parent.doCommitBranch( - this, uncommitted.type, uncommitted.message, uncommitted.caught, uncommitted.helpInfo); - - // Release the uncommitted state. - // - uncommitted = null; - } - } - } - - /** Derived classes should override this method to return a branched logger. */ - protected abstract AbstractTreeLogger doBranch(); - - /** - * Derived classes should override this method to actually commit the specified message associated - * with this the root of this branch. - */ - protected abstract void doCommitBranch( - AbstractTreeLogger childBeingCommitted, - Type type, - String msg, - Throwable caught, - HelpInfo helpInfo); - - /** - * Derived classes should override this method to actually write a log message. Note that {@link - * #isLoggable(Type)} will have already been called. - */ - protected abstract void doLog( - int indexOfLogEntryWithinParentLogger, - Type type, - String msg, - Throwable caught, - HelpInfo helpInfo); - - /** - * Scans t and its causes for {@link OutOfMemoryError} or {@link StackOverflowError}. - * - * @param t a possibly null {@link Throwable} - * @return true if {@link OutOfMemoryError} or {@link StackOverflowError} appears anywhere in the - * cause list or if t is an {@link OutOfMemoryError} or {@link - * StackOverflowError} - */ - private String causedBySpecialError(Throwable t) { - while (t != null) { - if (t instanceof OutOfMemoryError) { - return OUT_OF_MEMORY_MSG; - } else if (t instanceof StackOverflowError) { - return STACK_OVERFLOW_MSG; - } - t = t.getCause(); - } - return null; - } - - private String getLoggerId() { - if (parent != null) { - if (parent.parent == null) { - // Top-level - return parent.getLoggerId() + getBranchedIndex(); - } else { - // Nested - return parent.getLoggerId() + "." + getBranchedIndex(); - } - } else { - // The root - return "#"; - } - } - - private static class UncommittedBranchData { - - public final Throwable caught; - public final String message; - public final Type type; - private final HelpInfo helpInfo; - - public UncommittedBranchData(Type type, String message, Throwable caught, HelpInfo helpInfo) { - this.caught = caught; - this.message = message; - this.type = type; - this.helpInfo = helpInfo; - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/logger/PrintWriterTreeLogger.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/logger/PrintWriterTreeLogger.java deleted file mode 100644 index cac2f4571f6..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/logger/PrintWriterTreeLogger.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2006 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.kie.workbench.common.stunner.client.json.mapper.apt.logger; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.net.URL; - -/** Tree logger that logs to a print writer. */ -public final class PrintWriterTreeLogger extends AbstractTreeLogger { - - private final String indent; - - private final PrintWriter out; - - private final Object mutex = new Object(); - - public PrintWriterTreeLogger() { - this(new PrintWriter(System.out, true)); - } - - public PrintWriterTreeLogger(PrintWriter out) { - this(out, ""); - } - - public PrintWriterTreeLogger(File logFile) throws IOException { - boolean existing = logFile.exists(); - this.out = new PrintWriter(new FileWriter(logFile, true), true); - this.indent = ""; - if (existing) { - out.println(); // blank line to mark relaunch - } - } - - protected PrintWriterTreeLogger(PrintWriter out, String indent) { - this.out = out; - this.indent = indent; - } - - @Override - protected AbstractTreeLogger doBranch() { - return new PrintWriterTreeLogger(out, indent + " "); - } - - @Override - protected void doCommitBranch( - AbstractTreeLogger childBeingCommitted, - Type type, - String msg, - Throwable caught, - HelpInfo helpInfo) { - doLog(childBeingCommitted.getBranchedIndex(), type, msg, caught, helpInfo); - } - - @Override - protected void doLog( - int indexOfLogEntryWithinParentLogger, - Type type, - String msg, - Throwable caught, - HelpInfo helpInfo) { - synchronized (mutex) { // ensure thread interleaving... - out.print(indent); - if (type.needsAttention()) { - out.print("["); - out.print(type.getLabel()); - out.print("] "); - } - - out.println(msg); - if (helpInfo != null) { - URL url = helpInfo.getURL(); - if (url != null) { - out.print(indent); - out.println("For additional info see: " + url.toString()); - } - } - if (caught != null) { - caught.printStackTrace(out); - } - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/logger/TreeLogger.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/logger/TreeLogger.java deleted file mode 100644 index 9d8ca280b93..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/logger/TreeLogger.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2008 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package org.kie.workbench.common.stunner.client.json.mapper.apt.logger; - -import java.net.URL; - -/** An interface used to log messages in deferred binding generators. */ -public abstract class TreeLogger { - - /** - * Provides extra information to the user, generally details of what caused the problem or what - * the user should do to fix the problem. How this information is interpreted and displayed is - * implementation-dependent. - */ - public abstract static class HelpInfo { - - /** @return the text to use for an anchor if not null and getURL is non-null. */ - public String getAnchorText() { - return null; - } - - /** @return the prefix to go before the link. */ - public String getPrefix() { - return "More info: "; - } - - /** @return a URL containing extra information about the problem, or null if none. */ - public URL getURL() { - return null; - } - } - - /** A type-safe enum of all possible logging severity types. */ - @SuppressWarnings("hiding") - public enum Type { - - /** Logs an error. */ - ERROR(true), - - /** Logs a warning. */ - WARN(true), - - /** Logs information. */ - INFO(false), - - /** Logs information related to lower-level operation. */ - TRACE(false), - - /** Logs detailed information that could be useful during debugging. */ - DEBUG(false), - - /** - * Logs extremely verbose and detailed information that is typically useful only to product - * implementors. - */ - SPAM(false), - - /** Logs everything -- quite a bit of stuff. */ - ALL(false); - - /** - * Gets all the possible severity types as an array. - * - * @return an array of severity types - */ - public static Type[] instances() { - return Type.values(); - } - - private final boolean needsAttention; - - /** Constructs a log type with an optional parent. */ - Type(boolean needsAttention) { - this.needsAttention = needsAttention; - } - - /** - * Gets the label for this severity type. - * - * @return the label - */ - public String getLabel() { - return this.toString(); - } - - /** - * Determines whether this log type is of lower priority than some other log type. - * - * @param other the other log type - * @return true if this log type is lower priority - */ - public boolean isLowerPriorityThan(Type other) { - // Counterintuitive: higher number is lower priority. - return this.ordinal() > other.ordinal(); - } - - /** - * Indicates whether this severity type represents a high severity that should be highlighted - * for the user. - * - * @return true if this severity is high, otherwise false. - */ - public boolean needsAttention() { - return needsAttention; - } - } - - /** Logs an error. */ - public static final Type ERROR = Type.ERROR; - - /** Logs a warning. */ - public static final Type WARN = Type.WARN; - - /** Logs information. */ - public static final Type INFO = Type.INFO; - - /** Logs information related to lower-level operation. */ - public static final Type TRACE = Type.TRACE; - - /** Logs detailed information that could be useful during debugging. */ - public static final Type DEBUG = Type.DEBUG; - - /** - * Logs extremely verbose and detailed information that is typically useful only to product - * implementors. - */ - public static final Type SPAM = Type.SPAM; - - /** Logs everything -- quite a bit of stuff. */ - public static final Type ALL = Type.ALL; - - /** - * A valid logger that ignores all messages. Occasionally useful when calling methods that require - * a logger parameter. - */ - public static final TreeLogger NULL = - new TreeLogger() { - @Override - public TreeLogger branch(Type type, String msg, Throwable caught, HelpInfo helpInfo) { - return this; - } - - @Override - public boolean isLoggable(Type type) { - return false; - } - - @Override - public void log(Type type, String msg, Throwable caught, HelpInfo helpInfo) { - // nothing - } - }; - - /** - * Calls {@link #branch(Type, String, Throwable, HelpInfo)} with a - * null caught and helpInfo. - */ - public final TreeLogger branch(Type type, String msg) { - return branch(type, msg, null, null); - } - - /** - * Calls {@link #branch(Type, String, Throwable, HelpInfo)} with a - * null helpInfo. - */ - public final TreeLogger branch(Type type, String msg, Throwable caught) { - return branch(type, msg, caught, null); - } - - /** - * Produces a branched logger, which can be used to write messages that are logically grouped - * together underneath the current logger. The details of how/if the resulting messages are - * displayed is implementation-dependent. - * - *

    The log message supplied when branching serves two purposes. First, the message should be - * considered a heading for all the child messages below it. Second, the type of the - * message provides a hint as to the importance of the children below it. As an optimization, an - * implementation could return a "no-op" logger if messages of the specified type weren't being - * logged, which the implication being that all nested log messages were no more important than - * the level of their branch parent. - * - *

    As an example of how hierarchical logging can be used, a branched logger in a GUI could - * write log message as child items of a parent node in a tree control. If logging to streams, - * such as a text console, the branched logger could prefix each entry with a unique string and - * indent its text so that it could be sorted later to reconstruct a proper hierarchy. - * - * @param type - * @param msg an optional message to log, which can be null if only an exception is - * being logged - * @param caught an optional exception to log, which can be null if only a message is - * being logged - * @param helpInfo extra information that might be used by the logger to provide extended - * information to the user - * @return an instance of {@link TreeLogger} representing the new branch of the log; may be the - * same instance on which this method is called - */ - public abstract TreeLogger branch(Type type, String msg, Throwable caught, HelpInfo helpInfo); - - /** - * Determines whether or not a log entry of the specified type would actually be logged. Caller - * use this method to avoid constructing log messages that would be thrown away. - */ - public abstract boolean isLoggable(Type type); - - /** - * Calls {@link #log(Type, String, Throwable, HelpInfo)} with a null caught - * and helpInfo. - */ - public final void log(Type type, String msg) { - log(type, msg, null, null); - } - - /** - * Calls {@link #log(Type, String, Throwable, HelpInfo)} with a null helpInfo - * . - */ - public final void log(Type type, String msg, Throwable caught) { - log(type, msg, caught, null); - } - - /** - * Logs a message and/or an exception, with optional help info. It is also legal to call this - * method using null arguments for both msg and caught - * , in which case the log event can be ignored. The info can provide extra - * information to the logger; a logger may choose to ignore this info. - * - * @param type - * @param msg an optional message to log, which can be null if only an exception is - * being logged - * @param caught an optional exception to log, which can be null if only a message is - * being logged - * @param helpInfo extra information that might be used by the logger to provide extended - * information to the user - */ - public abstract void log(Type type, String msg, Throwable caught, HelpInfo helpInfo); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/processor/BeanProcessor.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/processor/BeanProcessor.java deleted file mode 100644 index b80925248d8..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/processor/BeanProcessor.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.apt.processor; - -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementFilter; - -import com.google.auto.common.MoreTypes; -import jakarta.json.bind.annotation.JsonbTransient; -import jakarta.json.bind.annotation.JsonbTypeInfo; -import org.kie.workbench.common.stunner.client.json.mapper.annotation.JSONMapper; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.apt.exception.GenerationException; -import org.kie.workbench.common.stunner.client.json.mapper.apt.generator.MapperGenerator; -import org.kie.workbench.common.stunner.client.json.mapper.apt.logger.TreeLogger; -import org.kie.workbench.common.stunner.client.json.mapper.apt.utils.TypeUtils; - -public class BeanProcessor { - - private final GenerationContext context; - private final TreeLogger logger; - private final Set annotatedBeans; - private final Set beans = new HashSet<>(); - - private final TypeUtils typeUtils; - - private final MapperGenerator mapperGenerator; - - private TypeMirror objectType; - - public BeanProcessor(GenerationContext context, TreeLogger logger, Set beans) { - this.context = context; - this.logger = logger; - this.annotatedBeans = beans; - this.typeUtils = context.getTypeUtils(); - this.mapperGenerator = new MapperGenerator(context, logger); - - this.objectType = - context - .getProcessingEnv() - .getElementUtils() - .getTypeElement(Object.class.getCanonicalName()) - .asType(); - } - - public void process() { - annotatedBeans.forEach(this::processBean); - beans.forEach(context::addBeanDefinition); - - context.getBeans().stream() - .filter(bean -> !bean.getElement().getModifiers().contains(Modifier.ABSTRACT)) - .forEach(mapperGenerator::generate); - } - - private void processBean(TypeElement bean) { - if (!beans.contains(bean)) { - beans.add(checkBean(bean)); - if (!context.getTypeUtils().isJsonbTypeSerializer(bean)) { - context.getTypeUtils().getAllFieldsIn(bean).forEach(this::processField); - } - } - } - - private void processField(VariableElement field) { - if (checkField(field)) { - if (!context.getTypeUtils().isJsonbTypeSerializer(field)) { - TypeMirror typeMirror = field.asType(); - checkTypeAndAdd(typeMirror); - } - } - } - - private void checkTypeAndAdd(TypeMirror type) { - if (type.getKind().isPrimitive() || typeUtils.isBoxedTypeOrString(type)) { - return; - } - - if (type.getKind().equals(TypeKind.ARRAY)) { - ArrayType arrayType = (ArrayType) type; - if (!context.getTypeUtils().isSimpleType(arrayType.getComponentType())) { - if (!MoreTypes.asElement(arrayType.getComponentType()).getKind().equals(ElementKind.ENUM) - && !context.getTypeUtils().isJsonbTypeSerializer(arrayType.getComponentType())) { - processBean(MoreTypes.asTypeElement(arrayType.getComponentType())); - } - } - } else if (MoreTypes.asElement(type).getKind().equals(ElementKind.ENUM)) { - return; - } else if (context.getTypeUtils().isAssignableFrom(type, Map.class)) { - DeclaredType collection = (DeclaredType) type; - collection.getTypeArguments().forEach(this::checkTypeAndAdd); - } else if (context.getTypeUtils().isAssignableFrom(type, Collection.class)) { - DeclaredType collection = (DeclaredType) type; - collection.getTypeArguments().stream() - .filter(e -> !context.getTypeUtils().isJsonbTypeSerializer(e)) - .forEach(this::checkTypeAndAdd); - } else if (context.getTypeUtils().isAssignableFrom(type, Iterable.class)) { - DeclaredType collection = (DeclaredType) type; - collection.getTypeArguments().stream() - .filter(e -> !context.getTypeUtils().isJsonbTypeSerializer(e)) - .forEach(this::checkTypeAndAdd); - } else if (!beans.contains(context.getProcessingEnv().getTypeUtils().erasure(type))) { - processBean(MoreTypes.asTypeElement(context.getProcessingEnv().getTypeUtils().erasure(type))); - } else if (type.getKind().equals(TypeKind.ARRAY)) { - ArrayType arrayType = (ArrayType) type; - TypeElement typeElement = MoreTypes.asTypeElement(arrayType.getComponentType()); - if (!context.getTypeUtils().isJsonbTypeSerializer(typeElement)) { - processBean(typeElement); - } - } else if (MoreTypes.isType(type) - && !MoreTypes.asElement(type).getKind().equals(ElementKind.ENUM) - && !context.getTypeUtils().isJsonbTypeSerializer(type)) { - processBean(MoreTypes.asTypeElement(type)); - } - } - - private boolean checkField(VariableElement field) { - if (field.getModifiers().contains(Modifier.STATIC) - || field.getModifiers().contains(Modifier.TRANSIENT) - || field.getAnnotation(JsonbTransient.class) != null - || field.getModifiers().contains(Modifier.FINAL)) { - return false; - } - - if (context.getProcessingEnv().getTypeUtils().isSameType(field.asType(), objectType)) { - if (!context.getTypeUtils().isJsonbTypeSerializer(field)) { - throw new GenerationException( - String.format( - "Field %s.%s is of type Object and must be annotated with @JsonbTypeSerializer and @JsonbTypeDeserializer", - field.getEnclosingElement().getSimpleName(), field.getSimpleName().toString())); - } - } - - if (!field.getModifiers().contains(Modifier.PRIVATE) - || typeUtils.hasGetter(field) && typeUtils.hasSetter(field)) { - return true; - } - - if (!typeUtils.hasGetter(field)) { - throw new GenerationException( - String.format( - "Unable to find suitable getter for [%s] in [%s].", - field.getSimpleName(), field.getEnclosingElement())); - } - - if (!typeUtils.hasSetter(field)) { - throw new GenerationException( - String.format( - "Unable to find suitable setter for [%s] in [%s]", - field.getSimpleName(), field.getEnclosingElement())); - } - - throw new GenerationException( - String.format( - "Unable to process [%s] in [%s]", field.getSimpleName(), field.getEnclosingElement())); - } - - private TypeElement checkBean(TypeElement type) { - if (!type.getKind().isClass() - && type.getAnnotation(JsonbTypeInfo.class) == null - && !context.getTypeUtils().isJsonbTypeSerializer(type)) { - throw new GenerationException( - "A @JSONMapper bean [" - + type - + "] must be class or has @JsonbTypeSerializer and @JsonbTypeDeserializer"); - } - - if (type.getModifiers().contains(Modifier.ABSTRACT) - && type.getAnnotation(JsonbTypeInfo.class) == null - && !context.getTypeUtils().isJsonbTypeSerializer(type)) { - throw new GenerationException( - "A @JSONMapper bean [" - + type - + "] must be non abstract or has @JsonbTypeSerializer and @JsonbTypeDeserializer"); - } - - if (type.getModifiers().contains(Modifier.PRIVATE)) { - throw new GenerationException("A @JSONMapper bean [" + type + "] must be public"); - } - - if (type.getModifiers().contains(Modifier.STATIC) - && type.getEnclosingElement().getKind().equals(ElementKind.PACKAGE)) { - throw new GenerationException("A @JSONMapper bean [" + type + "] must not be static"); - } - - if (!type.getModifiers().contains(Modifier.STATIC) - && !type.getEnclosingElement().getKind().equals(ElementKind.PACKAGE)) { - throw new GenerationException( - "If @JSONMapper bean [" + type + "] is a inner class, it must be static"); - } - - if (context.getTypeUtils().isJsonbTypeSerializer(type) - && type.getAnnotation(JSONMapper.class) != null) { - throw new GenerationException( - "A @JSONMapper bean [" - + type - + "] must not be annotated with JsonbTypeSerializer or JsonbTypeDeserializer"); - } - - List constructors = ElementFilter.constructorsIn(type.getEnclosedElements()); - if (!constructors.isEmpty()) { - long nonArgConstructorCount = - constructors.stream() - .filter(constr -> !constr.getModifiers().contains(Modifier.PRIVATE)) - .filter(constr -> constr.getParameters().isEmpty()) - .count(); - if (nonArgConstructorCount != 1) { - throw new GenerationException( - "A @JSONMapper bean [" + type + "] must have a non-private non-arg constructor"); - } - } - return type; - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/utils/TypeRegistry.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/utils/TypeRegistry.java deleted file mode 100644 index 9b55ff9a8a6..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/utils/TypeRegistry.java +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.apt.utils; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; - -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; - -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.apt.exception.TypeDeserializerNotFoundException; -import org.kie.workbench.common.stunner.client.json.mapper.apt.exception.TypeMapperNotFoundException; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BooleanJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.CharacterJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.EnumJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.StringJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array.PrimitiveBooleanArrayJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array.PrimitiveByteArrayJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array.PrimitiveCharacterArrayJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array.PrimitiveDoubleArrayJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array.PrimitiveFloatArrayJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array.PrimitiveIntegerArrayJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array.PrimitiveLongArrayJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array.PrimitiveShortArrayJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.array.StringArrayJsonDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection.ArrayListDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection.HashSetDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection.LinkedHashSetDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection.LinkedListDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection.ListDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.collection.SortedSetDeserializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BooleanJsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.CharacterJsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.EnumJsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.StringJsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array.PrimitiveBooleanArrayJsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array.PrimitiveByteArrayJsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array.PrimitiveCharacterArrayJsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array.PrimitiveDoubleArrayJsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array.PrimitiveFloatArrayJsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array.PrimitiveIntegerArrayJsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array.PrimitiveLongArrayLongSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.array.PrimitiveShortArrayJsonSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.collection.CollectionJsonSerializer; - -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.BigDecimalJsonDeserializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.BigIntegerJsonDeserializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.ByteJsonDeserializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.DoubleJsonDeserializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.FloatJsonDeserializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.IntegerJsonDeserializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.LongJsonDeserializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.deserializer.BaseNumberJsonDeserializer.ShortJsonDeserializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer.BigDecimalJsonSerializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer.BigIntegerJsonSerializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer.ByteJsonSerializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer.DoubleJsonSerializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer.FloatJsonSerializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer.IntegerJsonSerializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer.LongJsonSerializer; -import static org.kie.workbench.common.stunner.client.json.mapper.internal.serializer.BaseNumberJsonSerializer.ShortJsonSerializer; - -public class TypeRegistry { - private final ClassMapperFactory MAPPER = new ClassMapperFactory(); - - private Map buildIn = new HashMap<>(); - private final Types types; - private final Elements elements; - private final GenerationContext context; - - public TypeRegistry(GenerationContext context) { - this.types = context.getProcessingEnv().getTypeUtils(); - this.elements = context.getProcessingEnv().getElementUtils(); - this.context = context; - - initBasicMappers(); - initCommonMappers(); - initNumberMappers(); - initPrimitiveArraysMappers(); - initCollections(); - } - - public TypeElement getSerializer(TypeMirror typeMirror) { - return getSerializer(typeMirror.toString()); - } - - public TypeElement getSerializer(String typeName) { - if (buildIn.containsKey(typeName)) { - return get(typeName).serializer; - } - throw new TypeDeserializerNotFoundException(typeName); - } - - public TypeElement getDeserializer(TypeMirror typeMirror) { - return getDeserializer(typeMirror.toString()); - } - - public TypeElement getDeserializer(String typeName) { - if (buildIn.containsKey(typeName)) { - return get(typeName).deserializer; - } - throw new TypeDeserializerNotFoundException(typeName); - } - - public boolean has(TypeMirror typeMirror) { - return buildIn.containsKey(typeMirror.toString()); - } - - public ClassMapper get(String typeName) { - if (buildIn.containsKey(typeName)) { - return buildIn.get(typeName); - } - throw new TypeMapperNotFoundException(typeName); - } - - private void initBasicMappers() { - MAPPER - .forType(boolean.class) - // .serializer(BooleanJsonSerializer.class) - .deserializer(BooleanJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(char.class) - // .serializer(CharacterJsonSerializer.class) - .deserializer(CharacterJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(byte.class) - // .serializer(ByteJsonSerializer.class) - .deserializer(ByteJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(double.class) - // .serializer(DoubleJsonSerializer.class) - .deserializer(DoubleJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(float.class) - // .serializer(FloatJsonSerializer.class) - .deserializer(FloatJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(int.class) - // .serializer(IntegerJsonSerializer.class) - .deserializer(IntegerJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(long.class) - // .serializer(LongJsonSerializer.class) - .deserializer(LongJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(short.class) - // .serializer(ShortJsonSerializer.class) - .deserializer(ShortJsonDeserializer.class) - .register(buildIn); - } - - private void initCommonMappers() { - // Common mappers - MAPPER - .forType(String.class) - .serializer(StringJsonSerializer.class) - .deserializer(StringJsonDeserializer.class) - .register(buildIn); - MAPPER - .forType(Boolean.class) - .serializer(BooleanJsonSerializer.class) - .deserializer(BooleanJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(Character.class) - .serializer(CharacterJsonSerializer.class) - .deserializer(CharacterJsonDeserializer.class) - .register(buildIn); - - /* MAPPER - .forType(UUID.class) - .serializer(UUIDJsonSerializer.class) - .deserializer(UUIDJsonDeserializer.class) - .register(buildIn); - */ - MAPPER - .forType(Enum.class) - .serializer(EnumJsonSerializer.class) - .deserializer(EnumJsonDeserializer.class) - .register(buildIn); - } - - private void initNumberMappers() { - MAPPER - .forType(BigDecimal.class) - .serializer(BigDecimalJsonSerializer.class) - .deserializer(BigDecimalJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(BigInteger.class) - .serializer(BigIntegerJsonSerializer.class) - .deserializer(BigIntegerJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(Byte.class) - .serializer(ByteJsonSerializer.class) - .deserializer(ByteJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(Double.class) - .serializer(DoubleJsonSerializer.class) - .deserializer(DoubleJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(Float.class) - .serializer(FloatJsonSerializer.class) - .deserializer(FloatJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(Integer.class) - .serializer(IntegerJsonSerializer.class) - .deserializer(IntegerJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(Long.class) - .serializer(LongJsonSerializer.class) - .deserializer(LongJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(Short.class) - .serializer(ShortJsonSerializer.class) - .deserializer(ShortJsonDeserializer.class) - .register(buildIn); - } - - private void initPrimitiveArraysMappers() { - MAPPER - .forType(boolean[].class) - .serializer(PrimitiveBooleanArrayJsonSerializer.class) - .deserializer(PrimitiveBooleanArrayJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(byte[].class) - .serializer(PrimitiveByteArrayJsonSerializer.class) - .deserializer(PrimitiveByteArrayJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(char[].class) - .serializer(PrimitiveCharacterArrayJsonSerializer.class) - .deserializer(PrimitiveCharacterArrayJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(double[].class) - .serializer(PrimitiveDoubleArrayJsonSerializer.class) - .deserializer(PrimitiveDoubleArrayJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(float[].class) - .serializer(PrimitiveFloatArrayJsonSerializer.class) - .deserializer(PrimitiveFloatArrayJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(int[].class) - .serializer(PrimitiveIntegerArrayJsonSerializer.class) - .deserializer(PrimitiveIntegerArrayJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(long[].class) - .serializer(PrimitiveLongArrayLongSerializer.class) - .deserializer(PrimitiveLongArrayJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(short[].class) - .serializer(PrimitiveShortArrayJsonSerializer.class) - .deserializer(PrimitiveShortArrayJsonDeserializer.class) - .register(buildIn); - - MAPPER - .forType(String[].class) - .serializer(PrimitiveShortArrayJsonSerializer.class) - .deserializer(StringArrayJsonDeserializer.class) - .register(buildIn); - } - - private void initCollections() { - MAPPER - .forType(List.class) - .serializer(CollectionJsonSerializer.class) - .deserializer(ListDeserializer.class) - .register(buildIn); - - MAPPER - .forType(ArrayList.class) - .serializer(CollectionJsonSerializer.class) - .deserializer(ArrayListDeserializer.class) - .register(buildIn); - - MAPPER - .forType(LinkedList.class) - .serializer(CollectionJsonSerializer.class) - .deserializer(LinkedListDeserializer.class) - .register(buildIn); - - MAPPER - .forType(Set.class) - .serializer(CollectionJsonSerializer.class) - .deserializer(HashSetDeserializer.class) - .register(buildIn); - MAPPER - .forType(SortedSet.class) - .serializer(CollectionJsonSerializer.class) - .deserializer(SortedSetDeserializer.class) - .register(buildIn); - - MAPPER - .forType(HashSet.class) - .serializer(CollectionJsonSerializer.class) - .deserializer(HashSetDeserializer.class) - .register(buildIn); - - MAPPER - .forType(LinkedHashSet.class) - .serializer(CollectionJsonSerializer.class) - .deserializer(LinkedHashSetDeserializer.class) - .register(buildIn); - MAPPER - .forType(TreeSet.class) - .serializer(CollectionJsonSerializer.class) - .deserializer(SortedSetDeserializer.class) - .register(buildIn); - } - - class ClassMapperFactory { - - ClassMapper forType(Class clazz) { - return new ClassMapper(clazz); - } - } - - public class ClassMapper { - - private final String clazz; - - private TypeElement serializer; - - private TypeElement deserializer; - - private ClassMapper(Class clazz) { - this.clazz = clazz.getCanonicalName(); - } - - private ClassMapper(String type) { - this.clazz = type; - } - - private ClassMapper serializer(Class serializer) { - this.serializer = elements.getTypeElement(serializer.getCanonicalName()); - return this; - } - - private ClassMapper deserializer(Class deserializer) { - this.deserializer = elements.getTypeElement(deserializer.getCanonicalName()); - return this; - } - - private ClassMapper register(Map registry) { - registry.put(this.clazz, this); - return this; - } - - @Override - public String toString() { - return "ClassMapper{" + "clazz='" + clazz + '\'' + ", serializer=" + serializer != null - ? serializer.toString() - : "" + ", deserializer=" + deserializer != null ? deserializer.toString() : "" + '}'; - } - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/utils/TypeUtils.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/utils/TypeUtils.java deleted file mode 100644 index e3fcb74327e..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/json/processor/src/main/java/org/kie/workbench/common/stunner/client/json/mapper/apt/utils/TypeUtils.java +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.kie.workbench.common.stunner.client.json.mapper.apt.utils; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Deque; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.ArrayType; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.PrimitiveType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementFilter; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; - -import com.github.javaparser.ast.CompilationUnit; -import com.google.auto.common.MoreElements; -import com.google.auto.common.MoreTypes; -import jakarta.json.bind.annotation.JsonbTypeDeserializer; -import jakarta.json.bind.annotation.JsonbTypeSerializer; -import org.kie.workbench.common.stunner.client.json.mapper.apt.context.GenerationContext; -import org.kie.workbench.common.stunner.client.json.mapper.apt.exception.GenerationException; - -public class TypeUtils { - - private final Types types; - private final Elements elements; - - private final BoxedTypes boxedTypes; - - private final GenerationContext context; - - public TypeUtils(GenerationContext context) { - this.types = context.getProcessingEnv().getTypeUtils(); - this.elements = context.getProcessingEnv().getElementUtils(); - this.boxedTypes = new BoxedTypes(); - this.context = context; - } - - public BoxedTypes getBoxedTypes() { - return boxedTypes; - } - - public Collection getAllFieldsIn(TypeElement type) { - Map fields = new LinkedHashMap<>(); - ElementFilter.fieldsIn(type.getEnclosedElements()) - .forEach(field -> fields.put(field.getSimpleName().toString(), field)); - - List alltypes = getSuperTypes(elements, type); - for (TypeElement atype : alltypes) { - ElementFilter.fieldsIn(atype.getEnclosedElements()).stream() - .filter(field -> !fields.containsKey(field.getSimpleName().toString())) - .forEach(field -> fields.put(field.getSimpleName().toString(), field)); - } - return fields.values(); - } - - /** - * see: typetools/checker-framework Determine all type elements for the classes and interfaces - * referenced in the extends/implements clauses of the given type element. TODO: can we learn from - * the implementation of com.sun.tools.javac.model.JavacElements.getAllMembers(TypeElement)? - */ - public List getSuperTypes(Elements elements, TypeElement type) { - - List superelems = new ArrayList<>(); - if (type == null) { - return superelems; - } - - // Set up a stack containing type, which is our starting point. - Deque stack = new ArrayDeque<>(); - stack.push(type); - - while (!stack.isEmpty()) { - TypeElement current = stack.pop(); - - // For each direct supertype of the current type element, if it - // hasn't already been visited, push it onto the stack and - // add it to our superelems set. - TypeMirror supertypecls = current.getSuperclass(); - if (supertypecls.getKind() != TypeKind.NONE) { - TypeElement supercls = (TypeElement) ((DeclaredType) supertypecls).asElement(); - if (!superelems.contains(supercls)) { - stack.push(supercls); - superelems.add(supercls); - } - } - for (TypeMirror supertypeitf : current.getInterfaces()) { - TypeElement superitf = (TypeElement) ((DeclaredType) supertypeitf).asElement(); - if (!superelems.contains(superitf)) { - stack.push(superitf); - superelems.add(superitf); - } - } - } - - // Include java.lang.Object as implicit superclass for all classes and interfaces. - TypeElement jlobject = elements.getTypeElement(Object.class.getCanonicalName()); - if (!superelems.contains(jlobject)) { - superelems.add(jlobject); - } - - return Collections.unmodifiableList(superelems); - } - - public boolean hasGetter(VariableElement variable) { - return getGetter(variable) != null; - } - - public ExecutableElement getGetter(VariableElement variable) { - List method = compileGetterMethodName(variable); - return MoreElements.asType(variable.getEnclosingElement()).getEnclosedElements().stream() - .filter(e -> e.getKind().equals(ElementKind.METHOD)) - .filter(e -> method.contains(e.getSimpleName().toString())) - .filter(e -> !e.getModifiers().contains(Modifier.PRIVATE)) - .filter(e -> !e.getModifiers().contains(Modifier.STATIC)) - .map(MoreElements::asExecutable) - .filter(elm -> elm.getParameters().isEmpty()) - .filter(elm -> types.isSameType(elm.getReturnType(), variable.asType())) - .findFirst() - .orElseThrow( - () -> - new GenerationException( - String.format( - "Unable to find suitable getter for %s.%s", - variable.getEnclosingElement(), variable.getSimpleName()))); - } - - public List compileGetterMethodName(VariableElement variable) { - String varName = variable.getSimpleName().toString(); - boolean isBoolean = isBoolean(variable); - List result = new ArrayList<>(); - result.add("get" + capitalize(varName)); - if (isBoolean) { - result.add("is" + capitalize(varName)); - } - return result; - } - - public boolean hasSetter(VariableElement variable) { - return getSetter(variable) != null; - } - - public ExecutableElement getSetter(VariableElement variable) { - String method = compileSetterMethodName(variable); - return MoreElements.asType(variable.getEnclosingElement()).getEnclosedElements().stream() - .filter(e -> e.getKind().equals(ElementKind.METHOD)) - .filter(e -> e.toString().equals(method)) - .filter(e -> !e.getModifiers().contains(Modifier.PRIVATE)) - .filter(e -> !e.getModifiers().contains(Modifier.STATIC)) - .map(MoreElements::asExecutable) - .filter(elm -> elm.getParameters().size() == 1) - .filter(elm -> types.isSameType(elm.getParameters().get(0).asType(), variable.asType())) - .findFirst() - .orElseThrow( - () -> - new GenerationException( - String.format( - "Unable to find suitable setter for %s.%s", - variable.getEnclosingElement(), variable.getSimpleName()))); - } - - private String compileSetterMethodName(VariableElement variable) { - String varName = variable.getSimpleName().toString(); - StringBuffer sb = new StringBuffer(); - sb.append("set"); - sb.append(capitalize(varName)); - sb.append("("); - sb.append(variable.asType()); - sb.append(")"); - return sb.toString(); - } - - public boolean isBoxedType(TypeMirror type) { - return boxedTypes.isBoxedType(type); - } - - public boolean isBoxedTypeOrString(TypeMirror type) { - return boxedTypes.isBoxedType(type) || boxedTypes.isString(type); - } - - public boolean isBoolean(VariableElement variable) { - return variable.asType().getKind().equals(TypeKind.BOOLEAN) - || variable.asType().toString().equals(Boolean.class.getCanonicalName()); - } - - public boolean isAssignableFrom(TypeMirror typeMirror, Class targetClass) { - return types.isAssignable( - typeMirror, types.getDeclaredType(elements.getTypeElement(targetClass.getCanonicalName()))); - } - - public boolean isSimpleType(TypeMirror property) { - return property.getKind().isPrimitive() || isBoxedTypeOrString(property); - } - - private static final String BEAN_JSON_SERIALIZER_IMPL = "_JsonSerializerImpl"; - - private static final String BEAN_JSON_DESERIALIZER_IMPL = "_JsonDeserializerImpl"; - - public String getJsonSerializerImplQualifiedName(VariableElement variable) { - return getJsonSerializerImplQualifiedName(MoreTypes.asTypeElement(variable.asType())); - } - - public String getJsonSerializerImplQualifiedName(TypeElement type) { - return elements.getPackageOf(type) + "." + getJsonSerializerImplName(type); - } - - public String getJsonSerializerImplName(TypeElement type) { - return (type.getEnclosingElement().getKind().equals(ElementKind.PACKAGE) - ? "" - : MoreElements.asType(type.getEnclosingElement()).getSimpleName().toString() + "_") - + type.getSimpleName() - + BEAN_JSON_SERIALIZER_IMPL; - } - - public String getJsonDeserializerImplQualifiedName(TypeElement type, CompilationUnit cu) { - return elements.getPackageOf(type) + "." + getJsonDeserializerImplName(type); - } - - public String getJsonDeserializerImplName(TypeElement type) { - return (type.getEnclosingElement().getKind().equals(ElementKind.PACKAGE) - ? "" - : MoreElements.asType(type.getEnclosingElement()).getSimpleName().toString() + "_") - + type.getSimpleName() - + BEAN_JSON_DESERIALIZER_IMPL; - } - - public boolean isIterable(TypeMirror property) { - return !property.getKind().isPrimitive() && isAssignableFrom(property, Iterable.class); - } - - public boolean isJsonbTypeSerializer(VariableElement type) { - boolean isFieldAnnotated = - type.getAnnotation(JsonbTypeSerializer.class) != null - && type.getAnnotation(JsonbTypeDeserializer.class) != null; - if (isFieldAnnotated) { - return true; - } - - return isJsonbTypeSerializer(type.asType()); - } - - public boolean isJsonbTypeSerializer(Element type) { - if (type.getKind().isField()) { - VariableElement field = MoreElements.asVariable(type); - TypeMirror typeMirror = field.asType(); - if (typeMirror.getKind().isPrimitive()) { - return false; - } - if (!typeMirror.getKind().equals(TypeKind.ARRAY)) { - boolean hasJsonbTypeSerializer = isJsonbTypeSerializer(typeMirror); - if (hasJsonbTypeSerializer) { - return true; - } - } - } - return type.getAnnotation(JsonbTypeSerializer.class) != null - && type.getAnnotation(JsonbTypeDeserializer.class) != null; - } - - public boolean isJsonbTypeSerializer(TypeMirror mirror) { - if (mirror.getKind().isPrimitive()) { - return false; - } else if (mirror.getKind().equals(TypeKind.ARRAY)) { - ArrayType arrayType = (ArrayType) mirror; - if (arrayType.getComponentType().getKind().isPrimitive()) { - return false; - } - if (MoreTypes.asElement(arrayType.getComponentType()).getKind().equals(ElementKind.ENUM)) { - return false; - } - return isJsonbTypeSerializer(arrayType.getComponentType()); - } else if (isIterable(mirror)) { - boolean hasJsonbTypeSerializer = - isJsonbTypeSerializer(MoreTypes.asDeclared(mirror).getTypeArguments().get(0)); - if (hasJsonbTypeSerializer) { - return true; - } - } - return isJsonbTypeSerializer(MoreTypes.asElement(mirror)); - } - - public class BoxedTypes { - - private Set boxedTypes = new HashSet<>(); - - private BoxedTypes() { - - boxedTypes.add(asBoxedType(TypeKind.BOOLEAN)); - boxedTypes.add(asBoxedType(TypeKind.BYTE)); - boxedTypes.add(asBoxedType(TypeKind.CHAR)); - boxedTypes.add(asBoxedType(TypeKind.DOUBLE)); - boxedTypes.add(asBoxedType(TypeKind.FLOAT)); - boxedTypes.add(asBoxedType(TypeKind.INT)); - boxedTypes.add(asBoxedType(TypeKind.LONG)); - boxedTypes.add(asBoxedType(TypeKind.SHORT)); - } - - boolean isBoxedType(TypeMirror type) { - return boxedTypes.stream().filter(t -> types.isSameType(t, type)).findAny().isPresent(); - } - - public boolean isBoolean(TypeMirror type) { - if (type.getKind().equals(TypeKind.BOOLEAN)) { - return true; - } - return types.isSameType(asBoxedType(TypeKind.BOOLEAN), type); - } - - public boolean isByte(TypeMirror type) { - if (type.getKind().equals(TypeKind.BYTE)) { - return true; - } - return types.isSameType(asBoxedType(TypeKind.BYTE), type); - } - - public boolean isChar(TypeMirror type) { - if (type.getKind().equals(TypeKind.CHAR)) { - return true; - } - return types.isSameType(asBoxedType(TypeKind.CHAR), type); - } - - public boolean isDouble(TypeMirror type) { - if (type.getKind().equals(TypeKind.DOUBLE)) { - return true; - } - return types.isSameType(asBoxedType(TypeKind.DOUBLE), type); - } - - public boolean isFloat(TypeMirror type) { - if (type.getKind().equals(TypeKind.FLOAT)) { - return true; - } - return types.isSameType(asBoxedType(TypeKind.FLOAT), type); - } - - public boolean isInt(TypeMirror type) { - if (type.getKind().equals(TypeKind.INT)) { - return true; - } - return types.isSameType(asBoxedType(TypeKind.INT), type); - } - - public boolean isLong(TypeMirror type) { - if (type.getKind().equals(TypeKind.LONG)) { - return true; - } - return types.isSameType(asBoxedType(TypeKind.LONG), type); - } - - public boolean isShort(TypeMirror type) { - if (type.getKind().equals(TypeKind.SHORT)) { - return true; - } - return types.isSameType(asBoxedType(TypeKind.SHORT), type); - } - - public boolean isString(TypeMirror type) { - TypeMirror string = elements.getTypeElement(String.class.getCanonicalName()).asType(); - return types.isSameType(type, string); - } - - private TypeMirror asBoxedType(TypeKind type) { - PrimitiveType primitive = types.getPrimitiveType(type); - return types.boxedClass(primitive).asType(); - } - } - - private String capitalize(String name) { - return name.substring(0, 1).toUpperCase() + name.substring(1); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/pom.xml b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/pom.xml deleted file mode 100644 index df460398005..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/pom.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - tooling-parent - org.kie.kogito.stunner.serverless.editor.third_party.tooling - ${revision} - - 4.0.0 - pom - - json - yaml - - - marshalling-parent - org.kie.kogito.stunner.serverless.editor.third_party.tooling.marshalling - - GWT/J2CL marshallers parent - GWT/J2CL marshallers parent - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/pom.xml b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/pom.xml deleted file mode 100644 index 88ef142f18e..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/pom.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - 4.0.0 - - org.kie.kogito.stunner.serverless.editor.third_party.tooling.marshalling.yaml - parent - ${revision} - - - common - jar - - GWT/J2CL YAML Binding commons - GWT/J2CL YAML Binding commons - - - - com.google.jsinterop - base - - - com.google.elemental2 - elemental2-dom - - - org.kie.kogito.stunner.serverless.editor.third_party.tooling.marshalling.yaml - snakeyaml-engine - - - - - - - src/main/java - - **/*.java - - - - src/main/resources - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - package - - jar - - - - - - - - diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/AbstractObjectMapper.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/AbstractObjectMapper.java deleted file mode 100644 index 2f582a928c7..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/AbstractObjectMapper.java +++ /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 org.kie.workbench.common.stunner.client.yaml.mapper.api; - -import java.io.IOException; - -import org.kie.workbench.common.stunner.client.yaml.mapper.api.exception.YAMLDeserializationException; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.exception.YAMLSerializationException; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.internal.deser.DefaultYAMLDeserializationContext; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.internal.deser.YAMLDeserializationContext; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.internal.deser.bean.AbstractBeanYAMLDeserializer; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.internal.ser.YAMLSerializationContext; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.internal.ser.bean.AbstractBeanYAMLSerializer; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.node.YamlMapping; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.node.impl.Yaml; -import org.snakeyaml.engine.v2.api.DumpSettings; -import org.snakeyaml.engine.v2.common.FlowStyle; - -public abstract class AbstractObjectMapper { - - private YAMLDeserializer deserializer; - - private YAMLSerializer serializer; - - public T read(String in) throws YAMLDeserializationException, IOException { - YAMLDeserializationContext context = DefaultYAMLDeserializationContext.builder().build(); - return read(in, context); - } - - public T read(String in, YAMLDeserializationContext ctx) - throws YAMLDeserializationException, IOException { - YamlMapping reader = Yaml.fromString(in); - return ((AbstractBeanYAMLDeserializer) getDeserializer()).deserializeInline(reader, ctx); - } - - public YAMLDeserializer getDeserializer() { - if (null == deserializer) { - deserializer = newDeserializer(); - } - return deserializer; - } - - protected abstract YAMLDeserializer newDeserializer(); - - public String write(T value) throws YAMLSerializationException { - YAMLSerializationContext yamlSerializationContext = - DefaultYAMLSerializationContext.builder().build(); - return write(value, yamlSerializationContext); - } - - public String write(T value, YAMLSerializationContext ctx) throws YAMLSerializationException { - DumpSettings settings = - DumpSettings.builder() - .setDefaultFlowStyle(FlowStyle.BLOCK) - .setIndent(2) - .setIndicatorIndent(2) - .setIndentWithIndicator(true) - .build(); - YamlMapping writer = Yaml.create(settings); - ((AbstractBeanYAMLSerializer) getSerializer()).serializeInternally(writer, value, ctx); - return writer.toString(); - } - - @SuppressWarnings("unchecked") - public YAMLSerializer getSerializer() { - if (null == serializer) { - serializer = (YAMLSerializer) newSerializer(); - } - return serializer; - } - - protected abstract YAMLSerializer newSerializer(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/DefaultYAMLSerializationContext.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/DefaultYAMLSerializationContext.java deleted file mode 100644 index 9f784ba1241..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/DefaultYAMLSerializationContext.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -package org.kie.workbench.common.stunner.client.yaml.mapper.api; - -import java.util.Date; -import java.util.Map; - -import org.kie.workbench.common.stunner.client.yaml.mapper.api.internal.ser.YAMLSerializationContext; - -/** - * Context for the serialization process. - * - * @author Nicolas Morel - * @version $Id: $ - */ -public class DefaultYAMLSerializationContext implements YAMLSerializationContext { - - private final boolean serializeNulls; - private final boolean writeDatesAsTimestamps; - private final boolean writeEmptyYAMLArrays; - - private DefaultYAMLSerializationContext( - boolean serializeNulls, boolean writeDatesAsTimestamps, boolean writeEmptyYAMLArrays) { - this.serializeNulls = serializeNulls; - this.writeDatesAsTimestamps = writeDatesAsTimestamps; - this.writeEmptyYAMLArrays = writeEmptyYAMLArrays; - } - - /** - * builder - * - * @return a {@link DefaultYAMLSerializationContext.Builder} object. - */ - public static Builder builder() { - return new DefaultBuilder(); - } - - /** - * {@inheritDoc} - * - *

    isSerializeNulls - * - * @see Builder#serializeNulls(boolean) - */ - @Override - public boolean isSerializeNulls() { - return serializeNulls; - } - - /** - * {@inheritDoc} - * - *

    isWriteDatesAsTimestamps - * - * @see Builder#writeDatesAsTimestamps(boolean) - */ - @Override - public boolean isWriteDatesAsTimestamps() { - return writeDatesAsTimestamps; - } - - /** - * {@inheritDoc} - * - *

    isWriteEmptyYAMLArrays - * - * @see Builder#writeEmptyYAMLArrays(boolean) - */ - @Override - public boolean isWriteEmptyYAMLArrays() { - return writeEmptyYAMLArrays; - } - - public static class Builder { - - protected boolean serializeNulls = false; - - protected boolean writeDatesAsTimestamps = true; - - protected boolean writeEmptyYAMLArrays = true; - - protected boolean mapKeyAndValueCanonical = false; - - /** - * Sets whether object members are serialized when their value is null. This has no impact on - * array elements. The default is true. - * - * @param serializeNulls true if should serializeNulls - * @return the builder - */ - public Builder serializeNulls(boolean serializeNulls) { - this.serializeNulls = serializeNulls; - return this; - } - - /** - * Determines whether {@link Date} and {@link java.sql.Timestamp} values are to be serialized as - * numeric timestamps (true; the default), or as textual representation. - * - *

    If textual representation is used, the actual format is Option is enabled by default. - * - * @param writeDatesAsTimestamps true if should writeDatesAsTimestamps - * @return the builder - */ - public Builder writeDatesAsTimestamps(boolean writeDatesAsTimestamps) { - this.writeDatesAsTimestamps = writeDatesAsTimestamps; - return this; - } - - /** - * Feature that determines whether Container properties (POJO properties with declared value of - * Collection or array; i.e. things that produce YAML arrays) that are empty (have no elements) - * will be serialized as empty YAML arrays (true), or suppressed from output (false). - * - *

    Note that this does not change behavior of {@link Map}s, or "Collection-like" types. - * - *

    Feature is enabled by default. - * - * @param writeEmptyYAMLArrays true if should writeEmptyYAMLArrays - * @return the builder - */ - public Builder writeEmptyYAMLArrays(boolean writeEmptyYAMLArrays) { - this.writeEmptyYAMLArrays = writeEmptyYAMLArrays; - return this; - } - - public final YAMLSerializationContext build() { - return new DefaultYAMLSerializationContext( - serializeNulls, writeDatesAsTimestamps, writeEmptyYAMLArrays); - } - } - - public static class DefaultBuilder extends Builder { - - private DefaultBuilder() {} - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/YAMLDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/YAMLDeserializer.java deleted file mode 100644 index 1a0fef429c0..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/YAMLDeserializer.java +++ /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. - */ - - -package org.kie.workbench.common.stunner.client.yaml.mapper.api; - -import org.kie.workbench.common.stunner.client.yaml.mapper.api.exception.YAMLDeserializationException; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.internal.deser.YAMLDeserializationContext; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.node.YamlMapping; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.node.YamlNode; - -/** - * Base class for all the deserializer. It handles null values and exceptions. The rest is delegated - * to implementations. - * - * @author Nicolas Morel - * @version $Id: $ - */ -public interface YAMLDeserializer { - - T deserialize(YamlMapping yaml, String key, YAMLDeserializationContext ctx) - throws YAMLDeserializationException; - - T deserialize(YamlNode node, YAMLDeserializationContext ctx); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/YAMLSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/YAMLSerializer.java deleted file mode 100644 index 32ba2fb6829..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/YAMLSerializer.java +++ /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 org.kie.workbench.common.stunner.client.yaml.mapper.api; - -import org.kie.workbench.common.stunner.client.yaml.mapper.api.internal.ser.YAMLSerializationContext; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.node.YamlMapping; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.node.YamlSequence; - -public interface YAMLSerializer { - - void serialize(YamlMapping writer, String propertyName, T value, YAMLSerializationContext ctx); - - void serialize(YamlSequence writer, T value, YAMLSerializationContext ctx); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YAMLMapper.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YAMLMapper.java deleted file mode 100644 index abdf86aa067..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YAMLMapper.java +++ /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 org.kie.workbench.common.stunner.client.yaml.mapper.api.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface YAMLMapper {} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlProperty.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlProperty.java deleted file mode 100644 index c29f4e137b8..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlProperty.java +++ /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 org.kie.workbench.common.stunner.client.yaml.mapper.api.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Allows customization of field (or JavaBean property) name.This name is used either in - * serialization or in deserialization. - * - *

    Usage - * - *

    The {@code @YamlProperty} annotation can be used with the following program elements: - * - *

      - *
    • a JavaBean property - *
    • field - *
    - * - * @since JSON Binding 1.0 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) -public @interface YamlProperty { - - /** - * Customized name of the field (or JavaBean property). - * - * @return Customized property name. - */ - String value() default ""; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlPropertyOrder.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlPropertyOrder.java deleted file mode 100644 index 16673ebeabd..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlPropertyOrder.java +++ /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 org.kie.workbench.common.stunner.client.yaml.mapper.api.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.TYPE; - -/** This annotation is used to define the order of the properties in the YAML */ -@Retention(RetentionPolicy.RUNTIME) -@Target({TYPE}) -public @interface YamlPropertyOrder { - String[] value() default {""}; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlSubtype.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlSubtype.java deleted file mode 100644 index d7736c152ff..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlSubtype.java +++ /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 org.kie.workbench.common.stunner.client.yaml.mapper.api.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target({}) -public @interface YamlSubtype { - - /** - * Type alias which is used instead of a class name. - * - * @return alias value - */ - String alias(); - - /** - * An actual type bound to the alias. - * - * @return alias bound type - */ - Class type(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlTransient.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlTransient.java deleted file mode 100644 index 488c47dc433..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlTransient.java +++ /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 org.kie.workbench.common.stunner.client.yaml.mapper.api.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ANNOTATION_TYPE, FIELD, METHOD}) -public @interface YamlTransient {} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlTypeDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlTypeDeserializer.java deleted file mode 100644 index 081c96d9957..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlTypeDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.yaml.mapper.api.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.kie.workbench.common.stunner.client.yaml.mapper.api.YAMLDeserializer; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ - ElementType.TYPE, - ElementType.FIELD, -}) -public @interface YamlTypeDeserializer { - - /** - * Custom {@link YAMLDeserializer} which provides custom mapping for given field or JavaBean - * property. - * - * @return Deserializer to use. - */ - Class value(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlTypeInfo.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlTypeInfo.java deleted file mode 100644 index fec3e467dd4..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlTypeInfo.java +++ /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 org.kie.workbench.common.stunner.client.yaml.mapper.api.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE, ElementType.FIELD}) -public @interface YamlTypeInfo { - /** Default type information key name. */ - String DEFAULT_KEY_NAME = "_type"; - - /** - * Key used for keeping the type information (alias). Default value is {@code @type}. - * - * @return key name - */ - String key() default DEFAULT_KEY_NAME; - - /** - * Allowed aliases of the handled type. - * - * @return list of allowed aliases - */ - YamlSubtype[] value() default {}; -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlTypeSerializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlTypeSerializer.java deleted file mode 100644 index f8bfc898f69..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/annotation/YamlTypeSerializer.java +++ /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. - */ - - -package org.kie.workbench.common.stunner.client.yaml.mapper.api.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.kie.workbench.common.stunner.client.yaml.mapper.api.YAMLSerializer; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.internal.ser.AbstractYAMLSerializer; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ - ElementType.TYPE, - ElementType.FIELD, -}) -public @interface YamlTypeSerializer { - - /** - * Custom {@link AbstractYAMLSerializer} which provides custom mapping for given field or JavaBean - * property. - * - * @return Deserializer to use. - */ - Class value(); -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/exception/YAMLDeserializationException.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/exception/YAMLDeserializationException.java deleted file mode 100644 index 977aa679ebb..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/exception/YAMLDeserializationException.java +++ /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 org.kie.workbench.common.stunner.client.yaml.mapper.api.exception; - -/** Base exception for deserialization process */ -public class YAMLDeserializationException extends YAMLMappingException { - - /** Constructor for YAMLDeserializationException. */ - public YAMLDeserializationException() {} - - /** - * Constructor for YAMLDeserializationException. - * - * @param message a {@link String} object. - */ - public YAMLDeserializationException(String message) { - super(message); - } - - /** - * Constructor for YAMLDeserializationException. - * - * @param message a {@link String} object. - * @param cause a {@link Throwable} object. - */ - public YAMLDeserializationException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Constructor for YAMLDeserializationException. - * - * @param cause a {@link Throwable} object. - */ - public YAMLDeserializationException(Throwable cause) { - super(cause); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/exception/YAMLMappingException.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/exception/YAMLMappingException.java deleted file mode 100644 index c87c34e715b..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/exception/YAMLMappingException.java +++ /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 org.kie.workbench.common.stunner.client.yaml.mapper.api.exception; - -/** Base exception for mapping process */ -public class YAMLMappingException extends RuntimeException { - - /** Constructor for YAMLMappingException. */ - public YAMLMappingException() {} - - /** - * Constructor for YAMLMappingException. - * - * @param message a {@link String} object. - */ - public YAMLMappingException(String message) { - super(message); - } - - /** - * Constructor for YAMLMappingException. - * - * @param message a {@link String} object. - * @param cause a {@link Throwable} object. - */ - public YAMLMappingException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Constructor for YAMLMappingException. - * - * @param cause a {@link Throwable} object. - */ - public YAMLMappingException(Throwable cause) { - super(cause); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/exception/YAMLReadingException.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/exception/YAMLReadingException.java deleted file mode 100644 index 549cabe9e03..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/exception/YAMLReadingException.java +++ /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. - */ - - -package org.kie.workbench.common.stunner.client.yaml.mapper.api.exception; - -public class YAMLReadingException extends RuntimeException { - - public YAMLReadingException(String message) { - super(message); - } - - public YAMLReadingException(String message, Throwable cause) { - super(message, cause); - } - - public YAMLReadingException(Throwable cause) { - super(cause); - } - - public YAMLReadingException( - String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/exception/YAMLSerializationException.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/exception/YAMLSerializationException.java deleted file mode 100644 index 2c5c6c824ff..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/exception/YAMLSerializationException.java +++ /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 org.kie.workbench.common.stunner.client.yaml.mapper.api.exception; - -/** Base exception for serialization process */ -public class YAMLSerializationException extends YAMLMappingException { - - /** Constructor for YAMLSerializationException. */ - public YAMLSerializationException() {} - - /** - * Constructor for YAMLSerializationException. - * - * @param message a {@link String} object. - */ - public YAMLSerializationException(String message) { - super(message); - } - - /** - * Constructor for YAMLSerializationException. - * - * @param message a {@link String} object. - * @param cause a {@link Throwable} object. - */ - public YAMLSerializationException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Constructor for YAMLSerializationException. - * - * @param cause a {@link Throwable} object. - */ - public YAMLSerializationException(Throwable cause) { - super(cause); - } -} diff --git a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/internal/deser/BaseDateYAMLDeserializer.java b/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/internal/deser/BaseDateYAMLDeserializer.java deleted file mode 100644 index c0db7e44857..00000000000 --- a/packages/serverless-workflow-diagram-editor/third_party/tooling/marshalling/yaml/common/src/main/java/org/kie/workbench/common/stunner/client/yaml/mapper/api/internal/deser/BaseDateYAMLDeserializer.java +++ /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 org.kie.workbench.common.stunner.client.yaml.mapper.api.internal.deser; - -import java.sql.Time; -import java.sql.Timestamp; -import java.util.Date; - -import org.kie.workbench.common.stunner.client.yaml.mapper.api.YAMLDeserializer; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.node.YamlMapping; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.node.YamlNode; -import org.kie.workbench.common.stunner.client.yaml.mapper.api.node.YamlScalar; - -/** - * Base implementation of {@link YAMLDeserializer} for dates. - * - * @author Nicolas Morel - * @version $Id: $ - */ -public abstract class BaseDateYAMLDeserializer implements YAMLDeserializer { - - /** {@inheritDoc} */ - @Override - public D deserialize(YamlMapping yaml, String key, YAMLDeserializationContext ctx) { - return deserialize(yaml.getNode(key), ctx); - } - - /** Default implementation of {@link BaseDateYAMLDeserializer} for {@link Date} */ - public static final class DateYAMLDeserializer extends BaseDateYAMLDeserializer { - - public static final DateYAMLDeserializer INSTANCE = new DateYAMLDeserializer(); - - @Override - public Date deserialize(YamlNode date, YAMLDeserializationContext ctx) { - if (date == null) { - return null; - } - YamlScalar scalar = date.asScalar(); - return new Date(Long.parseLong(scalar.value())); - } - } - - /** Default implementation of {@link BaseDateYAMLDeserializer} for {@link java.sql.Date} */ - public static final class SqlDateYAMLDeserializer - extends BaseDateYAMLDeserializer { - - public static final SqlDateYAMLDeserializer INSTANCE = new SqlDateYAMLDeserializer(); - - private static final String SQL_DATE_FORMAT = "yyyy-MM-dd"; - - @Override - public java.sql.Date deserialize(YamlNode date, YAMLDeserializationContext ctx) { - if (date == null) { - return null; - } - YamlScalar scalar = date.asScalar(); - return new java.sql.Date(Long.parseLong(scalar.value())); - } - } - - /** Default implementation of {@link BaseDateYAMLDeserializer} for {@link Time} */ - public static final class SqlTimeYAMLDeserializer extends BaseDateYAMLDeserializer