├── .assets ├── kyverno-chainsaw-horizontal.png ├── kyverno-chainsaw-logo.png └── kyverno-chainsaw-logo.pptx ├── .crds ├── chainsaw.kyverno.io_configurations.yaml ├── chainsaw.kyverno.io_steptemplates.yaml └── chainsaw.kyverno.io_tests.yaml ├── .docs ├── LABELS.md └── RELEASE.md ├── .github ├── ISSUE_TEMPLATE │ ├── bug.yaml │ ├── config.yml │ ├── feature-request.yaml │ └── general-question.yaml ├── PULL_REQUEST_TEMPLATE.md ├── cherry-pick-bot.yml ├── dependabot.yml └── workflows │ ├── check-actions.yaml │ ├── check-milestone.yaml │ ├── codegen.yaml │ ├── codeql.yaml │ ├── docs-main.yaml │ ├── docs-release.yaml │ ├── lint.yaml │ ├── pr-semantics.yaml │ ├── release.yaml │ └── tests.yaml ├── .gitignore ├── .golangci.yml ├── .goreleaser.yaml ├── .ko.yaml ├── .release-notes ├── _template.md ├── main.md ├── v0.0.1.md ├── v0.0.2.md ├── v0.0.3.md ├── v0.0.4.md ├── v0.0.5.md ├── v0.0.6.md ├── v0.0.7.md ├── v0.0.8.md ├── v0.0.9.md ├── v0.1.0.md ├── v0.1.1.md ├── v0.1.2.md ├── v0.1.3.md ├── v0.1.4.md ├── v0.1.5.md ├── v0.1.6.md ├── v0.1.7.md ├── v0.1.8.md ├── v0.1.9.md ├── v0.2.0.md ├── v0.2.1.md ├── v0.2.10.md ├── v0.2.11.md ├── v0.2.12.md ├── v0.2.2.md ├── v0.2.3.md ├── v0.2.4.md ├── v0.2.5.md ├── v0.2.6.md ├── v0.2.7.md ├── v0.2.8.md └── v0.2.9.md ├── .schemas └── json │ ├── configuration-chainsaw-v1alpha1.json │ ├── configuration-chainsaw-v1alpha2.json │ ├── steptemplate-chainsaw-v1alpha1.json │ └── test-chainsaw-v1alpha1.json ├── .vscode └── launch.json ├── ADOPTERS.md ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── LICENSE ├── MAINTAINERS.md ├── Makefile ├── README.md ├── ROADMAP.md ├── chainsaw.rb ├── codecov.yml ├── go.mod ├── go.sum ├── hack ├── boilerplate.go.txt └── controller-gen │ ├── go.mod │ ├── go.sum │ ├── main.go │ └── markers.go ├── main.go ├── pkg ├── apis │ ├── compiler.go │ ├── conversion │ │ ├── configuration.go │ │ └── install.go │ ├── doc.go │ ├── v1alpha1 │ │ ├── action.go │ │ ├── catch_finally.go │ │ ├── catch_finally_test.go │ │ ├── configuration.go │ │ ├── doc.go │ │ ├── operation.go │ │ ├── operation_test.go │ │ ├── projection.go │ │ ├── step.go │ │ ├── test.go │ │ ├── types.go │ │ ├── types_test.go │ │ ├── zz_generated.deepcopy.go │ │ └── zz_generated.register.go │ └── v1alpha2 │ │ ├── configuration.go │ │ ├── doc.go │ │ ├── options.go │ │ ├── types.go │ │ ├── zz_generated.deepcopy.go │ │ └── zz_generated.register.go ├── cleanup │ └── cleaner │ │ ├── cleaner.go │ │ └── cleaner_test.go ├── client │ ├── client.go │ ├── dryrun │ │ ├── dry_run.go │ │ └── dry_run_test.go │ ├── simple │ │ ├── auth.go │ │ ├── client.go │ │ └── client_test.go │ ├── testing │ │ └── fake_client.go │ ├── types.go │ ├── utils.go │ └── utils_test.go ├── commands │ ├── assert │ │ ├── command.go │ │ └── command_test.go │ ├── build │ │ ├── command.go │ │ ├── command_test.go │ │ └── docs │ │ │ ├── catalog.tmpl │ │ │ ├── command.go │ │ │ ├── command_test.go │ │ │ └── docs.tmpl │ ├── create │ │ ├── command.go │ │ ├── command_test.go │ │ └── test │ │ │ ├── command.go │ │ │ └── command_test.go │ ├── docs │ │ ├── command.go │ │ ├── command_test.go │ │ ├── options.go │ │ ├── options_test.go │ │ └── utils.go │ ├── export │ │ ├── command.go │ │ ├── command_test.go │ │ └── schemas │ │ │ ├── command.go │ │ │ └── command_test.go │ ├── lint │ │ ├── command.go │ │ ├── command_test.go │ │ ├── processor.go │ │ └── schema.go │ ├── migrate │ │ ├── command.go │ │ ├── command_test.go │ │ └── kuttl │ │ │ ├── command.go │ │ │ ├── command_test.go │ │ │ ├── config │ │ │ ├── command.go │ │ │ └── command_test.go │ │ │ └── tests │ │ │ ├── command.go │ │ │ └── command_test.go │ ├── renovate │ │ ├── command.go │ │ ├── command_test.go │ │ └── config │ │ │ ├── command.go │ │ │ └── command_test.go │ ├── root.go │ ├── root │ │ ├── command.go │ │ └── command_test.go │ ├── root_test.go │ ├── test │ │ ├── command.go │ │ └── command_test.go │ └── version │ │ ├── command.go │ │ └── command_test.go ├── data │ ├── config │ │ └── default.yaml │ ├── crds │ │ ├── chainsaw.kyverno.io_configurations.yaml │ │ ├── chainsaw.kyverno.io_steptemplates.yaml │ │ └── chainsaw.kyverno.io_tests.yaml │ ├── data.go │ ├── data_test.go │ └── schemas │ │ └── json │ │ ├── configuration-chainsaw-v1alpha1.json │ │ ├── configuration-chainsaw-v1alpha2.json │ │ ├── steptemplate-chainsaw-v1alpha1.json │ │ └── test-chainsaw-v1alpha1.json ├── discovery │ ├── discovery.go │ ├── discovery_test.go │ ├── load.go │ ├── load_test.go │ ├── step.go │ └── test.go ├── engine │ ├── bindings │ │ ├── bindings.go │ │ └── bindings_test.go │ ├── checks │ │ ├── check.go │ │ ├── check_test.go │ │ ├── expect.go │ │ └── expect_test.go │ ├── client │ │ ├── client.go │ │ └── client_test.go │ ├── clusters │ │ ├── cluster.go │ │ ├── cluster_test.go │ │ ├── registry.go │ │ └── registry_test.go │ ├── functions │ │ ├── caller.go │ │ ├── env.go │ │ ├── env_test.go │ │ ├── functions.go │ │ ├── functions_test.go │ │ ├── k8s.go │ │ ├── k8s_test.go │ │ ├── metrics.go │ │ ├── strings.go │ │ └── utils.go │ ├── kubectl │ │ ├── describe.go │ │ ├── describe_test.go │ │ ├── get.go │ │ ├── get_test.go │ │ ├── logs.go │ │ ├── logs_test.go │ │ ├── mapping.go │ │ ├── proxy.go │ │ ├── proxy_test.go │ │ ├── wait.go │ │ └── wait_test.go │ ├── namespacer │ │ ├── namespacer.go │ │ ├── namespacer_test.go │ │ └── testing │ │ │ └── fake_namespacer.go │ ├── operations │ │ ├── apply │ │ │ ├── operation.go │ │ │ └── operation_test.go │ │ ├── assert │ │ │ ├── operation.go │ │ │ └── operation_test.go │ │ ├── command │ │ │ ├── operation.go │ │ │ └── operation_test.go │ │ ├── create │ │ │ ├── operation.go │ │ │ └── operation_test.go │ │ ├── delete │ │ │ ├── operation.go │ │ │ └── operation_test.go │ │ ├── error │ │ │ ├── operation.go │ │ │ └── operation_test.go │ │ ├── errors │ │ │ └── resource.go │ │ ├── internal │ │ │ ├── command_output.go │ │ │ ├── command_output_test.go │ │ │ ├── env.go │ │ │ ├── log.go │ │ │ ├── log_test.go │ │ │ ├── namespace.go │ │ │ ├── namespace_test.go │ │ │ ├── read.go │ │ │ └── read_test.go │ │ ├── operation.go │ │ ├── patch │ │ │ ├── operation.go │ │ │ └── operation_test.go │ │ ├── script │ │ │ ├── operation.go │ │ │ └── operation_test.go │ │ ├── sleep │ │ │ ├── operation.go │ │ │ └── operation_test.go │ │ ├── testing │ │ │ └── mock.go │ │ └── update │ │ │ ├── operation.go │ │ │ └── operation_test.go │ ├── outputs │ │ ├── outputs.go │ │ └── outputs_test.go │ ├── templating │ │ ├── convert.go │ │ ├── convert_test.go │ │ ├── resource_ref.go │ │ ├── resource_ref_test.go │ │ ├── template.go │ │ └── template_test.go │ └── types.go ├── expressions │ ├── parse.go │ ├── string.go │ ├── string_pointer.go │ ├── string_pointer_test.go │ └── string_test.go ├── loaders │ ├── config │ │ ├── default.go │ │ ├── default_test.go │ │ ├── load.go │ │ └── load_test.go │ ├── default.go │ ├── default_test.go │ ├── resource │ │ ├── load.go │ │ └── load_test.go │ ├── steptemplate │ │ ├── load.go │ │ └── load_test.go │ ├── test │ │ ├── load.go │ │ └── load_test.go │ ├── testing │ │ └── fake_loader.go │ └── values │ │ ├── load.go │ │ └── load_test.go ├── logging │ ├── context.go │ ├── context_test.go │ ├── log.go │ ├── log_test.go │ ├── logger.go │ ├── logger_test.go │ ├── operation.go │ ├── section.go │ ├── section_test.go │ ├── sink.go │ ├── sink_test.go │ └── status.go ├── metrics │ └── decode.go ├── mocks │ └── logger.go ├── model │ ├── config.go │ ├── report.go │ ├── report_test.go │ ├── summary.go │ ├── summary_test.go │ └── test.go ├── mutate │ ├── expression.go │ ├── mutate.go │ ├── mutate_test.go │ ├── mutation.go │ └── parse.go ├── report │ ├── json.go │ ├── junit.go │ ├── report.go │ └── report_test.go ├── runner │ ├── context │ │ ├── context.go │ │ ├── context_test.go │ │ ├── helpers.go │ │ ├── init.go │ │ ├── init_test.go │ │ └── legacy.go │ ├── flags │ │ ├── flags.go │ │ └── flags_test.go │ ├── info.go │ ├── internal │ │ ├── corpus_entry.go │ │ ├── test_deps.go │ │ └── test_deps_test.go │ ├── main_start.go │ ├── mocks │ │ └── registry.go │ ├── names │ │ ├── step.go │ │ ├── step_test.go │ │ ├── test.go │ │ └── test_test.go │ ├── namespace.go │ ├── namespace_test.go │ ├── operations │ │ ├── apply.go │ │ ├── assert.go │ │ ├── command.go │ │ ├── create.go │ │ ├── delete.go │ │ ├── describe.go │ │ ├── error.go │ │ ├── factory.go │ │ ├── get.go │ │ ├── helpers.go │ │ ├── operation.go │ │ ├── patch.go │ │ ├── podlogs.go │ │ ├── proxy.go │ │ ├── script.go │ │ ├── sleep.go │ │ ├── sleep_test.go │ │ ├── update.go │ │ ├── wait.go │ │ └── wait_test.go │ ├── runner.go │ ├── runner_test.go │ ├── sink.go │ ├── sink_test.go │ └── step_test.go ├── utils │ ├── diff │ │ ├── diff.go │ │ └── diff_test.go │ ├── env │ │ ├── expand.go │ │ └── expand_test.go │ ├── flag │ │ ├── flag.go │ │ └── flag_test.go │ ├── fs │ │ ├── check.go │ │ ├── check_test.go │ │ ├── discover.go │ │ └── discover_test.go │ ├── kube │ │ ├── namespace.go │ │ ├── namespace_test.go │ │ ├── unstructured.go │ │ └── unstructured_test.go │ ├── maps │ │ ├── merge.go │ │ └── merge_test.go │ ├── rest │ │ ├── config.go │ │ └── config_test.go │ └── yaml │ │ ├── with-anchors.yaml │ │ ├── without-anchors.yaml │ │ ├── yaml.go │ │ └── yaml_test.go └── version │ ├── version.go │ └── version_test.go ├── requirements.txt ├── testdata ├── .kube │ └── config ├── commands │ ├── assert │ │ ├── assert.yaml │ │ └── help.txt │ ├── build │ │ ├── docs │ │ │ └── help.txt │ │ └── help.txt │ ├── create │ │ ├── help.txt │ │ └── test │ │ │ ├── help.txt │ │ │ └── out.txt │ ├── docs │ │ ├── help.txt │ │ └── invalid-output.txt │ ├── export │ │ ├── help.txt │ │ └── schemas │ │ │ └── help.txt │ ├── help.txt │ ├── lint │ │ ├── configuration │ │ │ ├── configuration.json │ │ │ ├── configuration.yaml │ │ │ ├── pass.txt │ │ │ ├── wrong-configuration.json │ │ │ └── wrong-configuration.yaml │ │ └── test │ │ │ ├── pass.txt │ │ │ ├── test.json │ │ │ ├── test.yaml │ │ │ ├── txt.txt │ │ │ ├── wrong-test.json │ │ │ └── wrong-test.yaml │ ├── migrate │ │ ├── help.txt │ │ └── kuttl │ │ │ ├── config │ │ │ ├── help.txt │ │ │ ├── out-save.txt │ │ │ └── out.txt │ │ │ ├── help.txt │ │ │ └── tests │ │ │ ├── help.txt │ │ │ ├── out-save.txt │ │ │ └── out.txt │ ├── renovate │ │ ├── config │ │ │ ├── help.txt │ │ │ ├── out-save.txt │ │ │ ├── v1alpha1-custom.txt │ │ │ └── v1alpha1-default.txt │ │ └── help.txt │ ├── root │ │ └── help.txt │ ├── test │ │ ├── all_flags.txt │ │ ├── config │ │ │ ├── config_all_fields.yaml │ │ │ ├── empty_config.yaml │ │ │ ├── wrong_format_config.yaml │ │ │ └── wrong_kind_config.yaml │ │ ├── config_all_fields.txt │ │ ├── default.txt │ │ ├── help.txt │ │ ├── with_regex.txt │ │ ├── with_repeat_count.txt │ │ ├── with_suppress.txt │ │ ├── with_test_dirs.txt │ │ ├── with_timeout.txt │ │ ├── wrong_format_config.txt │ │ ├── wrong_kind_config.txt │ │ └── wrong_kind_config_err.txt │ └── version │ │ ├── help.txt │ │ └── out.txt ├── config │ ├── configmap.yaml │ ├── empty.yaml │ ├── multiple.yaml │ └── v1alpha1 │ │ ├── bad-catch.yaml │ │ ├── custom-config.yaml │ │ └── default.yaml ├── discovery │ ├── empty-test │ │ └── fake.json │ ├── manifests │ │ ├── 01-assert.yaml │ │ ├── 01-configmap.yaml │ │ └── 01-errors.yaml │ ├── multiple-tests │ │ └── chainsaw-test.yaml │ ├── not-a-test │ │ └── configmap.yaml │ ├── test-yml │ │ └── chainsaw-test.yml │ └── test │ │ └── chainsaw-test.yaml ├── e2e │ ├── config.yaml │ ├── examples │ │ ├── CATALOG.md │ │ ├── apply-outputs │ │ │ ├── README.md │ │ │ ├── chainsaw-test.yaml │ │ │ └── resources.yaml │ │ ├── array-assertion │ │ │ ├── README.md │ │ │ ├── assertions.yaml │ │ │ ├── chainsaw-test.yaml │ │ │ └── resources.yaml │ │ ├── assertion-tree │ │ │ ├── README.md │ │ │ ├── assert.yaml │ │ │ └── chainsaw-test.yaml │ │ ├── basic │ │ │ ├── README.md │ │ │ ├── chainsaw-test.yaml │ │ │ ├── configmap-assert.yaml │ │ │ └── configmap.yaml │ │ ├── bindings │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── catch │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── cel │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── command-output │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── delete │ │ │ ├── README.md │ │ │ ├── chainsaw-test.yaml │ │ │ └── cms.yaml │ │ ├── deployment │ │ │ ├── README.md │ │ │ ├── assertions.yaml │ │ │ ├── chainsaw-test.yaml │ │ │ └── resources.yaml │ │ ├── dynamic-clusters │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── field-validation │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── finally │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── inline │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── jmespath-label-condition │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── k8s-server-version │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── list │ │ │ ├── README.md │ │ │ ├── chainsaw-test.yaml │ │ │ └── list.yaml │ │ ├── metrics-decode │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── namespace-template-config │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── namespace-template │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── negative-testing │ │ │ ├── resource │ │ │ │ ├── README.md │ │ │ │ ├── chainsaw-test.yaml │ │ │ │ └── resources.yaml │ │ │ └── script │ │ │ │ ├── README.md │ │ │ │ └── chainsaw-test.yaml │ │ ├── non-resource-assertion │ │ │ ├── README.md │ │ │ ├── assert.yaml │ │ │ ├── chainsaw-test.yaml │ │ │ └── error.yaml │ │ ├── orphan │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── outputs │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── patch │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── proxy │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── quick-start │ │ │ ├── README.md │ │ │ ├── chainsaw-test.yaml │ │ │ └── configmap.yaml │ │ ├── scenarios │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── script-env │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── sleep │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── step-template-bindings │ │ │ ├── README.md │ │ │ ├── chainsaw-test.yaml │ │ │ └── template.yaml │ │ ├── step-template │ │ │ ├── README.md │ │ │ ├── chainsaw-test.yaml │ │ │ ├── configmap.yaml │ │ │ └── step-template.yaml │ │ ├── template │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── test-info │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── timeout │ │ │ ├── README.md │ │ │ └── chainsaw-test.yml │ │ ├── update-crd │ │ │ ├── README.md │ │ │ ├── chainsaw-test.yaml │ │ │ └── crd.yaml │ │ ├── update │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── values │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ ├── wait │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ │ └── yaml-anchors │ │ │ ├── README.md │ │ │ └── chainsaw-test.yaml │ └── values.yaml ├── kuttl │ ├── .chainsaw.yaml │ ├── 01-assert.yaml │ ├── 01-step.yaml │ ├── 02-assert.yaml │ ├── 02-step.yaml │ ├── configmap.yaml │ ├── invalid-config.yaml │ ├── kuttl-test.yaml │ └── multiple-config.yaml ├── report │ ├── JSON.json │ ├── JUNIT-OPERATION.xml │ ├── JUNIT-STEP.xml │ ├── JUNIT-TEST.xml │ └── XML.xml ├── resource │ ├── custom-resource.yaml │ ├── empty.yaml │ ├── folder-invalid │ │ ├── custom-resource.yaml │ │ └── invalid.yaml │ ├── folder-valid │ │ ├── custom-resource.yaml │ │ └── valid.yaml │ ├── invalid.yaml │ ├── list.yaml │ └── valid.yaml ├── runner │ └── processors │ │ ├── cron-job.yaml │ │ ├── deployment.yaml │ │ └── pod.yaml ├── step-template │ ├── bad-step.yaml │ ├── configmap.yaml │ ├── custom.yaml │ ├── empty.yaml │ ├── multiple.yaml │ ├── no-spec.yaml │ └── no-try.yaml ├── test │ ├── bad-step.yaml │ ├── configmap.yaml │ ├── custom-test.yaml │ ├── empty.yaml │ ├── multiple.yaml │ ├── no-spec.yaml │ ├── no-steps.yaml │ ├── ok.yaml │ └── raw-resource.yaml ├── validation │ └── example-file.yaml └── values │ ├── empty.yaml │ ├── invalid.yaml │ ├── values-1.yaml │ └── values-2.yaml └── website ├── apis ├── config.yaml └── markdown │ ├── members.tpl │ ├── pkg.tpl │ └── type.tpl ├── docs ├── cicd │ └── gh-action.md ├── community │ ├── contribute.md │ ├── index.md │ ├── making-a-pull-request.md │ ├── reporting-a-bug.md │ ├── reporting-a-docs-issue.md │ └── requesting-a-change.md ├── configuration │ ├── file.md │ ├── flags.md │ ├── index.md │ └── options │ │ ├── cleanup.md │ │ ├── clusters.md │ │ ├── deletion.md │ │ ├── discovery.md │ │ ├── error.md │ │ ├── execution.md │ │ ├── label-selectors.md │ │ ├── namespace.md │ │ ├── no-cluster.md │ │ ├── pause.md │ │ ├── report.md │ │ ├── templating.md │ │ ├── timeouts.md │ │ └── values.md ├── examples │ ├── concurrency.md │ ├── crds.md │ ├── events.md │ ├── index.md │ ├── inline.md │ ├── kube-version.md │ ├── label-selectors.md │ ├── multi-cluster.md │ ├── negative-testing.md │ ├── non-resource-assertions.md │ ├── test-output.md │ └── values.md ├── general │ ├── bindings.md │ ├── checks.md │ ├── inheritance.md │ ├── namespace.md │ ├── outputs.md │ ├── references.md │ └── templating.md ├── guides │ ├── kuttl-migration.md │ ├── lint.md │ └── test-docs.md ├── index.md ├── operations │ ├── apply.md │ ├── assert.md │ ├── command.md │ ├── create.md │ ├── delete.md │ ├── error.md │ ├── helpers │ │ ├── describe.md │ │ ├── events.md │ │ ├── get.md │ │ ├── index.md │ │ ├── logs.md │ │ └── wait.md │ ├── index.md │ ├── patch.md │ ├── script.md │ ├── sleep.md │ ├── todo │ │ ├── non-resource-assert._md │ │ └── templating._md │ └── update.md ├── overrides │ ├── home.html │ └── main.html ├── quick-start │ ├── assertion-trees.md │ ├── bindings.md │ ├── cleanup.md │ ├── completion.md │ ├── first-test.md │ ├── index.md │ ├── install.md │ ├── next-steps.md │ ├── operation-outputs.md │ ├── resource-templating.md │ ├── resources.md │ ├── run-tests.md │ ├── timeouts.md │ └── try-catch.md ├── reference │ ├── apis │ │ ├── chainsaw.v1alpha1.md │ │ └── chainsaw.v1alpha2.md │ ├── builtins.md │ ├── commands │ │ ├── chainsaw.md │ │ ├── chainsaw_assert.md │ │ ├── chainsaw_build.md │ │ ├── chainsaw_build_docs.md │ │ ├── chainsaw_completion.md │ │ ├── chainsaw_completion_bash.md │ │ ├── chainsaw_completion_fish.md │ │ ├── chainsaw_completion_powershell.md │ │ ├── chainsaw_completion_zsh.md │ │ ├── chainsaw_create.md │ │ ├── chainsaw_create_test.md │ │ ├── chainsaw_docs.md │ │ ├── chainsaw_export.md │ │ ├── chainsaw_export_schemas.md │ │ ├── chainsaw_lint.md │ │ ├── chainsaw_migrate.md │ │ ├── chainsaw_migrate_kuttl.md │ │ ├── chainsaw_migrate_kuttl_config.md │ │ ├── chainsaw_migrate_kuttl_tests.md │ │ ├── chainsaw_renovate.md │ │ ├── chainsaw_renovate_config.md │ │ ├── chainsaw_test.md │ │ └── chainsaw_version.md │ ├── index.md │ ├── jp │ │ ├── examples │ │ │ ├── abs.md │ │ │ ├── add.md │ │ │ ├── as_string.md │ │ │ ├── at.md │ │ │ ├── avg.md │ │ │ ├── base64_decode.md │ │ │ ├── base64_encode.md │ │ │ ├── ceil.md │ │ │ ├── compare.md │ │ │ ├── concat.md │ │ │ ├── contains.md │ │ │ ├── divide.md │ │ │ ├── ends_with.md │ │ │ ├── env.md │ │ │ ├── equal_fold.md │ │ │ ├── find_first.md │ │ │ ├── find_last.md │ │ │ ├── floor.md │ │ │ ├── from_items.md │ │ │ ├── group_by.md │ │ │ ├── items.md │ │ │ ├── join.md │ │ │ ├── json_parse.md │ │ │ ├── keys.md │ │ │ ├── label_match.md │ │ │ ├── length.md │ │ │ ├── lookup.md │ │ │ ├── lower.md │ │ │ ├── map.md │ │ │ ├── max.md │ │ │ ├── max_by.md │ │ │ ├── merge.md │ │ │ ├── min.md │ │ │ ├── min_by.md │ │ │ ├── modulo.md │ │ │ ├── multiply.md │ │ │ ├── not_null.md │ │ │ ├── object_from_lists.md │ │ │ ├── pad_left.md │ │ │ ├── pad_right.md │ │ │ ├── parse_json.md │ │ │ ├── parse_yaml.md │ │ │ ├── path_canonicalize.md │ │ │ ├── pattern_match.md │ │ │ ├── random.md │ │ │ ├── regex_match.md │ │ │ ├── regex_replace_all.md │ │ │ ├── regex_replace_all_literal.md │ │ │ ├── replace.md │ │ │ ├── replace_all.md │ │ │ ├── reverse.md │ │ │ ├── round.md │ │ │ ├── semver_compare.md │ │ │ ├── sort.md │ │ │ ├── sort_by.md │ │ │ ├── split.md │ │ │ ├── starts_with.md │ │ │ ├── subtract.md │ │ │ ├── sum.md │ │ │ ├── time_add.md │ │ │ ├── time_after.md │ │ │ ├── time_before.md │ │ │ ├── time_between.md │ │ │ ├── time_diff.md │ │ │ ├── time_now.md │ │ │ ├── time_now_utc.md │ │ │ ├── time_parse.md │ │ │ ├── time_since.md │ │ │ ├── time_to_cron.md │ │ │ ├── time_truncate.md │ │ │ ├── time_utc.md │ │ │ ├── to_array.md │ │ │ ├── to_boolean.md │ │ │ ├── to_lower.md │ │ │ ├── to_number.md │ │ │ ├── to_string.md │ │ │ ├── to_upper.md │ │ │ ├── trim.md │ │ │ ├── trim_left.md │ │ │ ├── trim_prefix.md │ │ │ ├── trim_right.md │ │ │ ├── trim_space.md │ │ │ ├── truncate.md │ │ │ ├── type.md │ │ │ ├── upper.md │ │ │ ├── values.md │ │ │ ├── wildcard.md │ │ │ ├── x509_decode.md │ │ │ ├── x_k8s_exists.md │ │ │ ├── x_k8s_get.md │ │ │ ├── x_k8s_list.md │ │ │ ├── x_k8s_resource_exists.md │ │ │ ├── x_k8s_server_version.md │ │ │ ├── x_metrics_decode.md │ │ │ └── zip.md │ │ └── functions.md │ └── json-schemas.md ├── static │ ├── extra.css │ ├── favicon.ico │ ├── kyverno-chainsaw-horizontal.png │ ├── kyverno-chainsaw-logo.png │ └── repo-card.js ├── step │ ├── catch.md │ ├── cleanup.md │ ├── finally.md │ ├── index.md │ └── try.md └── test │ ├── conventional.md │ ├── explicit.md │ ├── index.md │ └── spec │ └── index.md ├── jp ├── examples │ ├── abs.md │ ├── add.md │ ├── as_string.md │ ├── at.md │ ├── avg.md │ ├── base64_decode.md │ ├── base64_encode.md │ ├── ceil.md │ ├── compare.md │ ├── concat.md │ ├── contains.md │ ├── divide.md │ ├── ends_with.md │ ├── env.md │ ├── equal_fold.md │ ├── find_first.md │ ├── find_last.md │ ├── floor.md │ ├── from_items.md │ ├── group_by.md │ ├── items.md │ ├── join.md │ ├── json_parse.md │ ├── keys.md │ ├── label_match.md │ ├── length.md │ ├── lookup.md │ ├── lower.md │ ├── map.md │ ├── max.md │ ├── max_by.md │ ├── merge.md │ ├── min.md │ ├── min_by.md │ ├── modulo.md │ ├── multiply.md │ ├── not_null.md │ ├── object_from_lists.md │ ├── pad_left.md │ ├── pad_right.md │ ├── parse_json.md │ ├── parse_yaml.md │ ├── path_canonicalize.md │ ├── pattern_match.md │ ├── random.md │ ├── regex_match.md │ ├── regex_replace_all.md │ ├── regex_replace_all_literal.md │ ├── replace.md │ ├── replace_all.md │ ├── reverse.md │ ├── round.md │ ├── semver_compare.md │ ├── sort.md │ ├── sort_by.md │ ├── split.md │ ├── starts_with.md │ ├── subtract.md │ ├── sum.md │ ├── time_add.md │ ├── time_after.md │ ├── time_before.md │ ├── time_between.md │ ├── time_diff.md │ ├── time_now.md │ ├── time_now_utc.md │ ├── time_parse.md │ ├── time_since.md │ ├── time_to_cron.md │ ├── time_truncate.md │ ├── time_utc.md │ ├── to_array.md │ ├── to_boolean.md │ ├── to_lower.md │ ├── to_number.md │ ├── to_string.md │ ├── to_upper.md │ ├── trim.md │ ├── trim_left.md │ ├── trim_prefix.md │ ├── trim_right.md │ ├── trim_space.md │ ├── truncate.md │ ├── type.md │ ├── upper.md │ ├── values.md │ ├── wildcard.md │ ├── x509_decode.md │ ├── x_k8s_exists.md │ ├── x_k8s_get.md │ ├── x_k8s_list.md │ ├── x_k8s_resource_exists.md │ ├── x_k8s_server_version.md │ ├── x_metrics_decode.md │ └── zip.md └── main.go ├── mkdocs.base.yaml └── mkdocs.yaml /.assets/kyverno-chainsaw-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/.assets/kyverno-chainsaw-horizontal.png -------------------------------------------------------------------------------- /.assets/kyverno-chainsaw-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/.assets/kyverno-chainsaw-logo.png -------------------------------------------------------------------------------- /.assets/kyverno-chainsaw-logo.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/.assets/kyverno-chainsaw-logo.pptx -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://json.schemastore.org/github-issue-config.json 2 | 3 | blank_issues_enabled: true 4 | 5 | contact_links: 6 | - name: Chainsaw discussions 7 | url: https://github.com/kyverno/chainsaw/discussions 8 | about: Please ask and answer questions related to chainsaw here. 9 | - name: Chainsaw documentation 10 | url: https://kyverno.github.io/chainsaw 11 | about: Browse chainsaw documentation here. 12 | - name: Chainsaw slack channel 13 | url: https://kubernetes.slack.com/archives/C067LUFL43U 14 | about: Please ask and answer any chainsaw usage questions here. 15 | -------------------------------------------------------------------------------- /.github/cherry-pick-bot.yml: -------------------------------------------------------------------------------- 1 | enabled: true 2 | preservePullRequestTitle: true 3 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gomod 4 | directories: 5 | - / 6 | - /hack/controller-gen/ 7 | schedule: 8 | interval: daily 9 | - package-ecosystem: github-actions 10 | directory: / 11 | schedule: 12 | interval: daily 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache/ 2 | .gopath/ 3 | .temp/ 4 | .tools/ 5 | .venv/ 6 | chainsaw 7 | coverage.out 8 | website/site 9 | pkg/runner/chainsaw.xml 10 | pkg/runner/.json 11 | -------------------------------------------------------------------------------- /.ko.yaml: -------------------------------------------------------------------------------- 1 | defaultBaseImage: cgr.dev/chainguard/kubectl:latest-dev -------------------------------------------------------------------------------- /.release-notes/_template.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `TODO`. 4 | 5 | 22 | -------------------------------------------------------------------------------- /.release-notes/main.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `TODO`. 4 | 5 | 22 | 23 | ## 💫 New features 💫 24 | 25 | - Continue tests when an error happens when computing the test name -------------------------------------------------------------------------------- /.release-notes/v0.0.1.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.0.1`. 4 | 5 | ## 💫 New features 💫 6 | 7 | - Initial MVP release with support for `Apply`, `Delete`, `Assert` and `Error` operations 8 | - Supports configuration from both config file and command line flags 9 | - Full documentation available at https://kyverno.github.io/chainsaw 10 | -------------------------------------------------------------------------------- /.release-notes/v0.0.3.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.0.3`. 4 | 5 | ## 💫 New features 💫 6 | 7 | - We now have a [logo](https://github.com/kyverno/chainsaw/blob/main/.assets/kyverno-chainsaw-horizontal.png) :tada: 8 | - Timeouts are now managed per operation rather than per step 9 | - Added timeout support at the operation level 10 | 11 | ## 🔧 Fixes 🔧 12 | 13 | - Fixed `Exec` collectors not invoked 14 | 15 | ## 🎸 Misc 🎸 16 | 17 | - Improved error messages in a couple of places 18 | -------------------------------------------------------------------------------- /.release-notes/v0.0.4.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.0.4`. 4 | 5 | ## ‼️ Breaking changes ‼️ 6 | 7 | - Renamed flag `stop-on-first-failure` to `fail-fast` 8 | - Lots of API changes to allow more flexibility while making the syntax simpler 9 | - Commands accepting a file now expect a single file, list of files are not supported anymore 10 | 11 | ## 💫 New features 💫 12 | 13 | - Added provenance for released images 14 | - Added a GitHub action to install Chainsaw 15 | - Added a new `Create` operation 16 | - Steps changed to follow a Try / Catch / Finally model 17 | 18 | ## 🔧 Fixes 🔧 19 | 20 | - Fixed a bug where environment variables were not expanded correctly in command arguments 21 | 22 | ## 🎸 Misc 🎸 23 | 24 | - Switched to contextual logging 25 | -------------------------------------------------------------------------------- /.release-notes/v0.0.5.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.0.5`. 4 | 5 | ## 💫 New features 💫 6 | 7 | - Support new assertion tree model :tada: -------------------------------------------------------------------------------- /.release-notes/v0.1.0.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.1.0`. 4 | 5 | ## 💫 New features 💫 6 | 7 | - Chainsaw is now available via brew 8 | - Added support for defining multiple tests in the same test file 9 | 10 | ## 🔧 Fixes 🔧 11 | 12 | - Fixed an incorrect error message when loading a resource failed 13 | 14 | ## ✨ UI changes ✨ 15 | 16 | - Show Chainsaw version in `chainsaw test` command output 17 | 18 | ## 📚 Docs 📚 19 | 20 | - Added docs about parallel execution of Tests 21 | 22 | ## 🎸 Misc 🎸 23 | 24 | - Added an ADOPTERS.md file to the repository 25 | -------------------------------------------------------------------------------- /.release-notes/v0.1.2.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.1.2`. 4 | 5 | ## 💫 New features 💫 6 | 7 | - Added `chainsaw lint` command to lint tests 8 | - Added non-resource assertions support 9 | - Added experimental JMESPath functions prefix (`x_`) 10 | - Added JMESPath function to interact with the cluster under test 11 | 12 | ## 🔧 Fixes 🔧 13 | 14 | - Retry not working properly in `create` and `apply` operations 15 | 16 | ## 📚 Docs 📚 17 | 18 | - Added _Examples_ docs section 19 | - Added community meeting docs 20 | 21 | ## 🎸 Misc 🎸 22 | 23 | - Added pull request template 24 | - Added issue templates 25 | - GitHub action was removed from the main chainsaw repository 26 | -------------------------------------------------------------------------------- /.release-notes/v0.1.6.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.1.6`. 4 | 5 | ## 🔧 Fixes 🔧 6 | 7 | - Fix an issue with temporary KUBECONFIG not being an absolute path -------------------------------------------------------------------------------- /.release-notes/v0.2.1.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.2.1`. 4 | 5 | ## ‼️ Breaking changes ‼️ 6 | 7 | - Resource templating is now enabled by default 8 | 9 | ## 💫 New features 💫 10 | 11 | - Added `--pause-on-failure` flag to pause when a test failure happens (to ease troubleshooting) 12 | - Improved cleanup management logic, alternating `catch`, `finally` and `@cleanup` per step 13 | - Added support for registering clusters dynamically, useful when a cluster is created in a test step 14 | 15 | ## 🔧 Fixes 🔧 16 | 17 | - Fixed issue with cluster incorrectly registered 18 | - Force background deletion propagation policy (useful when testing unmanaged `Job`) 19 | -------------------------------------------------------------------------------- /.release-notes/v0.2.11.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.2.11`. 4 | 5 | ## 💫 New features 💫 6 | 7 | - Added CEL support everywhere (bindings, assertion trees, projection trees, outputs...) 8 | - Added test sharding support 9 | 10 | ## 🔧 Fixes 🔧 11 | 12 | - Fixed exit code when failing in root test run 13 | - Fixed `--no-cluster` flag not working 14 | 15 | ## 📚 Docs 📚 16 | 17 | - Added most JMESPath functions docs and examples 18 | -------------------------------------------------------------------------------- /.release-notes/v0.2.12.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.2.12`. 4 | 5 | ## 💫 New features 💫 6 | 7 | - Registered Kubernetes CEL libs, optional types, and various other std libs 8 | - Support conditions in labels in assertion templates 9 | - Added `skipCommandOutput` support to not log the `command` and `script` being executed 10 | 11 | ## 🔧 Fixes 🔧 12 | 13 | - Allow escaping dollar sign in `command` and `script` 14 | - Fixed `chainsaw build docs` rendering invalid yaml 15 | - Fixed step template bindings registered in the wrong order 16 | -------------------------------------------------------------------------------- /.release-notes/v0.2.5.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.2.5`. 4 | 5 | ## 💫 New features 💫 6 | 7 | - Add test scenarios support 8 | 9 | ## 🔧 Fixes 🔧 10 | 11 | - Fixed a potential issue with configuration defaults and marshaling 12 | 13 | ## 🎸 Misc 🎸 14 | 15 | - Improved all Python-based build operations 16 | -------------------------------------------------------------------------------- /.release-notes/v0.2.6.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.2.6`. 4 | 5 | ## 💫 New features 💫 6 | 7 | - Added a `proxy` action to allow HTTP calls to in-cluster services and pods 8 | - Added `as_string` JMESPath function to convert types based on strings to bare strings 9 | - Added `x_metrics_decode` JMESPath function to decode Prometheus metrics 10 | -------------------------------------------------------------------------------- /.release-notes/v0.2.7.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.2.7`. 4 | 5 | ## 💫 New features 💫 6 | 7 | - Added initial `TestTemplate` support to allow defining steps in separate files and reusing them across tests 8 | - Replaced programmatic validation with schema-based validation 9 | - Better generated JSON schemas based on OpenAPI v3 instead of v2 10 | 11 | ## 🔧 Fixes 🔧 12 | 13 | - Fixed incorrect `null` vs empty object comparison in assertion operations 14 | 15 | ## 📚 Docs 📚 16 | 17 | - Added detailed community pages to the website website 18 | - Added a CODE_OF_CONDUCT.md file in the repo 19 | -------------------------------------------------------------------------------- /.release-notes/v0.2.9.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | Release notes for `v0.2.9`. 4 | 5 | ## 💫 New features 💫 6 | 7 | - Added support for templating filenames used in operations 8 | - Added `ppc64le` and `s390x` binaries in release artifacts 9 | - Added support for Kubernetes 1.31 10 | - Added server side validation to validate the submitted resource 11 | - Added support for overriding the working directory in `command` and `script` operations 12 | - Compile string expressions at loading time 13 | - Made json path value optional in `wait` operation 14 | - Improved logging with `begin`, `end` and `warning` statuses 15 | - Added golang 1.23 support 16 | 17 | ## 🔧 Fixes 🔧 18 | 19 | - Fixed configuration `v1alpha2` lint command 20 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @kyverno/chainsaw-maintainers 2 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - 'hack/**/*.go' 3 | - 'website/**/*.go' 4 | - 'pkg/apis/**/zz_*.go' 5 | - 'pkg/testing/*.go' 6 | - '**/*_test.go' 7 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/go-logr/logr" 7 | "github.com/kyverno/chainsaw/pkg/commands" 8 | "sigs.k8s.io/controller-runtime/pkg/log" 9 | ) 10 | 11 | func main() { 12 | log.SetLogger(logr.Discard()) 13 | root := commands.RootCommand() 14 | if err := root.Execute(); err != nil { 15 | os.Exit(1) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pkg/apis/doc.go: -------------------------------------------------------------------------------- 1 | package apis 2 | -------------------------------------------------------------------------------- /pkg/apis/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | // Package v1alpha1 contains API Schema definitions for the v1alpha1 API group. 2 | // +k8s:deepcopy-gen=package 3 | // +kubebuilder:object:generate=true 4 | // +groupName=chainsaw.kyverno.io 5 | package v1alpha1 6 | -------------------------------------------------------------------------------- /pkg/apis/v1alpha2/doc.go: -------------------------------------------------------------------------------- 1 | // Package v1alpha2 contains API Schema definitions for the v1alpha2 API group. 2 | // +k8s:deepcopy-gen=package 3 | // +kubebuilder:object:generate=true 4 | // +groupName=chainsaw.kyverno.io 5 | package v1alpha2 6 | -------------------------------------------------------------------------------- /pkg/apis/v1alpha2/types.go: -------------------------------------------------------------------------------- 1 | package v1alpha2 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/apis/v1alpha1" 5 | _ "github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1" 6 | ) 7 | 8 | const ( 9 | EngineJP = v1alpha1.EngineJP 10 | EngineCEL = v1alpha1.EngineCEL 11 | ) 12 | 13 | type ( 14 | Clusters = v1alpha1.Clusters 15 | Compiler = v1alpha1.Compiler 16 | DefaultTimeouts = v1alpha1.DefaultTimeouts 17 | Projection = v1alpha1.Projection 18 | ) 19 | -------------------------------------------------------------------------------- /pkg/client/simple/auth.go: -------------------------------------------------------------------------------- 1 | package simple 2 | 3 | import ( 4 | _ "k8s.io/client-go/plugin/pkg/client/auth" // package needed for auth providers like GCP 5 | ) 6 | -------------------------------------------------------------------------------- /pkg/client/simple/client.go: -------------------------------------------------------------------------------- 1 | package simple 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/client" 5 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 6 | "k8s.io/client-go/rest" 7 | ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" 8 | ) 9 | 10 | func New(cfg *rest.Config) (client.Client, error) { 11 | var opts ctrlclient.Options 12 | client, err := ctrlclient.New(cfg, opts) 13 | if err != nil { 14 | return nil, err 15 | } 16 | return ctrlclient.WithFieldValidation(client, metav1.FieldValidationStrict), nil 17 | } 18 | -------------------------------------------------------------------------------- /pkg/commands/build/command.go: -------------------------------------------------------------------------------- 1 | package build 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/commands/build/docs" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func Command() *cobra.Command { 9 | cmd := &cobra.Command{ 10 | Use: "build", 11 | Short: "Build commands", 12 | Args: cobra.NoArgs, 13 | SilenceUsage: true, 14 | RunE: func(cmd *cobra.Command, _ []string) error { 15 | return cmd.Help() 16 | }, 17 | } 18 | cmd.AddCommand( 19 | docs.Command(), 20 | ) 21 | return cmd 22 | } 23 | -------------------------------------------------------------------------------- /pkg/commands/build/docs/catalog.tmpl: -------------------------------------------------------------------------------- 1 | # Tests catalog 2 | {{ range .Tests }} 3 | - [{{ .Test.Name }}]({{ fpRel $.BasePath (fpJoin .BasePath $.Readme) }}) 4 | {{- end }} 5 | -------------------------------------------------------------------------------- /pkg/commands/create/command.go: -------------------------------------------------------------------------------- 1 | package create 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/commands/create/test" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func Command() *cobra.Command { 9 | cmd := &cobra.Command{ 10 | Use: "create", 11 | Short: "Create Chainsaw resources", 12 | Args: cobra.NoArgs, 13 | SilenceUsage: true, 14 | RunE: func(cmd *cobra.Command, _ []string) error { 15 | return cmd.Help() 16 | }, 17 | } 18 | cmd.AddCommand( 19 | test.Command(), 20 | ) 21 | return cmd 22 | } 23 | -------------------------------------------------------------------------------- /pkg/commands/docs/utils.go: -------------------------------------------------------------------------------- 1 | package docs 2 | 3 | import ( 4 | "fmt" 5 | "path" 6 | "path/filepath" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | const fmTemplate = `--- 12 | date: %s 13 | title: "%s" 14 | weight: 35 15 | --- 16 | ` 17 | 18 | func websitePrepender(filename string) string { 19 | now := time.Now().Format(time.RFC3339) 20 | name := filepath.Base(filename) 21 | base := strings.TrimSuffix(name, path.Ext(name)) 22 | return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1)) 23 | } 24 | 25 | func websiteLinkHandler(filename string) string { 26 | return "../" + strings.TrimSuffix(filename, filepath.Ext(filename)) 27 | } 28 | 29 | func identity(s string) string { 30 | return s 31 | } 32 | 33 | func empty(s string) string { 34 | return "" 35 | } 36 | -------------------------------------------------------------------------------- /pkg/commands/export/command.go: -------------------------------------------------------------------------------- 1 | package export 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/commands/export/schemas" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func Command() *cobra.Command { 9 | cmd := &cobra.Command{ 10 | Use: "export", 11 | Short: "Export commands", 12 | Args: cobra.NoArgs, 13 | SilenceUsage: true, 14 | RunE: func(cmd *cobra.Command, _ []string) error { 15 | return cmd.Help() 16 | }, 17 | } 18 | cmd.AddCommand( 19 | schemas.Command(), 20 | ) 21 | return cmd 22 | } 23 | -------------------------------------------------------------------------------- /pkg/commands/lint/schema.go: -------------------------------------------------------------------------------- 1 | package lint 2 | 3 | import ( 4 | "fmt" 5 | "io/fs" 6 | 7 | "github.com/kyverno/chainsaw/pkg/data" 8 | ) 9 | 10 | func getScheme(kind string, version string) ([]byte, error) { 11 | schemasFs, err := data.Schemas() 12 | if err != nil { 13 | return nil, err 14 | } 15 | return fs.ReadFile(schemasFs, fmt.Sprintf("%s-chainsaw-%s.json", kind, version)) 16 | } 17 | -------------------------------------------------------------------------------- /pkg/commands/migrate/command.go: -------------------------------------------------------------------------------- 1 | package migrate 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/commands/migrate/kuttl" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func Command() *cobra.Command { 9 | cmd := &cobra.Command{ 10 | Use: "migrate", 11 | Short: "Migrate resources to Chainsaw", 12 | Args: cobra.NoArgs, 13 | SilenceUsage: true, 14 | RunE: func(cmd *cobra.Command, _ []string) error { 15 | return cmd.Help() 16 | }, 17 | } 18 | cmd.AddCommand( 19 | kuttl.Command(), 20 | ) 21 | return cmd 22 | } 23 | -------------------------------------------------------------------------------- /pkg/commands/migrate/kuttl/command.go: -------------------------------------------------------------------------------- 1 | package kuttl 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/commands/migrate/kuttl/config" 5 | "github.com/kyverno/chainsaw/pkg/commands/migrate/kuttl/tests" 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | func Command() *cobra.Command { 10 | cmd := &cobra.Command{ 11 | Use: "kuttl", 12 | Short: "Migrate KUTTL resources to Chainsaw", 13 | Args: cobra.NoArgs, 14 | SilenceUsage: true, 15 | RunE: func(cmd *cobra.Command, _ []string) error { 16 | return cmd.Help() 17 | }, 18 | } 19 | cmd.AddCommand( 20 | config.Command(), 21 | tests.Command(), 22 | ) 23 | return cmd 24 | } 25 | -------------------------------------------------------------------------------- /pkg/commands/renovate/command.go: -------------------------------------------------------------------------------- 1 | package renovate 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/commands/renovate/config" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func Command() *cobra.Command { 9 | cmd := &cobra.Command{ 10 | Use: "renovate", 11 | Short: "Upgrade Chainsaw resources", 12 | Args: cobra.NoArgs, 13 | SilenceUsage: true, 14 | RunE: func(cmd *cobra.Command, _ []string) error { 15 | return cmd.Help() 16 | }, 17 | } 18 | cmd.AddCommand( 19 | config.Command(), 20 | ) 21 | return cmd 22 | } 23 | -------------------------------------------------------------------------------- /pkg/commands/root/command.go: -------------------------------------------------------------------------------- 1 | package root 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | ) 6 | 7 | func Command() *cobra.Command { 8 | return &cobra.Command{ 9 | Use: "chainsaw", 10 | Short: "Stronger tool for e2e testing", 11 | SilenceUsage: true, 12 | RunE: func(cmd *cobra.Command, _ []string) error { 13 | return cmd.Help() 14 | }, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pkg/commands/version/command.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/kyverno/chainsaw/pkg/version" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func Command() *cobra.Command { 11 | return &cobra.Command{ 12 | Use: "version", 13 | Short: "Print the version informations", 14 | Args: cobra.NoArgs, 15 | SilenceUsage: true, 16 | RunE: func(cmd *cobra.Command, _ []string) error { 17 | fmt.Fprintf(cmd.OutOrStdout(), "Version: %s\n", version.Version()) 18 | fmt.Fprintf(cmd.OutOrStdout(), "Time: %s\n", version.Time()) 19 | fmt.Fprintf(cmd.OutOrStdout(), "Git commit ID: %s\n", version.Hash()) 20 | return nil 21 | }, 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /pkg/data/config/default.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha2 2 | kind: Configuration 3 | metadata: 4 | name: default 5 | spec: {} 6 | -------------------------------------------------------------------------------- /pkg/discovery/test.go: -------------------------------------------------------------------------------- 1 | package discovery 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/model" 5 | ) 6 | 7 | type Test struct { 8 | Test *model.Test 9 | BasePath string 10 | Err error 11 | } 12 | -------------------------------------------------------------------------------- /pkg/engine/functions/caller.go: -------------------------------------------------------------------------------- 1 | package functions 2 | 3 | import ( 4 | "context" 5 | "sync" 6 | 7 | jpfunctions "github.com/jmespath-community/go-jmespath/pkg/functions" 8 | "github.com/jmespath-community/go-jmespath/pkg/interpreter" 9 | "github.com/kyverno/kyverno-json/pkg/jp" 10 | ) 11 | 12 | var Caller = sync.OnceValue(func() interpreter.FunctionCaller { 13 | var funcs []jpfunctions.FunctionEntry 14 | funcs = append(funcs, jp.GetFunctions(context.Background())...) 15 | funcs = append(funcs, GetFunctions()...) 16 | return interpreter.NewFunctionCaller(funcs...) 17 | }) 18 | -------------------------------------------------------------------------------- /pkg/engine/functions/env.go: -------------------------------------------------------------------------------- 1 | package functions 2 | 3 | import ( 4 | "os" 5 | ) 6 | 7 | func jpEnv(arguments []any) (any, error) { 8 | var key string 9 | if err := getArg(arguments, 0, &key); err != nil { 10 | return nil, err 11 | } 12 | return os.Getenv(key), nil 13 | } 14 | -------------------------------------------------------------------------------- /pkg/engine/functions/functions_test.go: -------------------------------------------------------------------------------- 1 | package functions 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestGetFunctions(t *testing.T) { 10 | assert.Equal(t, 9, len(GetFunctions())) 11 | } 12 | -------------------------------------------------------------------------------- /pkg/engine/functions/metrics.go: -------------------------------------------------------------------------------- 1 | package functions 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/metrics" 5 | "github.com/prometheus/common/model" 6 | ) 7 | 8 | func jpMetricsDecode(arguments []any) (any, error) { 9 | var text string 10 | if err := getArg(arguments, 0, &text); err != nil { 11 | return nil, err 12 | } 13 | vector, err := metrics.Decode(text, model.Now()) 14 | if err != nil { 15 | return nil, err 16 | } 17 | return vector, nil 18 | } 19 | -------------------------------------------------------------------------------- /pkg/engine/functions/strings.go: -------------------------------------------------------------------------------- 1 | package functions 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | func jpTrimSpace(arguments []any) (any, error) { 8 | var in string 9 | if err := getArg(arguments, 0, &in); err != nil { 10 | return nil, err 11 | } 12 | return strings.TrimSpace(in), nil 13 | } 14 | -------------------------------------------------------------------------------- /pkg/engine/namespacer/testing/fake_namespacer.go: -------------------------------------------------------------------------------- 1 | package testing 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/client" 5 | ) 6 | 7 | type FakeNamespacer struct { 8 | ApplyFn func(call int, client client.Client, obj client.Object) error 9 | GetNamespaceFn func(call int) string 10 | numCalls int 11 | } 12 | 13 | func (n *FakeNamespacer) Apply(client client.Client, obj client.Object) error { 14 | defer func() { n.numCalls++ }() 15 | return n.ApplyFn(n.numCalls, client, obj) 16 | } 17 | 18 | func (n *FakeNamespacer) GetNamespace() string { 19 | defer func() { n.numCalls++ }() 20 | return n.GetNamespaceFn(n.numCalls) 21 | } 22 | -------------------------------------------------------------------------------- /pkg/engine/operations/internal/log.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/kyverno/chainsaw/pkg/client" 8 | "github.com/kyverno/chainsaw/pkg/logging" 9 | "github.com/kyverno/pkg/ext/output/color" 10 | ) 11 | 12 | func LogStart(ctx context.Context, op logging.Operation, obj client.Object, args ...fmt.Stringer) { 13 | logging.Log(ctx, op, logging.RunStatus, obj, color.BoldFgCyan, args...) 14 | } 15 | 16 | func LogEnd(ctx context.Context, op logging.Operation, obj client.Object, err error) { 17 | if err != nil { 18 | logging.Log(ctx, op, logging.ErrorStatus, obj, color.BoldRed, logging.ErrSection(err)) 19 | } else { 20 | logging.Log(ctx, op, logging.DoneStatus, obj, color.BoldGreen) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /pkg/engine/operations/internal/namespace.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/client" 5 | "github.com/kyverno/chainsaw/pkg/engine/namespacer" 6 | ) 7 | 8 | func ApplyNamespacer(namespacer namespacer.Namespacer, client client.Client, obj client.Object) error { 9 | if namespacer == nil { 10 | return nil 11 | } 12 | return namespacer.Apply(client, obj) 13 | } 14 | -------------------------------------------------------------------------------- /pkg/engine/operations/operation.go: -------------------------------------------------------------------------------- 1 | package operations 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/kyverno/chainsaw/pkg/apis" 7 | "github.com/kyverno/chainsaw/pkg/engine/outputs" 8 | ) 9 | 10 | type Operation interface { 11 | Exec(context.Context, apis.Bindings) (outputs.Outputs, error) 12 | } 13 | -------------------------------------------------------------------------------- /pkg/engine/operations/testing/mock.go: -------------------------------------------------------------------------------- 1 | package testing 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/kyverno/chainsaw/pkg/apis" 7 | "github.com/kyverno/chainsaw/pkg/engine/outputs" 8 | ) 9 | 10 | type MockOperation struct { 11 | ExecFn func(context.Context, apis.Bindings) (outputs.Outputs, error) 12 | } 13 | 14 | func (m MockOperation) Exec(ctx context.Context, bindings apis.Bindings) (outputs.Outputs, error) { 15 | return m.ExecFn(ctx, bindings) 16 | } 17 | -------------------------------------------------------------------------------- /pkg/engine/templating/convert.go: -------------------------------------------------------------------------------- 1 | package templating 2 | 3 | func convertSlice(in any) []any { 4 | data, ok := in.([]any) 5 | if !ok { 6 | return nil 7 | } 8 | out := []any{} 9 | for _, v := range data { 10 | out = append(out, convert(v)) 11 | } 12 | return out 13 | } 14 | 15 | func convertMap(in any) map[string]any { 16 | data, ok := in.(map[any]any) 17 | if !ok { 18 | return nil 19 | } 20 | out := map[string]any{} 21 | for k, v := range data { 22 | out[k.(string)] = convert(v) 23 | } 24 | return out 25 | } 26 | 27 | func convert(in any) any { 28 | if result := convertSlice(in); result != nil { 29 | return result 30 | } 31 | if result := convertMap(in); result != nil { 32 | return result 33 | } 34 | return in 35 | } 36 | -------------------------------------------------------------------------------- /pkg/engine/types.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/engine/namespacer" 5 | ) 6 | 7 | type ( 8 | Namespacer = namespacer.Namespacer 9 | ) 10 | -------------------------------------------------------------------------------- /pkg/loaders/config/default.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/kyverno/chainsaw/pkg/apis/v1alpha2" 7 | "github.com/kyverno/chainsaw/pkg/data" 8 | ) 9 | 10 | func defaultConfiguration(_fs func() ([]byte, error)) (*v1alpha2.Configuration, error) { 11 | if _fs == nil { 12 | _fs = data.ConfigFile 13 | } 14 | bytes, err := _fs() 15 | if err != nil { 16 | return nil, err 17 | } 18 | return LoadBytes(bytes) 19 | } 20 | 21 | var DefaultConfiguration = sync.OnceValues(func() (*v1alpha2.Configuration, error) { return defaultConfiguration(nil) }) 22 | -------------------------------------------------------------------------------- /pkg/loaders/default.go: -------------------------------------------------------------------------------- 1 | package loaders 2 | 3 | import ( 4 | "io/fs" 5 | "sync" 6 | 7 | "github.com/kyverno/chainsaw/pkg/data" 8 | "github.com/kyverno/pkg/ext/resource/loader" 9 | "sigs.k8s.io/kubectl-validate/pkg/openapiclient" 10 | ) 11 | 12 | func defaultLoader(_fs func() (fs.FS, error)) (loader.Loader, error) { 13 | if _fs == nil { 14 | _fs = data.Crds 15 | } 16 | crdsFs, err := _fs() 17 | if err != nil { 18 | return nil, err 19 | } 20 | return loader.New(openapiclient.NewLocalCRDFiles(crdsFs)) 21 | } 22 | 23 | var DefaultLoader = sync.OnceValues(func() (loader.Loader, error) { return defaultLoader(nil) }) 24 | -------------------------------------------------------------------------------- /pkg/loaders/testing/fake_loader.go: -------------------------------------------------------------------------------- 1 | package testing 2 | 3 | import ( 4 | "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 5 | "k8s.io/apimachinery/pkg/runtime/schema" 6 | ) 7 | 8 | type FakeLoader struct { 9 | LoadFn func(int, []byte) (schema.GroupVersionKind, unstructured.Unstructured, error) 10 | numCalls int 11 | } 12 | 13 | func (f *FakeLoader) Load(data []byte) (schema.GroupVersionKind, unstructured.Unstructured, error) { 14 | defer func() { f.numCalls++ }() 15 | return f.LoadFn(f.numCalls, data) 16 | } 17 | -------------------------------------------------------------------------------- /pkg/logging/log.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/fatih/color" 8 | "github.com/kyverno/chainsaw/pkg/client" 9 | ) 10 | 11 | func Log(ctx context.Context, operation Operation, status Status, obj client.Object, color *color.Color, args ...fmt.Stringer) { 12 | if logger := getLogger(ctx); logger != nil { 13 | logger.Log(ctx, operation, status, obj, color, args...) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pkg/logging/operation.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | type Operation string 4 | 5 | const ( 6 | Apply Operation = "APPLY" 7 | Assert Operation = "ASSERT" 8 | Catch Operation = "CATCH" 9 | Cleanup Operation = "CLEANUP" 10 | Command Operation = "CMD" 11 | Create Operation = "CREATE" 12 | Delete Operation = "DELETE" 13 | Error Operation = "ERROR" 14 | Finally Operation = "FINALLY" 15 | Get Operation = "GET" 16 | Internal Operation = "INTERNAL" 17 | Patch Operation = "PATCH" 18 | Script Operation = "SCRIPT" 19 | Sleep Operation = "SLEEP" 20 | Stderr Operation = "STDERR" 21 | Stdout Operation = "STDOUT" 22 | Try Operation = "TRY" 23 | Update Operation = "UPDATE" 24 | ) 25 | -------------------------------------------------------------------------------- /pkg/logging/sink.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/fatih/color" 7 | "github.com/kyverno/chainsaw/pkg/client" 8 | ) 9 | 10 | type Sink interface { 11 | Log(string, string, Operation, Status, client.Object, *color.Color, ...fmt.Stringer) 12 | } 13 | 14 | type SinkFunc func(string, string, Operation, Status, client.Object, *color.Color, ...fmt.Stringer) 15 | 16 | func (f SinkFunc) Log(test string, step string, operation Operation, status Status, obj client.Object, color *color.Color, args ...fmt.Stringer) { 17 | f(test, step, operation, status, obj, color, args...) 18 | } 19 | -------------------------------------------------------------------------------- /pkg/logging/status.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | type Status string 4 | 5 | const ( 6 | BeginStatus Status = "BEGIN" 7 | DoneStatus Status = "DONE" 8 | EndStatus Status = "END" 9 | ErrorStatus Status = "ERROR" 10 | LogStatus Status = "LOG" 11 | OkStatus Status = "OK" 12 | RunStatus Status = "RUN" 13 | SkippedStatus Status = "SKIP" 14 | WarnStatus Status = "WARN" 15 | // DoneStatus Status = "✅" 16 | // ErrorStatus Status = "❌" 17 | // LogStatus Status = "📄" 18 | // OkStatus Status = "🟢" 19 | // RunStatus Status = "🚧" 20 | // WarnStatus Status = "🟡" 21 | ) 22 | -------------------------------------------------------------------------------- /pkg/mocks/logger.go: -------------------------------------------------------------------------------- 1 | package mocks 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/fatih/color" 8 | "github.com/kyverno/chainsaw/pkg/client" 9 | "github.com/kyverno/chainsaw/pkg/logging" 10 | ) 11 | 12 | type Logger struct { 13 | Logs []string 14 | numCalls int 15 | } 16 | 17 | func (f *Logger) Log(_ context.Context, operation logging.Operation, status logging.Status, obj client.Object, color *color.Color, args ...fmt.Stringer) { 18 | defer func() { f.numCalls++ }() 19 | message := fmt.Sprintf("%s: %s - %v", operation, status, args) 20 | f.Logs = append(f.Logs, message) 21 | } 22 | 23 | func (f *Logger) NumCalls() int { 24 | return f.numCalls 25 | } 26 | -------------------------------------------------------------------------------- /pkg/model/config.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/apis/v1alpha2" 5 | ) 6 | 7 | type Configuration = v1alpha2.ConfigurationSpec 8 | -------------------------------------------------------------------------------- /pkg/model/summary.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "sync/atomic" 5 | ) 6 | 7 | type SummaryResult interface { 8 | Passed() int32 9 | Failed() int32 10 | Skipped() int32 11 | } 12 | 13 | type Summary struct { 14 | passed atomic.Int32 15 | failed atomic.Int32 16 | skipped atomic.Int32 17 | } 18 | 19 | func (s *Summary) IncPassed() { 20 | s.passed.Add(1) 21 | } 22 | 23 | func (s *Summary) IncFailed() { 24 | s.failed.Add(1) 25 | } 26 | 27 | func (s *Summary) IncSkipped() { 28 | s.skipped.Add(1) 29 | } 30 | 31 | func (s *Summary) Passed() int32 { 32 | return s.passed.Load() 33 | } 34 | 35 | func (s *Summary) Failed() int32 { 36 | return s.failed.Load() 37 | } 38 | 39 | func (s *Summary) Skipped() int32 { 40 | return s.skipped.Load() 41 | } 42 | -------------------------------------------------------------------------------- /pkg/model/summary_test.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "sync" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func Test_summay(t *testing.T) { 11 | var wg sync.WaitGroup 12 | var s Summary 13 | const count int32 = 10000 14 | for i := 0; i < int(count); i++ { 15 | wg.Add(3) 16 | go func() { 17 | defer wg.Done() 18 | s.IncFailed() 19 | }() 20 | go func() { 21 | defer wg.Done() 22 | s.IncPassed() 23 | }() 24 | go func() { 25 | defer wg.Done() 26 | s.IncSkipped() 27 | }() 28 | } 29 | wg.Wait() 30 | assert.Equal(t, count, s.Failed()) 31 | assert.Equal(t, count, s.Passed()) 32 | assert.Equal(t, count, s.Skipped()) 33 | } 34 | -------------------------------------------------------------------------------- /pkg/model/test.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/apis/v1alpha1" 5 | ) 6 | 7 | type Test = v1alpha1.Test 8 | -------------------------------------------------------------------------------- /pkg/mutate/expression.go: -------------------------------------------------------------------------------- 1 | package mutate 2 | 3 | import ( 4 | "context" 5 | "reflect" 6 | 7 | "github.com/kyverno/chainsaw/pkg/expressions" 8 | reflectutils "github.com/kyverno/kyverno-json/pkg/utils/reflect" 9 | ) 10 | 11 | func parseExpression(ctx context.Context, value any) *expressions.Expression { 12 | if reflectutils.GetKind(value) != reflect.String { 13 | return nil 14 | } 15 | return expressions.Parse(ctx, reflect.ValueOf(value).String()) 16 | } 17 | -------------------------------------------------------------------------------- /pkg/mutate/mutate.go: -------------------------------------------------------------------------------- 1 | package mutate 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/kyverno/chainsaw/pkg/apis" 7 | "github.com/kyverno/kyverno-json/pkg/core/compilers" 8 | "k8s.io/apimachinery/pkg/util/validation/field" 9 | ) 10 | 11 | func Mutate(ctx context.Context, compilers compilers.Compilers, path *field.Path, mutation Mutation, value any, bindings apis.Bindings) (any, error) { 12 | return mutation.mutate(ctx, compilers, path, value, bindings) 13 | } 14 | -------------------------------------------------------------------------------- /pkg/mutate/mutation.go: -------------------------------------------------------------------------------- 1 | package mutate 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/kyverno/chainsaw/pkg/apis" 7 | "github.com/kyverno/kyverno-json/pkg/core/compilers" 8 | "k8s.io/apimachinery/pkg/util/validation/field" 9 | ) 10 | 11 | type Mutation interface { 12 | mutate(context.Context, compilers.Compilers, *field.Path, any, apis.Bindings) (any, error) 13 | } 14 | -------------------------------------------------------------------------------- /pkg/runner/info.go: -------------------------------------------------------------------------------- 1 | package runner 2 | 3 | import ( 4 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 5 | ) 6 | 7 | type TestInfo struct { 8 | Id int 9 | ScenarioId int 10 | Metadata metav1.ObjectMeta 11 | } 12 | 13 | type StepInfo struct { 14 | Id int 15 | } 16 | 17 | type OperationInfo struct { 18 | Id int 19 | ResourceId int 20 | } 21 | -------------------------------------------------------------------------------- /pkg/runner/internal/corpus_entry.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | // corpusEntry is from the public go testing which references an internal structure. 4 | // corpusEntry is an alias to the same type as internal/fuzz.CorpusEntry. 5 | // We use a type alias because we don't want to export this type, and we can't 6 | // import internal/fuzz from testing. 7 | type corpusEntry = struct { 8 | Parent string 9 | Path string 10 | Data []byte 11 | Values []any 12 | Generation int 13 | IsSeed bool 14 | } 15 | -------------------------------------------------------------------------------- /pkg/runner/main_start.go: -------------------------------------------------------------------------------- 1 | package runner 2 | 3 | type mainstart interface { 4 | Run() int 5 | } 6 | -------------------------------------------------------------------------------- /pkg/runner/mocks/registry.go: -------------------------------------------------------------------------------- 1 | package mocks 2 | 3 | import ( 4 | "github.com/kyverno/chainsaw/pkg/client" 5 | "github.com/kyverno/chainsaw/pkg/engine/clusters" 6 | "k8s.io/client-go/rest" 7 | ) 8 | 9 | type Registry struct { 10 | Client client.Client 11 | } 12 | 13 | func (r Registry) Register(string, clusters.Cluster) clusters.Registry { 14 | return r 15 | } 16 | 17 | func (r Registry) Lookup(string) clusters.Cluster { 18 | return nil 19 | } 20 | 21 | func (r Registry) Build(clusters.Cluster) (*rest.Config, client.Client, error) { 22 | return nil, r.Client, nil 23 | } 24 | -------------------------------------------------------------------------------- /pkg/runner/names/step.go: -------------------------------------------------------------------------------- 1 | package names 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/kyverno/chainsaw/pkg/apis/v1alpha1" 7 | ) 8 | 9 | func Step(step v1alpha1.TestStep, i int) string { 10 | if step.Name != "" { 11 | return step.Name 12 | } 13 | return fmt.Sprintf("step-%d", i+1) 14 | } 15 | -------------------------------------------------------------------------------- /pkg/runner/names/step_test.go: -------------------------------------------------------------------------------- 1 | package names 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/kyverno/chainsaw/pkg/apis/v1alpha1" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestStep(t *testing.T) { 11 | tests := []struct { 12 | name string 13 | step v1alpha1.TestStep 14 | i int 15 | want string 16 | }{{ 17 | name: "no name", 18 | step: v1alpha1.TestStep{ 19 | Name: "", 20 | }, 21 | i: 10, 22 | want: "step-11", 23 | }, { 24 | name: "with name", 25 | step: v1alpha1.TestStep{ 26 | Name: "foo", 27 | }, 28 | i: 10, 29 | want: "foo", 30 | }} 31 | for _, tt := range tests { 32 | t.Run(tt.name, func(t *testing.T) { 33 | got := Step(tt.step, tt.i) 34 | assert.Equal(t, tt.want, got) 35 | }) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /pkg/runner/operations/operation.go: -------------------------------------------------------------------------------- 1 | package operations 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/kyverno/chainsaw/pkg/engine/outputs" 7 | enginecontext "github.com/kyverno/chainsaw/pkg/runner/context" 8 | ) 9 | 10 | type Operation interface { 11 | Execute(context.Context, enginecontext.TestContext) (outputs.Outputs, error) 12 | } 13 | -------------------------------------------------------------------------------- /pkg/runner/operations/sleep.go: -------------------------------------------------------------------------------- 1 | package operations 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/kyverno/chainsaw/pkg/apis/v1alpha1" 8 | opsleep "github.com/kyverno/chainsaw/pkg/engine/operations/sleep" 9 | "github.com/kyverno/chainsaw/pkg/engine/outputs" 10 | enginecontext "github.com/kyverno/chainsaw/pkg/runner/context" 11 | ) 12 | 13 | type sleepAction struct { 14 | duration time.Duration 15 | } 16 | 17 | func (o sleepAction) Execute(ctx context.Context, tc enginecontext.TestContext) (outputs.Outputs, error) { 18 | op := opsleep.New(o.duration) 19 | return op.Exec(ctx, tc.Bindings()) 20 | } 21 | 22 | func sleepOperation(op v1alpha1.Sleep) Operation { 23 | return sleepAction{ 24 | duration: op.Duration.Duration, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /pkg/utils/env/expand.go: -------------------------------------------------------------------------------- 1 | package env 2 | 3 | import ( 4 | "os" 5 | ) 6 | 7 | func Expand(env map[string]string, in ...string) []string { 8 | var args []string 9 | for _, arg := range in { 10 | expanded := os.Expand(arg, func(key string) string { 11 | // check $ key -> $$ becomes $ 12 | if key == "$" { 13 | return "$" 14 | } 15 | // check the env map first 16 | if expanded, found := env[key]; found { 17 | return expanded 18 | } 19 | // check the env vars 20 | if expanded, found := os.LookupEnv(key); found { 21 | return expanded 22 | } 23 | // return the given key 24 | return "$" + key 25 | }) 26 | args = append(args, expanded) 27 | } 28 | return args 29 | } 30 | -------------------------------------------------------------------------------- /pkg/utils/flag/flag.go: -------------------------------------------------------------------------------- 1 | package flag 2 | 3 | import ( 4 | "github.com/spf13/pflag" 5 | ) 6 | 7 | // IsSet returns true if a flag is set on the command line. 8 | func IsSet(flagSet *pflag.FlagSet, name string) bool { 9 | found := false 10 | flagSet.Visit(func(flag *pflag.Flag) { 11 | if flag.Name == name { 12 | found = true 13 | } 14 | }) 15 | return found 16 | } 17 | -------------------------------------------------------------------------------- /pkg/utils/fs/check.go: -------------------------------------------------------------------------------- 1 | package fs 2 | 3 | import ( 4 | "os" 5 | ) 6 | 7 | func CheckFolders(paths ...string) error { 8 | for _, path := range paths { 9 | if _, err := os.Stat(path); err != nil { 10 | return err 11 | } 12 | } 13 | return nil 14 | } 15 | -------------------------------------------------------------------------------- /pkg/utils/kube/namespace.go: -------------------------------------------------------------------------------- 1 | package kube 2 | 3 | import ( 4 | corev1 "k8s.io/api/core/v1" 5 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 6 | ) 7 | 8 | func Namespace(name string) corev1.Namespace { 9 | return corev1.Namespace{ 10 | TypeMeta: metav1.TypeMeta{ 11 | APIVersion: corev1.SchemeGroupVersion.String(), 12 | Kind: "Namespace", 13 | }, 14 | ObjectMeta: metav1.ObjectMeta{ 15 | Name: name, 16 | }, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pkg/utils/kube/namespace_test.go: -------------------------------------------------------------------------------- 1 | package kube 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | corev1 "k8s.io/api/core/v1" 8 | ) 9 | 10 | func TestNamespace(t *testing.T) { 11 | expectedName := "testNamespace" 12 | ns := Namespace(expectedName) 13 | assert.Equal(t, corev1.SchemeGroupVersion.String(), ns.APIVersion) 14 | assert.Equal(t, "Namespace", ns.Kind) 15 | assert.Equal(t, expectedName, ns.Name) 16 | } 17 | -------------------------------------------------------------------------------- /pkg/utils/kube/unstructured.go: -------------------------------------------------------------------------------- 1 | package kube 2 | 3 | import ( 4 | "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 5 | "k8s.io/apimachinery/pkg/runtime" 6 | ) 7 | 8 | func ToUnstructured(obj any) unstructured.Unstructured { 9 | data, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj) 10 | if err != nil { 11 | panic(err) 12 | } 13 | return unstructured.Unstructured{Object: data} 14 | } 15 | -------------------------------------------------------------------------------- /pkg/utils/kube/unstructured_test.go: -------------------------------------------------------------------------------- 1 | package kube 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 8 | "k8s.io/utils/ptr" 9 | ) 10 | 11 | func TestToUnstructured(t *testing.T) { 12 | var nilPtr *int 13 | assert.Panics(t, func() { 14 | ToUnstructured(nilPtr) 15 | }) 16 | assert.Equal(t, ToUnstructured(ptr.To(Namespace("foo"))), unstructured.Unstructured{ 17 | Object: map[string]any{ 18 | "apiVersion": "v1", 19 | "kind": "Namespace", 20 | "metadata": map[string]any{ 21 | "creationTimestamp": nil, 22 | "name": "foo", 23 | }, 24 | "spec": map[string]any{}, 25 | "status": map[string]any{}, 26 | }, 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/utils/maps/merge.go: -------------------------------------------------------------------------------- 1 | package maps 2 | 3 | func Merge(a, b map[string]any) map[string]any { 4 | out := make(map[string]any, len(a)) 5 | for k, v := range a { 6 | out[k] = v 7 | } 8 | for k, v := range b { 9 | if v, ok := v.(map[string]any); ok { 10 | if bv, ok := out[k]; ok { 11 | if bv, ok := bv.(map[string]any); ok { 12 | out[k] = Merge(bv, v) 13 | continue 14 | } 15 | } 16 | } 17 | out[k] = v 18 | } 19 | return out 20 | } 21 | -------------------------------------------------------------------------------- /pkg/utils/yaml/yaml.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "gopkg.in/yaml.v3" 5 | ) 6 | 7 | func remarshal(document []byte, unmarshal func(in []byte, out interface{}) (err error)) ([]byte, error) { 8 | if unmarshal == nil { 9 | unmarshal = yaml.Unmarshal 10 | } 11 | var pre map[string]any 12 | err := unmarshal(document, &pre) 13 | if err != nil { 14 | return nil, err 15 | } 16 | return yaml.Marshal(pre) 17 | } 18 | 19 | func Remarshal(document []byte) ([]byte, error) { 20 | return remarshal(document, nil) 21 | } 22 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | cairosvg 2 | lunr 3 | mike 4 | mkdocs 5 | mkdocs-include-markdown-plugin 6 | mkdocs-material 7 | mkdocs-minify-plugin 8 | mkdocs-redirects 9 | mkdocs-rss-plugin 10 | git+https://github.com/eddycharly/openapi2jsonschema.git@v3 11 | Pillow 12 | -------------------------------------------------------------------------------- /testdata/commands/assert/assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: quick-start 5 | data: 6 | foo: bar 7 | -------------------------------------------------------------------------------- /testdata/commands/build/docs/help.txt: -------------------------------------------------------------------------------- 1 | Build tests documentation 2 | 3 | Usage: 4 | chainsaw docs [flags] 5 | 6 | Flags: 7 | --catalog string Path to the built test catalog file 8 | -h, --help help for docs 9 | --readme-file string Name of the built docs file (default "README.md") 10 | --test-dir stringArray Directories containing test cases to run 11 | --test-file string Name of the test file (default "chainsaw-test") 12 | -------------------------------------------------------------------------------- /testdata/commands/build/help.txt: -------------------------------------------------------------------------------- 1 | Build commands 2 | 3 | Usage: 4 | chainsaw build [flags] 5 | chainsaw build [command] 6 | 7 | Available Commands: 8 | docs Build tests documentation 9 | 10 | Flags: 11 | -h, --help help for build 12 | 13 | Use "chainsaw build [command] --help" for more information about a command. 14 | -------------------------------------------------------------------------------- /testdata/commands/create/help.txt: -------------------------------------------------------------------------------- 1 | Create Chainsaw resources 2 | 3 | Usage: 4 | chainsaw create [flags] 5 | chainsaw create [command] 6 | 7 | Available Commands: 8 | test Create a Chainsaw test 9 | 10 | Flags: 11 | -h, --help help for create 12 | 13 | Use "chainsaw create [command] --help" for more information about a command. 14 | -------------------------------------------------------------------------------- /testdata/commands/create/test/help.txt: -------------------------------------------------------------------------------- 1 | Create a Chainsaw test 2 | 3 | Usage: 4 | chainsaw test [flags] 5 | 6 | Flags: 7 | --description If set, adds description when applicable (default true) 8 | --force If set, existing test will be deleted if needed 9 | -h, --help help for test 10 | --save If set, created test will be saved 11 | -------------------------------------------------------------------------------- /testdata/commands/docs/help.txt: -------------------------------------------------------------------------------- 1 | Generate reference documentation 2 | 3 | Usage: 4 | chainsaw docs [flags] 5 | 6 | Flags: 7 | --autogenTag Determines if the generated docs should contain a timestamp (default true) 8 | -h, --help help for docs 9 | -o, --output string Output path (default ".") 10 | --website Website version 11 | -------------------------------------------------------------------------------- /testdata/commands/docs/invalid-output.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/testdata/commands/docs/invalid-output.txt -------------------------------------------------------------------------------- /testdata/commands/export/help.txt: -------------------------------------------------------------------------------- 1 | Export commands 2 | 3 | Usage: 4 | chainsaw export [flags] 5 | chainsaw export [command] 6 | 7 | Available Commands: 8 | schemas Export JSON schemas 9 | 10 | Flags: 11 | -h, --help help for export 12 | 13 | Use "chainsaw export [command] --help" for more information about a command. 14 | -------------------------------------------------------------------------------- /testdata/commands/export/schemas/help.txt: -------------------------------------------------------------------------------- 1 | Export JSON schemas 2 | 3 | Usage: 4 | chainsaw schemas [flags] 5 | 6 | Flags: 7 | -h, --help help for schemas 8 | -------------------------------------------------------------------------------- /testdata/commands/lint/configuration/configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "apiVersion": "chainsaw.kyverno.io/v1alpha1", 3 | "kind": "Configuration", 4 | "metadata": { 5 | "name": "valid", 6 | "namespace": "kyverno" 7 | }, 8 | "spec": { 9 | "timeouts": { 10 | "apply": "5s", 11 | "assert": "10s", 12 | "error": "10s", 13 | "delete": "5s", 14 | "cleanup": "5s", 15 | "exec": "10s" 16 | }, 17 | "skipDelete": true, 18 | "failFast": true, 19 | "parallel": 5, 20 | "reportFormat": "JSON", 21 | "reportName": "custom-chainsaw-report", 22 | "namespace": "test-namespace", 23 | "fullName": true, 24 | "includeTestRegex": "^include-.*", 25 | "excludeTestRegex": "^exclude-.*" 26 | } 27 | } -------------------------------------------------------------------------------- /testdata/commands/lint/configuration/configuration.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: valid 5 | namespace: kyverno 6 | spec: 7 | timeouts: 8 | apply: 5s 9 | assert: 10s 10 | error: 10s 11 | delete: 5s 12 | cleanup: 5s 13 | exec: 10s 14 | skipDelete: true 15 | failFast: true 16 | parallel: 5 17 | reportFormat: JSON 18 | reportName: custom-chainsaw-report 19 | namespace: test-namespace 20 | fullName: true 21 | includeTestRegex: ^include-.* 22 | excludeTestRegex: ^exclude-.* 23 | -------------------------------------------------------------------------------- /testdata/commands/lint/configuration/pass.txt: -------------------------------------------------------------------------------- 1 | Processing input... 2 | The document is valid 3 | -------------------------------------------------------------------------------- /testdata/commands/lint/configuration/wrong-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "apiVersion": "chainsaw.kyverno.io/v1alpha2", 3 | "kind": "Configurations", 4 | "metadata": { 5 | "name": "valid", 6 | "namespace": "kyverno" 7 | }, 8 | "spec": { 9 | "timeouts": { 10 | "apply": "5s", 11 | "assert": "10s", 12 | "error": "10s", 13 | "delete": "5s", 14 | "cleanup": "5s", 15 | "exec": "10s" 16 | }, 17 | "skipDelete": true, 18 | "failFast": true, 19 | "parallel": 5, 20 | "reportFormat": "JSON", 21 | "reportName": "custom-chainsaw-report", 22 | "namespace": "test-namespace", 23 | "fullName": true, 24 | "includeTestRegex": "^include-.*", 25 | "excludeTestRegex": "^exclude-.*" 26 | } 27 | } -------------------------------------------------------------------------------- /testdata/commands/lint/configuration/wrong-configuration.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha2 2 | kind: Configurations 3 | metadata: 4 | name: valid 5 | namespace: kyverno 6 | spec: 7 | timeouts: 8 | apply: 5s 9 | assert: 10s 10 | error: 10s 11 | delete: 5s 12 | cleanup: 5s 13 | exec: 10s 14 | skipDelete: true 15 | failFast: true 16 | parallel: 5 17 | reportFormat: JSON 18 | reportName: custom-chainsaw-report 19 | namespace: test-namespace 20 | fullName: true 21 | includeTestRegex: ^include-.* 22 | excludeTestRegex: ^exclude-.* 23 | -------------------------------------------------------------------------------- /testdata/commands/lint/test/pass.txt: -------------------------------------------------------------------------------- 1 | Processing input... 2 | The document is valid 3 | -------------------------------------------------------------------------------- /testdata/commands/migrate/help.txt: -------------------------------------------------------------------------------- 1 | Migrate resources to Chainsaw 2 | 3 | Usage: 4 | chainsaw migrate [flags] 5 | chainsaw migrate [command] 6 | 7 | Available Commands: 8 | kuttl Migrate KUTTL resources to Chainsaw 9 | 10 | Flags: 11 | -h, --help help for migrate 12 | 13 | Use "chainsaw migrate [command] --help" for more information about a command. 14 | -------------------------------------------------------------------------------- /testdata/commands/migrate/kuttl/config/help.txt: -------------------------------------------------------------------------------- 1 | Migrate KUTTL config to Chainsaw 2 | 3 | Usage: 4 | chainsaw config [flags] 5 | 6 | Flags: 7 | --cleanup If set, delete converted files 8 | -h, --help help for config 9 | --save If set, converted files will be saved 10 | -------------------------------------------------------------------------------- /testdata/commands/migrate/kuttl/config/out-save.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/testdata/commands/migrate/kuttl/config/out-save.txt -------------------------------------------------------------------------------- /testdata/commands/migrate/kuttl/config/out.txt: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/configuration-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Configuration 4 | metadata: 5 | creationTimestamp: null 6 | name: configuration 7 | spec: 8 | parallel: 4 9 | template: false 10 | timeouts: 11 | apply: 5m0s 12 | assert: 5m0s 13 | cleanup: 5m0s 14 | delete: 5m0s 15 | error: 5m0s 16 | exec: 5m0s 17 | 18 | -------------------------------------------------------------------------------- /testdata/commands/migrate/kuttl/help.txt: -------------------------------------------------------------------------------- 1 | Migrate KUTTL resources to Chainsaw 2 | 3 | Usage: 4 | chainsaw kuttl [flags] 5 | chainsaw kuttl [command] 6 | 7 | Available Commands: 8 | config Migrate KUTTL config to Chainsaw 9 | tests Migrate KUTTL tests to Chainsaw 10 | 11 | Flags: 12 | -h, --help help for kuttl 13 | 14 | Use "chainsaw kuttl [command] --help" for more information about a command. 15 | -------------------------------------------------------------------------------- /testdata/commands/migrate/kuttl/tests/help.txt: -------------------------------------------------------------------------------- 1 | Migrate KUTTL tests to Chainsaw 2 | 3 | Usage: 4 | chainsaw tests [flags] 5 | 6 | Flags: 7 | --cleanup If set, delete converted files 8 | -h, --help help for tests 9 | --save If set, converted files will be saved 10 | -------------------------------------------------------------------------------- /testdata/commands/migrate/kuttl/tests/out-save.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/testdata/commands/migrate/kuttl/tests/out-save.txt -------------------------------------------------------------------------------- /testdata/commands/renovate/config/help.txt: -------------------------------------------------------------------------------- 1 | Upgrade Chainsaw configuration to the latest version 2 | 3 | Usage: 4 | chainsaw config [flags] 5 | 6 | Flags: 7 | -h, --help help for config 8 | --save If set, converted files will be saved 9 | -------------------------------------------------------------------------------- /testdata/commands/renovate/config/out-save.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/testdata/commands/renovate/config/out-save.txt -------------------------------------------------------------------------------- /testdata/commands/renovate/config/v1alpha1-default.txt: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/configuration-chainsaw-v1alpha2.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha2 3 | kind: Configuration 4 | metadata: 5 | name: default 6 | spec: 7 | report: 8 | name: chainsaw-report 9 | 10 | -------------------------------------------------------------------------------- /testdata/commands/renovate/help.txt: -------------------------------------------------------------------------------- 1 | Upgrade Chainsaw resources 2 | 3 | Usage: 4 | chainsaw renovate [flags] 5 | chainsaw renovate [command] 6 | 7 | Available Commands: 8 | config Upgrade Chainsaw configuration to the latest version 9 | 10 | Flags: 11 | -h, --help help for renovate 12 | 13 | Use "chainsaw renovate [command] --help" for more information about a command. 14 | -------------------------------------------------------------------------------- /testdata/commands/root/help.txt: -------------------------------------------------------------------------------- 1 | Stronger tool for e2e testing 2 | 3 | Usage: 4 | chainsaw [flags] 5 | 6 | Flags: 7 | -h, --help help for chainsaw 8 | -------------------------------------------------------------------------------- /testdata/commands/test/config/config_all_fields.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: valid 5 | namespace: kyverno 6 | spec: 7 | timeouts: 8 | apply: 5s 9 | assert: 10s 10 | error: 10s 11 | delete: 5s 12 | cleanup: 5s 13 | exec: 10s 14 | skipDelete: true 15 | failFast: true 16 | parallel: 5 17 | reportFormat: JSON 18 | reportName: custom-chainsaw-report 19 | namespace: test-namespace 20 | fullName: true 21 | includeTestRegex: ^include-.* 22 | excludeTestRegex: ^exclude-.* 23 | -------------------------------------------------------------------------------- /testdata/commands/test/config/empty_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: default 5 | namespace: kyverno 6 | -------------------------------------------------------------------------------- /testdata/commands/test/config/wrong_format_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: default 5 | namespace: kyverno 6 | spec: 7 | foo: bar 8 | -------------------------------------------------------------------------------- /testdata/commands/test/config/wrong_kind_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: foo 3 | metadata: 4 | name: default 5 | namespace: kyverno 6 | -------------------------------------------------------------------------------- /testdata/commands/test/default.txt: -------------------------------------------------------------------------------- 1 | Version: --- 2 | Loading default configuration... 3 | - Using test file: chainsaw-test 4 | - TestDirs [.] 5 | - SkipDelete false 6 | - FailFast false 7 | - Namespace '' 8 | - FullName false 9 | - IncludeTestRegex '' 10 | - ExcludeTestRegex '' 11 | - ApplyTimeout 5s 12 | - AssertTimeout 30s 13 | - CleanupTimeout 30s 14 | - DeleteTimeout 15s 15 | - ErrorTimeout 30s 16 | - ExecTimeout 5s 17 | - DeletionPropagationPolicy Background 18 | - Template true 19 | - NoCluster false 20 | - PauseOnFailure false 21 | Loading tests... 22 | Loading values... 23 | Running tests... 24 | Tests Summary... 25 | - Passed tests 0 26 | - Failed tests 0 27 | - Skipped tests 0 28 | Done. 29 | -------------------------------------------------------------------------------- /testdata/commands/test/with_regex.txt: -------------------------------------------------------------------------------- 1 | Version: --- 2 | Loading default configuration... 3 | - Using test file: chainsaw-test 4 | - TestDirs [.] 5 | - SkipDelete false 6 | - FailFast false 7 | - Namespace '' 8 | - FullName false 9 | - IncludeTestRegex 'test[4-6]' 10 | - ExcludeTestRegex 'test[1-3]' 11 | - ApplyTimeout 5s 12 | - AssertTimeout 30s 13 | - CleanupTimeout 30s 14 | - DeleteTimeout 15s 15 | - ErrorTimeout 30s 16 | - ExecTimeout 5s 17 | - DeletionPropagationPolicy Background 18 | - Template true 19 | - NoCluster false 20 | - PauseOnFailure false 21 | Loading tests... 22 | Loading values... 23 | Running tests... 24 | Tests Summary... 25 | - Passed tests 0 26 | - Failed tests 0 27 | - Skipped tests 0 28 | Done. 29 | -------------------------------------------------------------------------------- /testdata/commands/test/with_repeat_count.txt: -------------------------------------------------------------------------------- 1 | Version: --- 2 | Loading default configuration... 3 | - Using test file: chainsaw-test 4 | - TestDirs [.] 5 | - SkipDelete false 6 | - FailFast false 7 | - Namespace '' 8 | - FullName false 9 | - IncludeTestRegex '' 10 | - ExcludeTestRegex '' 11 | - ApplyTimeout 5s 12 | - AssertTimeout 30s 13 | - CleanupTimeout 30s 14 | - DeleteTimeout 15s 15 | - ErrorTimeout 30s 16 | - ExecTimeout 5s 17 | - DeletionPropagationPolicy Background 18 | - RepeatCount 3 19 | - Template true 20 | - NoCluster false 21 | - PauseOnFailure false 22 | Loading tests... 23 | Loading values... 24 | Running tests... 25 | Tests Summary... 26 | - Passed tests 0 27 | - Failed tests 0 28 | - Skipped tests 0 29 | Done. 30 | -------------------------------------------------------------------------------- /testdata/commands/test/with_suppress.txt: -------------------------------------------------------------------------------- 1 | Version: --- 2 | Loading default configuration... 3 | - Using test file: chainsaw-test 4 | - Timeout 30s 5 | - TestDirs [.] 6 | - SkipDelete false 7 | - FailFast false 8 | - ReportFormat '' 9 | - ReportName '' 10 | - Namespace '' 11 | - FullName false 12 | - IncludeTestRegex '' 13 | - ExcludeTestRegex '' 14 | - ApplyTimeout 5s 15 | - AssertTimeout 30s 16 | - CleanupTimeout 30s 17 | - DeleteTimeout 15s 18 | - ErrorTimeout 30s 19 | - ExecTimeout 5s 20 | - DeletionPropagationPolicy Background 21 | - Template true 22 | - NoCluster false 23 | - PauseOnFailure false 24 | Loading tests... 25 | Loading values... 26 | Running tests... 27 | Tests Summary... 28 | - Passed tests 0 29 | - Failed tests 0 30 | - Skipped tests 0 31 | Done. 32 | -------------------------------------------------------------------------------- /testdata/commands/test/with_test_dirs.txt: -------------------------------------------------------------------------------- 1 | Version: --- 2 | Loading default configuration... 3 | - Using test file: chainsaw-test 4 | - TestDirs [.. .] 5 | - SkipDelete false 6 | - FailFast false 7 | - Namespace '' 8 | - FullName false 9 | - IncludeTestRegex '' 10 | - ExcludeTestRegex '' 11 | - ApplyTimeout 5s 12 | - AssertTimeout 30s 13 | - CleanupTimeout 30s 14 | - DeleteTimeout 15s 15 | - ErrorTimeout 30s 16 | - ExecTimeout 5s 17 | - DeletionPropagationPolicy Background 18 | - Template true 19 | - NoCluster false 20 | - PauseOnFailure false 21 | Loading tests... 22 | Loading values... 23 | Running tests... 24 | Tests Summary... 25 | - Passed tests 0 26 | - Failed tests 0 27 | - Skipped tests 0 28 | Done. 29 | -------------------------------------------------------------------------------- /testdata/commands/test/with_timeout.txt: -------------------------------------------------------------------------------- 1 | Version: --- 2 | Loading default configuration... 3 | - Using test file: chainsaw-test 4 | - TestDirs [.] 5 | - SkipDelete false 6 | - FailFast false 7 | - Namespace '' 8 | - FullName false 9 | - IncludeTestRegex '' 10 | - ExcludeTestRegex '' 11 | - ApplyTimeout 10s 12 | - AssertTimeout 30s 13 | - CleanupTimeout 30s 14 | - DeleteTimeout 15s 15 | - ErrorTimeout 30s 16 | - ExecTimeout 5s 17 | - DeletionPropagationPolicy Background 18 | - Template true 19 | - NoCluster false 20 | - PauseOnFailure false 21 | Loading tests... 22 | Loading values... 23 | Running tests... 24 | Tests Summary... 25 | - Passed tests 0 26 | - Failed tests 0 27 | - Skipped tests 0 28 | Done. 29 | -------------------------------------------------------------------------------- /testdata/commands/test/wrong_format_config.txt: -------------------------------------------------------------------------------- 1 | Version: --- 2 | Loading config (../../../testdata/commands/test/config/wrong_format_config.yaml)... 3 | -------------------------------------------------------------------------------- /testdata/commands/test/wrong_kind_config.txt: -------------------------------------------------------------------------------- 1 | Version: --- 2 | Loading config (../../../testdata/commands/test/config/wrong_kind_config.yaml)... 3 | -------------------------------------------------------------------------------- /testdata/commands/test/wrong_kind_config_err.txt: -------------------------------------------------------------------------------- 1 | Error: failed to load configuration (failed to parse document (failed to retrieve validator: kind foo not found in chainsaw.kyverno.io/v1alpha1 groupversion)) 2 | -------------------------------------------------------------------------------- /testdata/commands/version/help.txt: -------------------------------------------------------------------------------- 1 | Print the version informations 2 | 3 | Usage: 4 | chainsaw version [flags] 5 | 6 | Flags: 7 | -h, --help help for version 8 | -------------------------------------------------------------------------------- /testdata/commands/version/out.txt: -------------------------------------------------------------------------------- 1 | Version: --- 2 | Time: --- 3 | Git commit ID: --- 4 | -------------------------------------------------------------------------------- /testdata/config/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: default 5 | data: 6 | foo: bar -------------------------------------------------------------------------------- /testdata/config/empty.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/testdata/config/empty.yaml -------------------------------------------------------------------------------- /testdata/config/multiple.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: default 5 | spec: {} 6 | --- 7 | apiVersion: chainsaw.kyverno.io/v1alpha1 8 | kind: Configuration 9 | metadata: 10 | name: timeout-1m 11 | spec: 12 | timeouts: 13 | assert: 1m 14 | -------------------------------------------------------------------------------- /testdata/config/v1alpha1/bad-catch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: default 5 | spec: 6 | catch: 7 | - description: this is a bad catch because it contains two actions 8 | sleep: 9 | duration: 1m 10 | events: {} 11 | -------------------------------------------------------------------------------- /testdata/config/v1alpha1/custom-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: custom-config 5 | spec: 6 | timeouts: 7 | apply: 5s 8 | assert: 10s 9 | error: 10s 10 | delete: 5s 11 | cleanup: 5s 12 | exec: 10s 13 | skipDelete: true 14 | testFile: custom-test.yaml 15 | failFast: true 16 | parallel: 4 17 | reportFormat: "JSON" 18 | reportName: "custom-report" 19 | fullName: true 20 | includeTestRegex: "include-*" 21 | excludeTestRegex: "exclude-*" 22 | forceTerminationGracePeriod: 10s 23 | -------------------------------------------------------------------------------- /testdata/config/v1alpha1/default.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: default 5 | spec: {} -------------------------------------------------------------------------------- /testdata/discovery/empty-test/fake.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/testdata/discovery/empty-test/fake.json -------------------------------------------------------------------------------- /testdata/discovery/manifests/01-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: chainsaw-quick-start 5 | data: 6 | foo: bar 7 | -------------------------------------------------------------------------------- /testdata/discovery/manifests/01-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: chainsaw-quick-start 5 | data: 6 | foo: bar 7 | -------------------------------------------------------------------------------- /testdata/discovery/manifests/01-errors.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: chainsaw-quick-start 5 | data: 6 | foo: bar 7 | -------------------------------------------------------------------------------- /testdata/discovery/multiple-tests/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Test 3 | metadata: 4 | name: test-1 5 | spec: 6 | steps: 7 | - name: create configmap 8 | try: 9 | - apply: 10 | file: configmap.yaml 11 | - name: assert configmap 12 | try: 13 | - assert: 14 | file: configmap.yaml 15 | --- 16 | apiVersion: chainsaw.kyverno.io/v1alpha1 17 | kind: Test 18 | metadata: 19 | name: test-2 20 | spec: 21 | steps: 22 | - name: create configmap 23 | try: 24 | - apply: 25 | file: configmap.yaml 26 | - name: assert configmap 27 | try: 28 | - assert: 29 | file: configmap.yaml 30 | -------------------------------------------------------------------------------- /testdata/discovery/not-a-test/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: chainsaw-quick-start 5 | data: 6 | foo: bar 7 | -------------------------------------------------------------------------------- /testdata/discovery/test-yml/chainsaw-test.yml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Test 3 | metadata: 4 | name: test 5 | spec: 6 | steps: 7 | - name: create configmap 8 | try: 9 | - apply: 10 | file: configmap.yaml 11 | - name: assert configmap 12 | try: 13 | - assert: 14 | file: configmap.yaml 15 | -------------------------------------------------------------------------------- /testdata/discovery/test/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Test 3 | metadata: 4 | name: test 5 | spec: 6 | steps: 7 | - name: create configmap 8 | try: 9 | - apply: 10 | file: configmap.yaml 11 | - name: assert configmap 12 | try: 13 | - assert: 14 | file: configmap.yaml 15 | -------------------------------------------------------------------------------- /testdata/e2e/config.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../.schemas/json/configuration-chainsaw-v1alpha2.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha2 3 | kind: Configuration 4 | metadata: 5 | name: configuration 6 | spec: 7 | discovery: 8 | fullName: true 9 | execution: 10 | failFast: true 11 | forceTerminationGracePeriod: 5s 12 | parallel: 1 13 | namespace: 14 | compiler: cel 15 | template: 16 | metadata: 17 | annotations: 18 | from-config-file: (string("hello")) 19 | -------------------------------------------------------------------------------- /testdata/e2e/examples/apply-outputs/resources.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: first 5 | data: 6 | foo: bar 7 | --- 8 | apiVersion: v1 9 | kind: ConfigMap 10 | metadata: 11 | name: second 12 | data: 13 | foo: bar 14 | -------------------------------------------------------------------------------- /testdata/e2e/examples/array-assertion/README.md: -------------------------------------------------------------------------------- 1 | # Test: `array-assertions` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 2 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | | 2 | `assert` | 0 | 0 | *No description* | 21 | 22 | --- 23 | 24 | -------------------------------------------------------------------------------- /testdata/e2e/examples/array-assertion/assertions.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: example 5 | spec: 6 | # iterate over all containers having `name: container-1` 7 | ~.(containers[?name == 'container-1']): 8 | image: nginx-1 9 | # iterate over all containers, bind `$index` to the element index 10 | ~index.(containers): 11 | image: (join('-', ['nginx', to_string($index + `1`)])) 12 | # nested iteration 13 | ~index2.(containers): 14 | ~.(env): 15 | name: (join('_', ['ENV', to_string($index2 + `1`)])) 16 | value: (join('-', ['value', to_string($index2 + `1`)])) 17 | -------------------------------------------------------------------------------- /testdata/e2e/examples/array-assertion/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: array-assertions 6 | spec: 7 | steps: 8 | - try: 9 | - apply: 10 | file: resources.yaml 11 | - assert: 12 | file: assertions.yaml 13 | -------------------------------------------------------------------------------- /testdata/e2e/examples/array-assertion/resources.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: example 5 | spec: 6 | containers: 7 | - name: container-1 8 | image: nginx-1 9 | env: 10 | - name: ENV_1 11 | value: value-1 12 | - name: container-2 13 | image: nginx-2 14 | env: 15 | - name: ENV_2 16 | value: value-2 17 | - name: container-3 18 | image: nginx-3 19 | env: 20 | - name: ENV_3 21 | value: value-3 22 | -------------------------------------------------------------------------------- /testdata/e2e/examples/assertion-tree/README.md: -------------------------------------------------------------------------------- 1 | # Test: `assertion-tree` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 1 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `assert` | 0 | 0 | *No description* | 20 | 21 | --- 22 | 23 | -------------------------------------------------------------------------------- /testdata/e2e/examples/assertion-tree/assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | k8s-app: kube-dns 6 | namespace: kube-system 7 | spec: 8 | template: 9 | (spec)->specBinding: 10 | # the ~ modifier tells Chainsaw to iterate over the array elements 11 | ~.(containers): 12 | ($specBinding.securityContext != null || securityContext != null): true 13 | -------------------------------------------------------------------------------- /testdata/e2e/examples/assertion-tree/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: assertion-tree 6 | spec: 7 | steps: 8 | - try: 9 | - assert: 10 | file: assert.yaml 11 | -------------------------------------------------------------------------------- /testdata/e2e/examples/basic/README.md: -------------------------------------------------------------------------------- 1 | # Test: `basic` 2 | 3 | This is a very simple test that creates a configmap and checks the content is as expected. 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 3 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | This steps applies the configmap in the cluster and checks the configmap content. 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | Create the configmap. | 20 | | 2 | `assert` | 0 | 0 | Check the configmap content. | 21 | | 3 | `script` | 0 | 0 | *No description* | 22 | 23 | --- 24 | 25 | -------------------------------------------------------------------------------- /testdata/e2e/examples/basic/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: basic 6 | spec: 7 | description: This is a very simple test that creates a configmap and checks the content is as expected. 8 | steps: 9 | - description: This steps applies the configmap in the cluster and checks the configmap content. 10 | try: 11 | - description: Create the configmap. 12 | apply: 13 | file: configmap.yaml 14 | - description: Check the configmap content. 15 | assert: 16 | file: configmap-assert.yaml 17 | - script: 18 | content: cd .. && kubectl get pod -A -------------------------------------------------------------------------------- /testdata/e2e/examples/basic/configmap-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: quick-start 5 | data: 6 | foo: bar 7 | -------------------------------------------------------------------------------- /testdata/e2e/examples/basic/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: quick-start 5 | data: 6 | foo: bar 7 | -------------------------------------------------------------------------------- /testdata/e2e/examples/catch/README.md: -------------------------------------------------------------------------------- 1 | # Test: `catch` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 2 | 2 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | | 2 | `assert` | 0 | 0 | *No description* | 21 | 22 | #### Catch 23 | 24 | | # | Operation | Bindings | Outputs | Description | 25 | |:-:|---|:-:|:-:|---| 26 | | 1 | `events` | 0 | 0 | *No description* | 27 | | 2 | `describe` | 0 | 0 | *No description* | 28 | 29 | --- 30 | 31 | -------------------------------------------------------------------------------- /testdata/e2e/examples/command-output/README.md: -------------------------------------------------------------------------------- 1 | # Test: `command-output` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [Check bad kubectl command](#step-Check bad kubectl command) | 0 | 1 | 0 | 0 | 0 | 10 | 11 | ### Step: `Check bad kubectl command` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `script` | 0 | 0 | *No description* | 20 | 21 | --- 22 | 23 | -------------------------------------------------------------------------------- /testdata/e2e/examples/command-output/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: command-output 6 | spec: 7 | steps: 8 | - name: Check bad kubectl command 9 | try: 10 | - script: 11 | content: kubectl foo 12 | check: 13 | # This checks that the result of the content was an error. 14 | ($error != null): true 15 | # This check below ensures that the string 'top' is found in stderr or else fails 16 | (contains($stderr, 'top')): true 17 | -------------------------------------------------------------------------------- /testdata/e2e/examples/delete/cms.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: quick-start 5 | data: 6 | foo: bar 7 | --- 8 | apiVersion: v1 9 | kind: ConfigMap 10 | metadata: 11 | name: quick-start-2 12 | data: 13 | foo: bar 14 | -------------------------------------------------------------------------------- /testdata/e2e/examples/deployment/README.md: -------------------------------------------------------------------------------- 1 | # Test: `deployment` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 2 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | | 2 | `assert` | 0 | 0 | *No description* | 21 | 22 | --- 23 | 24 | -------------------------------------------------------------------------------- /testdata/e2e/examples/deployment/assertions.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | labels: 5 | app: nginx 6 | spec: {} -------------------------------------------------------------------------------- /testdata/e2e/examples/deployment/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: deployment 6 | spec: 7 | steps: 8 | - try: 9 | - apply: 10 | file: resources.yaml 11 | - assert: 12 | file: assertions.yaml 13 | -------------------------------------------------------------------------------- /testdata/e2e/examples/deployment/resources.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: example 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: nginx 9 | template: 10 | metadata: 11 | labels: 12 | app: nginx 13 | spec: 14 | containers: 15 | - name: nginx 16 | image: nginx:1.14.2 17 | -------------------------------------------------------------------------------- /testdata/e2e/examples/field-validation/README.md: -------------------------------------------------------------------------------- 1 | # Test: `field-validation` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 1 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | 21 | --- 22 | 23 | -------------------------------------------------------------------------------- /testdata/e2e/examples/field-validation/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: field-validation 6 | spec: 7 | steps: 8 | - try: 9 | - apply: 10 | resource: 11 | apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: chainsaw-quick-start 15 | data: 16 | foo: bar 17 | bar: baz 18 | expect: 19 | - check: 20 | ($error): |- 21 | ConfigMap in version "v1" cannot be handled as a ConfigMap: strict decoding error: unknown field "bar" 22 | -------------------------------------------------------------------------------- /testdata/e2e/examples/finally/README.md: -------------------------------------------------------------------------------- 1 | # Test: `finally` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 2 | 0 | 2 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | | 2 | `assert` | 0 | 0 | *No description* | 21 | 22 | #### Finally 23 | 24 | | # | Operation | Bindings | Outputs | Description | 25 | |:-:|---|:-:|:-:|---| 26 | | 1 | `events` | 0 | 0 | *No description* | 27 | | 2 | `script` | 0 | 0 | *No description* | 28 | 29 | --- 30 | 31 | -------------------------------------------------------------------------------- /testdata/e2e/examples/inline/README.md: -------------------------------------------------------------------------------- 1 | # Test: `inline` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 2 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | | 2 | `assert` | 0 | 0 | *No description* | 21 | 22 | --- 23 | 24 | -------------------------------------------------------------------------------- /testdata/e2e/examples/inline/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: inline 6 | spec: 7 | steps: 8 | - try: 9 | - apply: 10 | resource: 11 | apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: quick-start 15 | data: 16 | foo: bar 17 | - assert: 18 | resource: 19 | apiVersion: v1 20 | kind: ConfigMap 21 | metadata: 22 | name: quick-start 23 | data: 24 | foo: bar 25 | -------------------------------------------------------------------------------- /testdata/e2e/examples/jmespath-label-condition/README.md: -------------------------------------------------------------------------------- 1 | # Test: `jmespath-label-condition` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 2 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | | 2 | `assert` | 0 | 0 | *No description* | 21 | 22 | --- 23 | 24 | -------------------------------------------------------------------------------- /testdata/e2e/examples/jmespath-label-condition/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: jmespath-label-condition 6 | spec: 7 | steps: 8 | - try: 9 | - apply: 10 | resource: 11 | apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: jmespath-label-condition 15 | labels: 16 | type: my-first-configmap 17 | - assert: 18 | resource: 19 | apiVersion: v1 20 | kind: ConfigMap 21 | metadata: 22 | labels: 23 | type: 24 | (starts_with(@, 'my-first-')): true 25 | -------------------------------------------------------------------------------- /testdata/e2e/examples/k8s-server-version/README.md: -------------------------------------------------------------------------------- 1 | # Test: `k8s-server-version` 2 | 3 | *No description* 4 | 5 | ## Bindings 6 | 7 | | # | Name | Value | 8 | |:-:|---|---| 9 | | 1 | `version` | "(x_k8s_server_version($config))" | 10 | 11 | ## Steps 12 | 13 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 14 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 15 | | 1 | [step-1](#step-step-1) | 0 | 1 | 0 | 0 | 0 | 16 | 17 | ### Step: `step-1` 18 | 19 | *No description* 20 | 21 | #### Try 22 | 23 | | # | Operation | Bindings | Outputs | Description | 24 | |:-:|---|:-:|:-:|---| 25 | | 1 | `script` | 0 | 0 | *No description* | 26 | 27 | --- 28 | 29 | -------------------------------------------------------------------------------- /testdata/e2e/examples/k8s-server-version/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: k8s-server-version 6 | spec: 7 | bindings: 8 | - name: version 9 | value: (x_k8s_server_version($config)) 10 | steps: 11 | - try: 12 | - script: 13 | env: 14 | - name: K8S_VERSION 15 | value: (to_string($version)) 16 | content: | 17 | set -e 18 | echo $K8S_VERSION 19 | -------------------------------------------------------------------------------- /testdata/e2e/examples/list/README.md: -------------------------------------------------------------------------------- 1 | # Test: `list` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 3 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | | 2 | `assert` | 0 | 0 | *No description* | 21 | | 3 | `assert` | 0 | 0 | *No description* | 22 | 23 | --- 24 | 25 | -------------------------------------------------------------------------------- /testdata/e2e/examples/list/list.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: List 3 | items: 4 | - apiVersion: v1 5 | kind: ConfigMap 6 | metadata: 7 | name: cm-1 8 | namespace: default 9 | data: 10 | key: 'yes' 11 | - apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: cm-2 15 | namespace: default 16 | data: 17 | key: 'no' 18 | -------------------------------------------------------------------------------- /testdata/e2e/examples/namespace-template-config/README.md: -------------------------------------------------------------------------------- 1 | # Test: `namespace-template-config` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 1 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `assert` | 0 | 0 | *No description* | 20 | 21 | --- 22 | 23 | -------------------------------------------------------------------------------- /testdata/e2e/examples/namespace-template-config/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: namespace-template-config 6 | spec: 7 | steps: 8 | - try: 9 | - assert: 10 | resource: 11 | apiVersion: v1 12 | kind: Namespace 13 | metadata: 14 | annotations: 15 | from-config-file: hello 16 | -------------------------------------------------------------------------------- /testdata/e2e/examples/namespace-template/README.md: -------------------------------------------------------------------------------- 1 | # Test: `namespace-template` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 1 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `assert` | 0 | 0 | *No description* | 20 | 21 | --- 22 | 23 | -------------------------------------------------------------------------------- /testdata/e2e/examples/namespace-template/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: namespace-template 6 | spec: 7 | namespaceTemplate: 8 | metadata: 9 | name: foo 10 | annotations: 11 | keptn.sh/lifecycle-toolkit: enabled 12 | steps: 13 | - try: 14 | - assert: 15 | resource: 16 | apiVersion: v1 17 | kind: Namespace 18 | metadata: 19 | name: foo 20 | annotations: 21 | keptn.sh/lifecycle-toolkit: enabled 22 | -------------------------------------------------------------------------------- /testdata/e2e/examples/negative-testing/resource/README.md: -------------------------------------------------------------------------------- 1 | # Test: `negative-resource` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 1 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | 21 | --- 22 | 23 | -------------------------------------------------------------------------------- /testdata/e2e/examples/negative-testing/resource/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: negative-resource 6 | spec: 7 | steps: 8 | - try: 9 | - apply: 10 | file: resources.yaml 11 | expect: 12 | - match: 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | name: bad 17 | check: 18 | ($error != null): true 19 | -------------------------------------------------------------------------------- /testdata/e2e/examples/negative-testing/resource/resources.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: good 5 | data: 6 | foo: bar 7 | --- 8 | apiVersion: v1 9 | kind: ConfigMap 10 | metadata: 11 | name: bad 12 | data: 13 | foo: true 14 | -------------------------------------------------------------------------------- /testdata/e2e/examples/negative-testing/script/README.md: -------------------------------------------------------------------------------- 1 | # Test: `negative-script` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 1 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `script` | 0 | 0 | *No description* | 20 | 21 | --- 22 | 23 | -------------------------------------------------------------------------------- /testdata/e2e/examples/negative-testing/script/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: negative-script 6 | spec: 7 | steps: 8 | - try: 9 | - script: 10 | content: kubectl get foo 11 | check: 12 | ($error != null): true 13 | ($stderr): | 14 | error: the server doesn't have a resource type "foo" 15 | -------------------------------------------------------------------------------- /testdata/e2e/examples/non-resource-assertion/assert.yaml: -------------------------------------------------------------------------------- 1 | (x_k8s_list($client, 'v1', 'Node')): 2 | (length(items)): 1 3 | -------------------------------------------------------------------------------- /testdata/e2e/examples/non-resource-assertion/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: non-resource-assertion 6 | spec: 7 | steps: 8 | - try: 9 | - assert: 10 | file: assert.yaml 11 | - error: 12 | file: error.yaml 13 | - try: 14 | - assert: 15 | resource: 16 | (x_k8s_list($client, 'v1', 'Node')): 17 | (length(items)): 1 18 | - error: 19 | resource: 20 | (x_k8s_list($client, 'v1', 'Node')): 21 | (length(items)): 2 22 | -------------------------------------------------------------------------------- /testdata/e2e/examples/non-resource-assertion/error.yaml: -------------------------------------------------------------------------------- 1 | (x_k8s_list($client, 'v1', 'Node')): 2 | (length(items)): 2 3 | -------------------------------------------------------------------------------- /testdata/e2e/examples/orphan/README.md: -------------------------------------------------------------------------------- 1 | # Test: `delete-test` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [delete-test](#step-delete-test) | 0 | 5 | 0 | 0 | 0 | 10 | 11 | ### Step: `delete-test` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | | 2 | `sleep` | 0 | 0 | *No description* | 21 | | 3 | `delete` | 0 | 0 | *No description* | 22 | | 4 | `sleep` | 0 | 0 | *No description* | 23 | | 5 | `error` | 0 | 0 | *No description* | 24 | 25 | --- 26 | 27 | -------------------------------------------------------------------------------- /testdata/e2e/examples/patch/README.md: -------------------------------------------------------------------------------- 1 | # Test: `patch` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 3 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | | 2 | `patch` | 0 | 0 | *No description* | 21 | | 3 | `assert` | 0 | 0 | *No description* | 22 | 23 | --- 24 | 25 | -------------------------------------------------------------------------------- /testdata/e2e/examples/proxy/README.md: -------------------------------------------------------------------------------- 1 | # Test: `proxy` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 2 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `proxy` | 0 | 1 | *No description* | 20 | | 2 | `assert` | 0 | 0 | *No description* | 21 | 22 | --- 23 | 24 | -------------------------------------------------------------------------------- /testdata/e2e/examples/proxy/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: proxy 6 | spec: 7 | skip: true 8 | steps: 9 | - try: 10 | - proxy: 11 | apiVersion: v1 12 | kind: Service 13 | namespace: kyverno 14 | name: kyverno-svc-metrics 15 | port: metrics-port 16 | path: /metrics 17 | outputs: 18 | - name: metrics 19 | value: (x_metrics_decode($stdout)) 20 | - assert: 21 | resource: 22 | ($metrics[?as_string(metric.code) == '500' && as_string(metric.__name__) == 'promhttp_metric_handler_requests_total'].value): 23 | - 0 24 | -------------------------------------------------------------------------------- /testdata/e2e/examples/quick-start/README.md: -------------------------------------------------------------------------------- 1 | # Test: `quick-start` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 2 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | | 2 | `assert` | 0 | 0 | *No description* | 21 | 22 | --- 23 | 24 | -------------------------------------------------------------------------------- /testdata/e2e/examples/quick-start/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: quick-start 6 | spec: 7 | steps: 8 | - try: 9 | # first operation: create the config map 10 | - apply: 11 | # file is relative to the test folder 12 | file: configmap.yaml 13 | # second operation: verify the config map exists and contains the expected data 14 | - assert: 15 | # file is relative to the test folder 16 | file: configmap.yaml 17 | -------------------------------------------------------------------------------- /testdata/e2e/examples/quick-start/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: chainsaw-quick-start 5 | data: 6 | foo: bar 7 | -------------------------------------------------------------------------------- /testdata/e2e/examples/script-env/README.md: -------------------------------------------------------------------------------- 1 | # Test: `script-env` 2 | 3 | *No description* 4 | 5 | ## Bindings 6 | 7 | | # | Name | Value | 8 | |:-:|---|---| 9 | | 1 | `chainsaw` | "chainsaw" | 10 | 11 | ## Steps 12 | 13 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 14 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 15 | | 1 | [step-1](#step-step-1) | 1 | 2 | 0 | 0 | 0 | 16 | 17 | ### Step: `step-1` 18 | 19 | *No description* 20 | 21 | #### Bindings 22 | 23 | | # | Name | Value | 24 | |:-:|---|---| 25 | | 1 | `hello` | "hello" | 26 | 27 | #### Try 28 | 29 | | # | Operation | Bindings | Outputs | Description | 30 | |:-:|---|:-:|:-:|---| 31 | | 1 | `script` | 0 | 0 | *No description* | 32 | | 2 | `command` | 0 | 0 | *No description* | 33 | 34 | --- 35 | 36 | -------------------------------------------------------------------------------- /testdata/e2e/examples/sleep/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: sleep 6 | spec: 7 | steps: 8 | - try: 9 | - sleep: 10 | duration: 10s 11 | catch: 12 | - sleep: 13 | duration: 5s 14 | finally: 15 | - sleep: 16 | duration: 5s 17 | -------------------------------------------------------------------------------- /testdata/e2e/examples/step-template-bindings/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: step-template-bindings 6 | spec: 7 | steps: 8 | - use: 9 | template: template.yaml 10 | with: 11 | bindings: 12 | - name: input 13 | value: from-test 14 | - try: 15 | - assert: 16 | resource: 17 | apiVersion: v1 18 | kind: ConfigMap 19 | metadata: 20 | name: from-test 21 | -------------------------------------------------------------------------------- /testdata/e2e/examples/step-template-bindings/template.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/steptemplate-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: StepTemplate 4 | metadata: 5 | name: template 6 | spec: 7 | bindings: 8 | - name: input 9 | value: from-template 10 | try: 11 | - create: 12 | resource: 13 | apiVersion: v1 14 | kind: ConfigMap 15 | metadata: 16 | name: ($input) 17 | -------------------------------------------------------------------------------- /testdata/e2e/examples/step-template/README.md: -------------------------------------------------------------------------------- 1 | # Test: `quick-start` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 1 | 2 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Bindings 16 | 17 | | # | Name | Value | 18 | |:-:|---|---| 19 | | 1 | `file` | "configmap.yaml" | 20 | 21 | #### Try 22 | 23 | | # | Operation | Bindings | Outputs | Description | 24 | |:-:|---|:-:|:-:|---| 25 | | 1 | `apply` | 0 | 0 | *No description* | 26 | | 2 | `assert` | 0 | 0 | *No description* | 27 | 28 | --- 29 | 30 | -------------------------------------------------------------------------------- /testdata/e2e/examples/step-template/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: quick-start 6 | spec: 7 | steps: 8 | - use: 9 | template: step-template.yaml 10 | with: 11 | bindings: 12 | - name: file 13 | value: configmap.yaml 14 | -------------------------------------------------------------------------------- /testdata/e2e/examples/step-template/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: chainsaw-quick-start 5 | data: 6 | foo: bar 7 | -------------------------------------------------------------------------------- /testdata/e2e/examples/step-template/step-template.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/steptemplate-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: StepTemplate 4 | metadata: 5 | name: quick-start 6 | spec: 7 | try: 8 | # first operation: create the config map 9 | - apply: 10 | # file is relative to the test folder 11 | file: ($file) 12 | # second operation: verify the config map exists and contains the expected data 13 | - assert: 14 | # file is relative to the test folder 15 | file: ($file) 16 | -------------------------------------------------------------------------------- /testdata/e2e/examples/template/README.md: -------------------------------------------------------------------------------- 1 | # Test: `template` 2 | 3 | *No description* 4 | 5 | ## Bindings 6 | 7 | | # | Name | Value | 8 | |:-:|---|---| 9 | | 1 | `foo` | "(join('-', [$namespace, 'foo']))" | 10 | 11 | ## Steps 12 | 13 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 14 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 15 | | 1 | [step-1](#step-step-1) | 0 | 3 | 0 | 0 | 0 | 16 | 17 | ### Step: `step-1` 18 | 19 | *No description* 20 | 21 | #### Try 22 | 23 | | # | Operation | Bindings | Outputs | Description | 24 | |:-:|---|:-:|:-:|---| 25 | | 1 | `apply` | 0 | 0 | *No description* | 26 | | 2 | `assert` | 0 | 0 | *No description* | 27 | | 3 | `delete` | 0 | 0 | *No description* | 28 | 29 | --- 30 | 31 | -------------------------------------------------------------------------------- /testdata/e2e/examples/test-info/README.md: -------------------------------------------------------------------------------- 1 | # Test: `test-info` 2 | 3 | *No description* 4 | 5 | ## Bindings 6 | 7 | | # | Name | Value | 8 | |:-:|---|---| 9 | | 1 | `foo` | "(join('-', [$test.metadata.name, 'foo']))" | 10 | 11 | ## Steps 12 | 13 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 14 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 15 | | 1 | [step-1](#step-step-1) | 0 | 2 | 0 | 0 | 0 | 16 | 17 | ### Step: `step-1` 18 | 19 | *No description* 20 | 21 | #### Try 22 | 23 | | # | Operation | Bindings | Outputs | Description | 24 | |:-:|---|:-:|:-:|---| 25 | | 1 | `script` | 0 | 1 | *No description* | 26 | | 2 | `assert` | 0 | 0 | *No description* | 27 | 28 | --- 29 | 30 | -------------------------------------------------------------------------------- /testdata/e2e/examples/test-info/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: test-info 6 | spec: 7 | bindings: 8 | - name: foo 9 | value: (join('-', [$test.metadata.name, 'foo'])) 10 | steps: 11 | - try: 12 | - script: 13 | env: 14 | - name: FOO 15 | value: ($foo) 16 | outputs: 17 | - name: OUTPUT 18 | value: ($stdout) 19 | content: echo $FOO 20 | - assert: 21 | resource: 22 | (trim_space($OUTPUT)): test-info-foo -------------------------------------------------------------------------------- /testdata/e2e/examples/timeout/README.md: -------------------------------------------------------------------------------- 1 | # Test: `timeout` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 1 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `script` | 0 | 0 | *No description* | 20 | 21 | --- 22 | 23 | -------------------------------------------------------------------------------- /testdata/e2e/examples/timeout/chainsaw-test.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: timeout 6 | spec: 7 | steps: 8 | - try: 9 | - script: 10 | content: sleep 5 11 | timeout: 3s 12 | check: 13 | ($error != null): true 14 | -------------------------------------------------------------------------------- /testdata/e2e/examples/update-crd/README.md: -------------------------------------------------------------------------------- 1 | # Test: `update-crd` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 6 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | | 2 | `assert` | 0 | 0 | *No description* | 21 | | 3 | `apply` | 0 | 0 | *No description* | 22 | | 4 | `update` | 0 | 0 | *No description* | 23 | | 5 | `error` | 0 | 0 | *No description* | 24 | | 6 | `assert` | 0 | 0 | *No description* | 25 | 26 | --- 27 | 28 | -------------------------------------------------------------------------------- /testdata/e2e/examples/update/README.md: -------------------------------------------------------------------------------- 1 | # Test: `update` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 4 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | | 2 | `update` | 0 | 0 | *No description* | 21 | | 3 | `assert` | 0 | 0 | *No description* | 22 | | 4 | `error` | 0 | 0 | *No description* | 23 | 24 | --- 25 | 26 | -------------------------------------------------------------------------------- /testdata/e2e/examples/values/README.md: -------------------------------------------------------------------------------- 1 | # Test: `values` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [step-1](#step-step-1) | 0 | 1 | 0 | 0 | 0 | 10 | 11 | ### Step: `step-1` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `assert` | 0 | 0 | *No description* | 20 | 21 | --- 22 | 23 | -------------------------------------------------------------------------------- /testdata/e2e/examples/values/chainsaw-test.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../../../.schemas/json/test-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Test 4 | metadata: 5 | name: values 6 | spec: 7 | steps: 8 | - try: 9 | - assert: 10 | resource: 11 | ($values.foo): bar 12 | -------------------------------------------------------------------------------- /testdata/e2e/examples/yaml-anchors/README.md: -------------------------------------------------------------------------------- 1 | # Test: `yaml-anchors` 2 | 3 | *No description* 4 | 5 | ## Steps 6 | 7 | | # | Name | Bindings | Try | Catch | Finally | Cleanup | 8 | |:-:|---|:-:|:-:|:-:|:-:|:-:| 9 | | 1 | [yaml-anchors](#step-yaml-anchors) | 0 | 2 | 0 | 0 | 0 | 10 | 11 | ### Step: `yaml-anchors` 12 | 13 | *No description* 14 | 15 | #### Try 16 | 17 | | # | Operation | Bindings | Outputs | Description | 18 | |:-:|---|:-:|:-:|---| 19 | | 1 | `apply` | 0 | 0 | *No description* | 20 | | 2 | `assert` | 0 | 0 | *No description* | 21 | 22 | --- 23 | 24 | -------------------------------------------------------------------------------- /testdata/e2e/values.yaml: -------------------------------------------------------------------------------- 1 | foo: bar -------------------------------------------------------------------------------- /testdata/kuttl/.chainsaw.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/configuration-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: Configuration 4 | metadata: 5 | creationTimestamp: null 6 | name: configuration 7 | spec: 8 | parallel: 4 9 | template: false 10 | timeouts: 11 | apply: 5m0s 12 | assert: 5m0s 13 | cleanup: 5m0s 14 | delete: 5m0s 15 | error: 5m0s 16 | exec: 5m0s 17 | -------------------------------------------------------------------------------- /testdata/kuttl/01-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestAssert 3 | timeout: 30 4 | commands: 5 | - command: echo hello 6 | collectors: 7 | - type: pod 8 | pod: nginx -------------------------------------------------------------------------------- /testdata/kuttl/01-step.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | delete: 4 | # Delete a Pod 5 | - apiVersion: v1 6 | kind: Pod 7 | name: my-pod 8 | # Delete all Pods with app=nginx 9 | - apiVersion: v1 10 | kind: Pod 11 | labels: 12 | app: nginx 13 | # Delete all Pods in the test namespace 14 | - apiVersion: v1 15 | kind: Pod 16 | commands: 17 | - script: echo "hello world" 18 | skipLogOutput: true 19 | - command: echo "hello world" 20 | skipLogOutput: true 21 | -------------------------------------------------------------------------------- /testdata/kuttl/02-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestAssert 3 | timeout: 30 4 | commands: 5 | - command: echo hello 6 | collectors: 7 | - type: command 8 | command: sleep 1 -------------------------------------------------------------------------------- /testdata/kuttl/02-step.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | delete: 4 | # Delete a Pod 5 | - apiVersion: v1 6 | kind: Pod 7 | name: my-pod 8 | # Delete all Pods with app=nginx 9 | - apiVersion: v1 10 | kind: Pod 11 | labels: 12 | app: nginx 13 | # Delete all Pods in the test namespace 14 | - apiVersion: v1 15 | kind: Pod 16 | commands: 17 | - script: echo "hello world" 18 | skipLogOutput: true 19 | - command: echo "hello world" 20 | skipLogOutput: true 21 | -------------------------------------------------------------------------------- /testdata/kuttl/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: quick-start 5 | data: 6 | foo: bar 7 | -------------------------------------------------------------------------------- /testdata/kuttl/invalid-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestSuite 3 | data: 4 | foo: bar 5 | -------------------------------------------------------------------------------- /testdata/kuttl/kuttl-test.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestSuite 3 | parallel: 4 4 | timeout: 300 5 | startControlPlane: true -------------------------------------------------------------------------------- /testdata/kuttl/multiple-config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestSuite 3 | parallel: 4 4 | timeout: 300 5 | startControlPlane: true 6 | --- 7 | apiVersion: kuttl.dev/v1beta1 8 | kind: TestSuite 9 | parallel: 4 10 | timeout: 300 11 | startControlPlane: true 12 | -------------------------------------------------------------------------------- /testdata/report/JUNIT-TEST.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /testdata/report/XML.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /testdata/resource/empty.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/testdata/resource/empty.yaml -------------------------------------------------------------------------------- /testdata/resource/folder-invalid/invalid.yaml: -------------------------------------------------------------------------------- 1 | this: is 2 | a: invalid 3 | -------------------------------------------------------------------------------- /testdata/resource/folder-valid/valid.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Pod 4 | metadata: 5 | name: test-pod 6 | --- 7 | apiVersion: v1 8 | kind: Service 9 | metadata: 10 | name: test-service 11 | -------------------------------------------------------------------------------- /testdata/resource/invalid.yaml: -------------------------------------------------------------------------------- 1 | this: is 2 | a: invalid 3 | -------------------------------------------------------------------------------- /testdata/resource/list.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: List 3 | items: 4 | - apiVersion: v1 5 | kind: ConfigMap 6 | metadata: 7 | name: cm-1 8 | namespace: default 9 | data: 10 | key: 'yes' 11 | - apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: cm-2 15 | namespace: default 16 | data: 17 | key: 'no' 18 | -------------------------------------------------------------------------------- /testdata/resource/valid.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Pod 4 | metadata: 5 | name: test-pod 6 | --- 7 | apiVersion: v1 8 | kind: Service 9 | metadata: 10 | name: test-service 11 | -------------------------------------------------------------------------------- /testdata/runner/processors/cron-job.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1beta1 2 | kind: CronJob 3 | metadata: 4 | name: hello 5 | namespace: default 6 | spec: 7 | schedule: "*/1 * * * *" 8 | jobTemplate: 9 | spec: 10 | template: 11 | spec: 12 | containers: 13 | - name: hello 14 | image: busybox 15 | args: ['/bin/sh', '-c', 'date; echo Hello from the Chainsaw'] 16 | restartPolicy: OnFailure -------------------------------------------------------------------------------- /testdata/runner/processors/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: chainsaw 5 | spec: 6 | replicas: 1 7 | template: 8 | metadata: 9 | labels: 10 | editor: vscode 11 | spec: 12 | containers: 13 | - name: nginx 14 | image: nginx:1.7.9 -------------------------------------------------------------------------------- /testdata/runner/processors/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: myapp 5 | labels: 6 | name: myapp 7 | spec: 8 | containers: 9 | - name: myapp 10 | image: myapp:latest 11 | resources: 12 | limits: 13 | memory: "128Mi" 14 | cpu: "500m" 15 | -------------------------------------------------------------------------------- /testdata/step-template/bad-step.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../.schemas/json/steptemplate-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: StepTemplate 4 | metadata: 5 | name: quick-start 6 | spec: 7 | try: 8 | - foo: bar -------------------------------------------------------------------------------- /testdata/step-template/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: default 5 | data: 6 | foo: bar -------------------------------------------------------------------------------- /testdata/step-template/custom.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../.schemas/json/steptemplate-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: StepTemplate 4 | metadata: 5 | name: quick-start 6 | spec: 7 | try: 8 | # first operation: create the config map 9 | - apply: 10 | # file is relative to the test folder 11 | file: configmap.yaml 12 | # second operation: verify the config map exists and contains the expected data 13 | - assert: 14 | # file is relative to the test folder 15 | file: configmap.yaml 16 | -------------------------------------------------------------------------------- /testdata/step-template/empty.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/testdata/step-template/empty.yaml -------------------------------------------------------------------------------- /testdata/step-template/no-spec.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../.schemas/json/steptemplate-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: StepTemplate 4 | metadata: 5 | name: quick-start 6 | -------------------------------------------------------------------------------- /testdata/step-template/no-try.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=../../.schemas/json/steptemplate-chainsaw-v1alpha1.json 2 | apiVersion: chainsaw.kyverno.io/v1alpha1 3 | kind: StepTemplate 4 | metadata: 5 | name: quick-start 6 | spec: {} -------------------------------------------------------------------------------- /testdata/test/bad-step.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Test 3 | metadata: 4 | name: test-1 5 | spec: 6 | steps: 7 | - foo: bar -------------------------------------------------------------------------------- /testdata/test/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: default 5 | data: 6 | foo: bar -------------------------------------------------------------------------------- /testdata/test/empty.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/testdata/test/empty.yaml -------------------------------------------------------------------------------- /testdata/test/multiple.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Test 3 | metadata: 4 | name: test-1 5 | spec: 6 | steps: [] 7 | --- 8 | apiVersion: chainsaw.kyverno.io/v1alpha1 9 | kind: Test 10 | metadata: 11 | name: test-2 12 | spec: 13 | steps: [] 14 | -------------------------------------------------------------------------------- /testdata/test/no-spec.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Test 3 | metadata: 4 | name: test-1 5 | -------------------------------------------------------------------------------- /testdata/test/no-steps.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Test 3 | metadata: 4 | name: test-1 5 | spec: {} -------------------------------------------------------------------------------- /testdata/test/ok.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Test 3 | metadata: 4 | name: test-1 5 | spec: 6 | steps: 7 | - try: 8 | - apply: 9 | file: foo.yaml 10 | catch: 11 | - podLogs: 12 | namespace: foo 13 | name: bar 14 | - events: 15 | namespace: foo 16 | name: bar 17 | - command: 18 | entrypoint: time 19 | - script: 20 | content: echo "hello" 21 | - try: 22 | - assert: 23 | file: bar.yaml 24 | finally: 25 | - podLogs: 26 | namespace: foo 27 | name: bar 28 | - events: 29 | namespace: foo 30 | name: bar 31 | - command: 32 | entrypoint: time 33 | - script: 34 | content: echo "hello" 35 | -------------------------------------------------------------------------------- /testdata/test/raw-resource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: chainsaw.kyverno.io/v1alpha1 2 | kind: Test 3 | metadata: 4 | name: test-1 5 | spec: 6 | steps: 7 | - try: 8 | - apply: 9 | resource: 10 | apiVersion: v1 11 | kind: ConfigMap 12 | metadata: 13 | name: chainsaw-quick-start 14 | data: 15 | foo: bar 16 | - try: 17 | - create: 18 | resource: 19 | apiVersion: v1 20 | kind: ConfigMap 21 | metadata: 22 | name: chainsaw-quick-start 23 | data: 24 | foo: bar 25 | -------------------------------------------------------------------------------- /testdata/validation/example-file.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: nginx 5 | labels: 6 | name: nginx 7 | spec: 8 | containers: 9 | - name: nginx 10 | image: nginx 11 | resources: 12 | limits: 13 | memory: "128Mi" 14 | cpu: "500m" 15 | -------------------------------------------------------------------------------- /testdata/values/empty.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/testdata/values/empty.yaml -------------------------------------------------------------------------------- /testdata/values/invalid.yaml: -------------------------------------------------------------------------------- 1 | this, or that -------------------------------------------------------------------------------- /testdata/values/values-1.yaml: -------------------------------------------------------------------------------- 1 | foo: 2 | bar: baz 3 | test: 42 -------------------------------------------------------------------------------- /testdata/values/values-2.yaml: -------------------------------------------------------------------------------- 1 | foo: 2 | bar: baz 3 | test: ~ -------------------------------------------------------------------------------- /website/docs/configuration/options/label-selectors.md: -------------------------------------------------------------------------------- 1 | # Label selectors 2 | 3 | Chainsaw can filter the tests to run using [label selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors). 4 | 5 | ## Configuration 6 | 7 | ### With file 8 | 9 | !!! note 10 | Label selectors can't be configured with a configuration file. 11 | 12 | ### With flags 13 | 14 | ```bash 15 | chainsaw test --selector foo=bar 16 | ``` 17 | -------------------------------------------------------------------------------- /website/docs/configuration/options/no-cluster.md: -------------------------------------------------------------------------------- 1 | # No cluster options 2 | 3 | Chainsaw can be run without any connection to a Kubernetes cluster. 4 | 5 | In this case, Chainsaw will not try to create an ephemeral namespace and all operations requiring a Kubernetes cluster will fail. 6 | 7 | ## Configuration 8 | 9 | ### With file 10 | 11 | !!! note 12 | No cluster options can't be configured with a configuration file. 13 | 14 | ### With flags 15 | 16 | ```bash 17 | chainsaw test --no-cluster 18 | ``` 19 | -------------------------------------------------------------------------------- /website/docs/configuration/options/pause.md: -------------------------------------------------------------------------------- 1 | # Pause options 2 | 3 | Chainsaw can be configured to pause and wait for user input when a failure happens. 4 | This is useful when Chainsaw is run locally to allow debugging and troubleshooting failures. 5 | 6 | ## Configuration 7 | 8 | ### With file 9 | 10 | !!! note 11 | Pause options can't be configured with a configuration file. 12 | 13 | ### With flags 14 | 15 | ```bash 16 | chainsaw test --pause-on-failure 17 | ``` 18 | -------------------------------------------------------------------------------- /website/docs/configuration/options/values.md: -------------------------------------------------------------------------------- 1 | # External values 2 | 3 | Chainsaw can pass arbitrary values when running tests using the `--values` flag. 4 | Values will be available to tests under the `$values` binding. 5 | 6 | ## Configuration 7 | 8 | ### With file 9 | 10 | !!! note 11 | Values can't be configured with a configuration file. 12 | 13 | ### With flags 14 | 15 | ```bash 16 | chainsaw test --values ./values.yaml 17 | ``` 18 | -------------------------------------------------------------------------------- /website/docs/examples/concurrency.md: -------------------------------------------------------------------------------- 1 | # Concurrency control 2 | 3 | By default, Chainsaw will run tests in parallel. 4 | 5 | The number of concurrent tests can be configured globally using a [configuration file](http://127.0.0.1:8000/chainsaw/configuration/options/execution/) or with the `--parallel` flag. 6 | 7 | Alternatively, the concurrent nature of a test can specified at the test level: 8 | 9 | ```yaml 10 | apiVersion: chainsaw.kyverno.io/v1alpha1 11 | kind: Test 12 | metadata: 13 | name: example 14 | spec: 15 | # concurrency can be specified per test (`true` or `false`) 16 | # default value is `true` 17 | concurrent: false 18 | # ... 19 | ``` 20 | 21 | All non-concurrent tests are executed first, followed by the concurrent tests running in parallel. 22 | -------------------------------------------------------------------------------- /website/docs/examples/events.md: -------------------------------------------------------------------------------- 1 | # Work with events 2 | 3 | Kubernetes events are regular Kubernetes objects and can be asserted on just like any other object: 4 | 5 | ```yaml 6 | apiVersion: chainsaw.kyverno.io/v1alpha1 7 | kind: Test 8 | metadata: 9 | name: example 10 | spec: 11 | steps: 12 | - try: 13 | - assert: 14 | resource: 15 | apiVersion: v1 16 | kind: Event 17 | reason: Started 18 | source: 19 | component: kubelet 20 | involvedObject: 21 | apiVersion: v1 22 | kind: Pod 23 | name: my-pod 24 | ``` 25 | -------------------------------------------------------------------------------- /website/docs/examples/index.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | !!! info 4 | Select an item in the navigation menu to browse a specific page. 5 | -------------------------------------------------------------------------------- /website/docs/examples/label-selectors.md: -------------------------------------------------------------------------------- 1 | # Work with label selectors 2 | 3 | Chainsaw can filter the tests to run using [label selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors). 4 | 5 | You can pass label selectors using the `--selector` flag when invoking the `chainsaw test` command. 6 | 7 | Given the test below: 8 | 9 | ```yaml 10 | apiVersion: chainsaw.kyverno.io/v1alpha1 11 | kind: Test 12 | metadata: 13 | name: basic 14 | labels: 15 | foo: bar 16 | spec: 17 | # ... 18 | ``` 19 | 20 | Invoking Chainsaw with the command below will take the test above into account: 21 | 22 | ```bash 23 | chainsaw test --selector foo=bar 24 | ``` 25 | -------------------------------------------------------------------------------- /website/docs/guides/lint.md: -------------------------------------------------------------------------------- 1 | # Lint tests 2 | 3 | ## Overview 4 | 5 | Chainsaw comes with a `lint` command to detect ill-formated tests. 6 | 7 | !!! tip "Reference documentation" 8 | 9 | You can view the full command documentation [here](../reference/commands/chainsaw_lint.md). 10 | 11 | ## Usage 12 | 13 | To build the docs of a test, Chainsaw provides the `chainsaw lint test -f path/to/chainsaw-test.yaml` command. 14 | 15 | ```bash 16 | chainsaw lint test -f - < error 23 | ``` 24 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/lookup.md: -------------------------------------------------------------------------------- 1 | # lookup 2 | 3 | ## Signature 4 | 5 | `lookup(object|array, string|number)` 6 | 7 | ## Description 8 | 9 | Returns the value corresponding to the given key/index in the given object/array. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/lower.md: -------------------------------------------------------------------------------- 1 | # lower 2 | 3 | ## Signature 4 | 5 | `lower(string)` 6 | 7 | ## Description 8 | 9 | Returns the given string with all Unicode letters mapped to their lower case. 10 | 11 | ## Examples 12 | 13 | ``` 14 | lower('FOOBAR') == 'foobar' 15 | ``` 16 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/map.md: -------------------------------------------------------------------------------- 1 | # map 2 | 3 | ## Signature 4 | 5 | `map(expref, array)` 6 | 7 | ## Description 8 | 9 | Transforms elements in a given array and returns the result. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/max.md: -------------------------------------------------------------------------------- 1 | # max 2 | 3 | ## Signature 4 | 5 | `max(array[number]|array[string])` 6 | 7 | ## Description 8 | 9 | Returns the highest found element in the provided array argument. An empty array will produce a return value of null. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/max_by.md: -------------------------------------------------------------------------------- 1 | # max_by 2 | 3 | ## Signature 4 | 5 | `max_by(array, expref)` 6 | 7 | ## Description 8 | 9 | Returns the highest found element using a custom expression to compute the associated value for each element in the input array. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/merge.md: -------------------------------------------------------------------------------- 1 | # merge 2 | 3 | ## Signature 4 | 5 | `merge(object)` 6 | 7 | ## Description 8 | 9 | Meges a list of objects together and returns the result. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/min.md: -------------------------------------------------------------------------------- 1 | # min 2 | 3 | ## Signature 4 | 5 | `min(array[number]|array[string])` 6 | 7 | ## Description 8 | 9 | Returns the lowest found element in the provided array argument. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/min_by.md: -------------------------------------------------------------------------------- 1 | # min_by 2 | 3 | ## Signature 4 | 5 | `min_by(array, expref)` 6 | 7 | ## Description 8 | 9 | Returns the lowest found element using a custom expression to compute the associated value for each element in the input array. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/modulo.md: -------------------------------------------------------------------------------- 1 | # modulo 2 | 3 | ## Signature 4 | 5 | `modulo(any, any)` 6 | 7 | ## Description 8 | 9 | Divisor must be non-zero, arguments must be integers. 10 | 11 | ## Examples 12 | 13 | ``` 14 | modulo(`10`, `3`) == `1` 15 | ``` 16 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/multiply.md: -------------------------------------------------------------------------------- 1 | # multiply 2 | 3 | ## Signature 4 | 5 | `multiply(any, any)` 6 | 7 | ## Description 8 | 9 | Does arithmetic multiplication of two specified values of numbers, quantities, and durations. 10 | 11 | ## Examples 12 | 13 | ### With numbers 14 | 15 | ``` 16 | multiply(`1`, `2`) == `2` 17 | ``` 18 | 19 | ### With durations 20 | 21 | ``` 22 | multiply('1h', `2`) == '2h' 23 | ``` 24 | 25 | ### With quantities 26 | 27 | ``` 28 | multiply('1Mi', `2`) == '2Mi' 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/not_null.md: -------------------------------------------------------------------------------- 1 | # not_null 2 | 3 | ## Signature 4 | 5 | `not_null(any)` 6 | 7 | ## Description 8 | 9 | Returns the first non null element in the input array. 10 | 11 | ## Examples 12 | 13 | ``` 14 | not_null(null, null, 'foo') == 'foo' 15 | ``` 16 | 17 | ``` 18 | not_null(null, null) == null 19 | ``` 20 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/object_from_lists.md: -------------------------------------------------------------------------------- 1 | # object_from_lists 2 | 3 | ## Signature 4 | 5 | `object_from_lists(array, array)` 6 | 7 | ## Description 8 | 9 | Converts a pair of lists containing keys and values to an object. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/pad_left.md: -------------------------------------------------------------------------------- 1 | # pad_left 2 | 3 | ## Signature 4 | 5 | `pad_left(string, number, string)` 6 | 7 | ## Description 8 | 9 | Adds characters to the beginning of a string. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/pad_right.md: -------------------------------------------------------------------------------- 1 | # pad_right 2 | 3 | ## Signature 4 | 5 | `pad_right(string, number, string)` 6 | 7 | ## Description 8 | 9 | Adds characters to the end of a string. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/parse_json.md: -------------------------------------------------------------------------------- 1 | # parse_json 2 | 3 | ## Signature 4 | 5 | `parse_json(string)` 6 | 7 | ## Description 8 | 9 | Decodes a valid JSON encoded string to the appropriate type. Opposite of `to_string` function. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/parse_yaml.md: -------------------------------------------------------------------------------- 1 | # parse_yaml 2 | 3 | ## Signature 4 | 5 | `parse_yaml(string)` 6 | 7 | ## Description 8 | 9 | Decodes a valid YAML encoded string to the appropriate type provided it can be represented as JSON. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/path_canonicalize.md: -------------------------------------------------------------------------------- 1 | # path_canonicalize 2 | 3 | ## Signature 4 | 5 | `path_canonicalize(string)` 6 | 7 | ## Description 8 | 9 | Normalizes or canonicalizes a given path by removing excess slashes. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/pattern_match.md: -------------------------------------------------------------------------------- 1 | # pattern_match 2 | 3 | ## Signature 4 | 5 | `pattern_match(string, string|number)` 6 | 7 | ## Description 8 | 9 | '*' matches zero or more alphanumeric characters, '?' matches a single alphanumeric character. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/random.md: -------------------------------------------------------------------------------- 1 | # random 2 | 3 | ## Signature 4 | 5 | `random(string)` 6 | 7 | ## Description 8 | 9 | Generates a random sequence of characters. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/regex_match.md: -------------------------------------------------------------------------------- 1 | # regex_match 2 | 3 | ## Signature 4 | 5 | `regex_match(string, string|number)` 6 | 7 | ## Description 8 | 9 | First string is the regular exression which is compared with second input which can be a number or string. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/regex_replace_all.md: -------------------------------------------------------------------------------- 1 | # regex_replace_all 2 | 3 | ## Signature 4 | 5 | `regex_replace_all(string, string|number, string|number)` 6 | 7 | ## Description 8 | 9 | Converts all parameters to string. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/regex_replace_all_literal.md: -------------------------------------------------------------------------------- 1 | # regex_replace_all_literal 2 | 3 | ## Signature 4 | 5 | `regex_replace_all_literal(string, string|number, string|number)` 6 | 7 | ## Description 8 | 9 | Converts all parameters to string. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/replace.md: -------------------------------------------------------------------------------- 1 | # replace 2 | 3 | ## Signature 4 | 5 | `replace(string, string, string, number)` 6 | 7 | ## Description 8 | 9 | Replaces a specified number of instances of the source string with the replacement string in a parent. 10 | 11 | ## Examples 12 | 13 | ``` 14 | replace('foobar', 'oo', 'ii') == 'fiibar' 15 | ``` 16 | 17 | ``` 18 | replace('foobar', 'o', 'i', `1`) == 'fiobar' 19 | ``` 20 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/replace_all.md: -------------------------------------------------------------------------------- 1 | # replace_all 2 | 3 | ## Signature 4 | 5 | `replace_all(string, string, string)` 6 | 7 | ## Description 8 | 9 | Replace all instances of one string with another in an overall parent string. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/reverse.md: -------------------------------------------------------------------------------- 1 | # reverse 2 | 3 | ## Signature 4 | 5 | `reverse(array|string)` 6 | 7 | ## Description 8 | 9 | Reverses the input string or array and returns the result. 10 | 11 | ## Examples 12 | 13 | ``` 14 | reverse('abcd') == 'dcba' 15 | ``` 16 | 17 | ``` 18 | reverse([`1`, `2`, `3`, `4`]) == [`4`, `3`, `2`, `1`] 19 | ``` 20 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/round.md: -------------------------------------------------------------------------------- 1 | # round 2 | 3 | ## Signature 4 | 5 | `round(number, number)` 6 | 7 | ## Description 8 | 9 | Does roundoff to upto the given decimal places. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/semver_compare.md: -------------------------------------------------------------------------------- 1 | # semver_compare 2 | 3 | ## Signature 4 | 5 | `semver_compare(string, string)` 6 | 7 | ## Description 8 | 9 | Compares two strings which comply with the semantic versioning schema and outputs a boolean response as to the position of the second relative to the first. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/sort.md: -------------------------------------------------------------------------------- 1 | # sort 2 | 3 | ## Signature 4 | 5 | `sort(array[string]|array[number])` 6 | 7 | ## Description 8 | 9 | This function accepts an array argument and returns the sorted elements as an array. 10 | 11 | ## Examples 12 | 13 | ``` 14 | sort(['b', 'a', 'c']) == ['a', 'b', 'c'] 15 | ``` 16 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/sort_by.md: -------------------------------------------------------------------------------- 1 | # sort_by 2 | 3 | ## Signature 4 | 5 | `sort_by(array, expref)` 6 | 7 | ## Description 8 | 9 | This function accepts an array argument and returns the sorted elements as an array using a custom expression to compute the associated value for each element. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/split.md: -------------------------------------------------------------------------------- 1 | # split 2 | 3 | ## Signature 4 | 5 | `split(string, string)` 6 | 7 | ## Description 8 | 9 | Splits the first string when the second string is found and converts it into an array. 10 | 11 | ## Examples 12 | 13 | ``` 14 | split('average|-|min|-|max|-|mean|-|median', '|-|', `3`) == ['average', 'min', 'max', 'mean|-|median'] 15 | ``` 16 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/starts_with.md: -------------------------------------------------------------------------------- 1 | # starts_with 2 | 3 | ## Signature 4 | 5 | `starts_with(string, string)` 6 | 7 | ## Description 8 | 9 | Reports whether the input string begins with the provided string prefix argument. 10 | 11 | ## Examples 12 | 13 | ``` 14 | starts_with('foobar', 'foo') == `true` 15 | ``` 16 | 17 | ``` 18 | starts_with('foobar', 'bar') == `false` 19 | ``` 20 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/subtract.md: -------------------------------------------------------------------------------- 1 | # subtract 2 | 3 | ## Signature 4 | 5 | `subtract(any, any)` 6 | 7 | ## Description 8 | 9 | Does arithmetic subtraction of two specified values of numbers, quantities, and durations. 10 | 11 | ## Examples 12 | 13 | ### With numbers 14 | 15 | ``` 16 | subtract(`2`, `1`) == `1` 17 | ``` 18 | 19 | ### With durations 20 | 21 | ``` 22 | subtract('2h', '1h') == '1h' 23 | ``` 24 | 25 | ### With quantities 26 | 27 | ``` 28 | subtract('2Mi', '1Mi') == '1Mi' 29 | ``` 30 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/sum.md: -------------------------------------------------------------------------------- 1 | # sum 2 | 3 | ## Signature 4 | 5 | `sum(array)` 6 | 7 | ## Description 8 | 9 | Does arithmetic addition of specified array of values of numbers, quantities, and durations. 10 | 11 | ## Examples 12 | 13 | ``` 14 | sum(`[]`) == `0` 15 | ``` 16 | 17 | ``` 18 | sum([`10`, `15`]) == `25` 19 | ``` 20 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/time_add.md: -------------------------------------------------------------------------------- 1 | # time_add 2 | 3 | ## Signature 4 | 5 | `time_add(string, string)` 6 | 7 | ## Description 8 | 9 | Adds duration (second string) to a time value (first string). 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/time_after.md: -------------------------------------------------------------------------------- 1 | # time_after 2 | 3 | ## Signature 4 | 5 | `time_after(string, string)` 6 | 7 | ## Description 8 | 9 | Checks if a time is after another time, both in RFC3339 format. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/time_before.md: -------------------------------------------------------------------------------- 1 | # time_before 2 | 3 | ## Signature 4 | 5 | `time_before(string, string)` 6 | 7 | ## Description 8 | 9 | Checks if a time is before another time, both in RFC3339 format. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/time_between.md: -------------------------------------------------------------------------------- 1 | # time_between 2 | 3 | ## Signature 4 | 5 | `time_between(string, string, string)` 6 | 7 | ## Description 8 | 9 | Checks if a time is between a start and end time, all in RFC3339 format. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/time_diff.md: -------------------------------------------------------------------------------- 1 | # time_diff 2 | 3 | ## Signature 4 | 5 | `time_diff(string, string)` 6 | 7 | ## Description 8 | 9 | Calculate the difference between a start and end date in RFC3339 format. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/time_now.md: -------------------------------------------------------------------------------- 1 | # time_now 2 | 3 | ## Signature 4 | 5 | `time_now()` 6 | 7 | ## Description 8 | 9 | Returns current time in RFC 3339 format. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/time_now_utc.md: -------------------------------------------------------------------------------- 1 | # time_now_utc 2 | 3 | ## Signature 4 | 5 | `time_now_utc()` 6 | 7 | ## Description 8 | 9 | Returns current UTC time in RFC 3339 format. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/time_parse.md: -------------------------------------------------------------------------------- 1 | # time_parse 2 | 3 | ## Signature 4 | 5 | `time_parse(string, string)` 6 | 7 | ## Description 8 | 9 | Changes a time value of a given layout to RFC 3339. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/time_since.md: -------------------------------------------------------------------------------- 1 | # time_since 2 | 3 | ## Signature 4 | 5 | `time_since(string, string, string)` 6 | 7 | ## Description 8 | 9 | Calculate the difference between a start and end period of time where the end may either be a static definition or the then-current time. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/time_to_cron.md: -------------------------------------------------------------------------------- 1 | # time_to_cron 2 | 3 | ## Signature 4 | 5 | `time_to_cron(string)` 6 | 7 | ## Description 8 | 9 | Converts a time (RFC 3339) to a cron expression (string). 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/time_truncate.md: -------------------------------------------------------------------------------- 1 | # time_truncate 2 | 3 | ## Signature 4 | 5 | `time_truncate(string, string)` 6 | 7 | ## Description 8 | 9 | Returns the result of rounding time down to a multiple of duration. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/time_utc.md: -------------------------------------------------------------------------------- 1 | # time_utc 2 | 3 | ## Signature 4 | 5 | `time_utc(string)` 6 | 7 | ## Description 8 | 9 | Calcutes time in UTC from a given time in RFC 3339 format. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/to_array.md: -------------------------------------------------------------------------------- 1 | # to_array 2 | 3 | ## Signature 4 | 5 | `to_array(any)` 6 | 7 | ## Description 8 | 9 | Returns a one element array containing the passed in argument, or the passed in value if it's an array. 10 | 11 | ## Examples 12 | 13 | ``` 14 | to_array(`true`) == [`true`] 15 | ``` 16 | 17 | ``` 18 | to_array([`10`, `15`, `20`]) == [`10`, `15`, `20`] 19 | ``` 20 | 21 | ``` 22 | to_array(`[]`) == [] 23 | ``` 24 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/to_boolean.md: -------------------------------------------------------------------------------- 1 | # to_boolean 2 | 3 | ## Signature 4 | 5 | `to_boolean(string)` 6 | 7 | ## Description 8 | 9 | It returns true or false for any string, such as 'True', 'TruE', 'False', 'FAlse', 'faLSE', etc. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/to_lower.md: -------------------------------------------------------------------------------- 1 | # to_lower 2 | 3 | ## Signature 4 | 5 | `to_lower(string)` 6 | 7 | ## Description 8 | 9 | Takes in a string and outputs the same string with all lower-case letters. 10 | 11 | ## Examples 12 | 13 | ``` 14 | lower('FOOBAR') == 'foobar' 15 | ``` 16 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/to_number.md: -------------------------------------------------------------------------------- 1 | # to_number 2 | 3 | ## Signature 4 | 5 | `to_number(any)` 6 | 7 | ## Description 8 | 9 | Returns the parsed number. 10 | 11 | ## Examples 12 | 13 | ``` 14 | to_number('1.0') == `1` 15 | ``` 16 | 17 | ``` 18 | to_number(`1.0`) == `1` 19 | ``` 20 | 21 | ``` 22 | to_number(`false`) == null 23 | ``` 24 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/to_string.md: -------------------------------------------------------------------------------- 1 | # to_string 2 | 3 | ## Signature 4 | 5 | `to_string(any)` 6 | 7 | ## Description 8 | 9 | The JSON encoded value of the given argument. 10 | 11 | ## Examples 12 | 13 | ``` 14 | to_string(`2`) == '2' 15 | ``` 16 | 17 | ``` 18 | to_string('foobar') == 'foobar' 19 | ``` 20 | 21 | ``` 22 | to_string(null) == 'null' 23 | ``` 24 | 25 | ``` 26 | to_string({bar:'bam',foo:'baz'}) == '{"bar":"bam","foo":"baz"}' 27 | ``` 28 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/to_upper.md: -------------------------------------------------------------------------------- 1 | # to_upper 2 | 3 | ## Signature 4 | 5 | `to_upper(string)` 6 | 7 | ## Description 8 | 9 | Takes in a string and outputs the same string with all upper-case letters. 10 | 11 | ## Examples 12 | 13 | ``` 14 | upper('foobar') == 'FOOBAR' 15 | ``` 16 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/trim.md: -------------------------------------------------------------------------------- 1 | # trim 2 | 3 | ## Signature 4 | 5 | `trim(string, string)` 6 | 7 | ## Description 8 | 9 | Trims both ends of the source string by characters appearing in the second string. 10 | 11 | ## Examples 12 | 13 | ``` 14 | trim(' foobar ', 'fbr ') == 'ooba' 15 | ``` 16 | 17 | ``` 18 | trim(' foobar ', 'fbr') == ' foobar ' 19 | ``` 20 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/trim_left.md: -------------------------------------------------------------------------------- 1 | # trim_left 2 | 3 | ## Signature 4 | 5 | `trim_left(string, string)` 6 | 7 | ## Description 8 | 9 | Removes the leading characters found in the passed in string argument. 10 | 11 | ## Examples 12 | 13 | ``` 14 | trim_left(' foobar ', 'fbr ') == 'oobar ' 15 | ``` 16 | 17 | ``` 18 | trim_left(' foobar ', 'fbr') == ' foobar ' 19 | ``` 20 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/trim_prefix.md: -------------------------------------------------------------------------------- 1 | # trim_prefix 2 | 3 | ## Signature 4 | 5 | `trim_prefix(string, string)` 6 | 7 | ## Description 8 | 9 | Trims the second string prefix from the first string if the first string starts with the prefix. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/trim_right.md: -------------------------------------------------------------------------------- 1 | # trim_right 2 | 3 | ## Signature 4 | 5 | `trim_right(string, string)` 6 | 7 | ## Description 8 | 9 | Removes the trailing characters found in the passed in string argument. 10 | 11 | ## Examples 12 | 13 | ``` 14 | trim_right(' foobar ', 'fbr ') == ' fooba' 15 | ``` 16 | 17 | ``` 18 | trim_right(' foobar ', 'fbr') == ' foobar ' 19 | ``` 20 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/trim_space.md: -------------------------------------------------------------------------------- 1 | # trim_space 2 | 3 | ## Signature 4 | 5 | `trim_space(string)` 6 | 7 | ## Description 8 | 9 | Trims leading and trailing spaces from the string passed in argument. 10 | 11 | ## Examples 12 | 13 | ``` 14 | trim_space(' foobar ') == 'foobar' 15 | ``` 16 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/truncate.md: -------------------------------------------------------------------------------- 1 | # truncate 2 | 3 | ## Signature 4 | 5 | `truncate(string, number)` 6 | 7 | ## Description 8 | 9 | Length argument must be enclosed in backticks; ex. "{{request.object.metadata.name | truncate(@, `9`)}}". 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/type.md: -------------------------------------------------------------------------------- 1 | # type 2 | 3 | ## Signature 4 | 5 | `type(any)` 6 | 7 | ## Description 8 | 9 | Returns the JavaScript type of the given argument as a string value. 10 | 11 | ## Examples 12 | 13 | ``` 14 | type(`false`) == 'boolean' 15 | ``` 16 | 17 | ``` 18 | type(null) == 'null' 19 | ``` 20 | 21 | ``` 22 | type('foobar') == 'string' 23 | ``` 24 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/upper.md: -------------------------------------------------------------------------------- 1 | # upper 2 | 3 | ## Signature 4 | 5 | `upper(string)` 6 | 7 | ## Description 8 | 9 | Returns the given string with all Unicode letters mapped to their upper case. 10 | 11 | ## Examples 12 | 13 | ``` 14 | upper('foobar') == 'FOOBAR' 15 | ``` 16 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/values.md: -------------------------------------------------------------------------------- 1 | # values 2 | 3 | ## Signature 4 | 5 | `values(object)` 6 | 7 | ## Description 8 | 9 | Returns the values of the provided object. 10 | 11 | ## Examples 12 | 13 | ``` 14 | values({bar:'bam',foo:'baz'}) == ['bam','baz'] 15 | ``` 16 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/wildcard.md: -------------------------------------------------------------------------------- 1 | # wildcard 2 | 3 | ## Signature 4 | 5 | `wildcard(string, string)` 6 | 7 | ## Description 8 | 9 | Compares a wildcard pattern with a given string and returns if they match or not. 10 | 11 | ## Examples 12 | 13 | ``` 14 | wildcard('foo*', 'foobar') == `true` 15 | ``` 16 | 17 | ``` 18 | wildcard('fooba?', 'foobar') == `true` 19 | ``` 20 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/x509_decode.md: -------------------------------------------------------------------------------- 1 | # x509_decode 2 | 3 | ## Signature 4 | 5 | `x509_decode(string)` 6 | 7 | ## Description 8 | 9 | Decodes an x.509 certificate to an object. you may also use this in conjunction with `base64_decode` jmespath function to decode a base64-encoded certificate. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/x_k8s_exists.md: -------------------------------------------------------------------------------- 1 | # x_k8s_exists 2 | 3 | ## Signature 4 | 5 | `x_k8s_exists(any, string, string, string, string)` 6 | 7 | ## Description 8 | 9 | Checks if a given resource exists in a Kubernetes cluster. 10 | 11 | ## Examples 12 | 13 | !!! info "Clustered resources" 14 | 15 | For clustered resources, you can leave the namespace empty `''`. 16 | 17 | ``` 18 | # `$client` is a binding pointing to a Kubernetes client 19 | 20 | x_k8s_exists($client, 'apps/v1', 'Deployment', 'crossplane-system', 'crossplane') 21 | ``` 22 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/x_k8s_get.md: -------------------------------------------------------------------------------- 1 | # x_k8s_get 2 | 3 | ## Signature 4 | 5 | `x_k8s_get(any, string, string, string, string)` 6 | 7 | ## Description 8 | 9 | Gets a resource from a Kubernetes cluster. 10 | 11 | ## Examples 12 | 13 | !!! info "Clustered resources" 14 | 15 | For clustered resources, you can leave the namespace empty `''`. 16 | 17 | ``` 18 | # `$client` is a binding pointing to a Kubernetes client 19 | 20 | x_k8s_get($client, 'apps/v1', 'Deployment', 'crossplane-system', 'crossplane') 21 | ``` 22 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/x_k8s_list.md: -------------------------------------------------------------------------------- 1 | # x_k8s_list 2 | 3 | ## Signature 4 | 5 | `x_k8s_list(any, string, string, string)` 6 | 7 | ## Description 8 | 9 | Lists resources from a Kubernetes cluster. 10 | 11 | ## Examples 12 | 13 | !!! info "Clustered resources" 14 | 15 | For clustered resources, you can leave the namespace empty `''`. 16 | 17 | ``` 18 | # `$client` is a binding pointing to a Kubernetes client 19 | 20 | x_k8s_list($client, 'apps/v1', 'Deployment', 'crossplane-system') 21 | ``` 22 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/x_k8s_resource_exists.md: -------------------------------------------------------------------------------- 1 | # x_k8s_resource_exists 2 | 3 | ## Signature 4 | 5 | `x_k8s_resource_exists(any, string, string)` 6 | 7 | ## Description 8 | 9 | Checks if a given resource type is available in a Kubernetes cluster. 10 | 11 | ## Examples 12 | 13 | !!! info "Clustered resources" 14 | 15 | For clustered resources, you can leave the namespace empty `''`. 16 | 17 | ``` 18 | # `$client` is a binding pointing to a Kubernetes client 19 | 20 | x_k8s_resource_exists($client, 'apps/v1', 'Deployment') 21 | ``` 22 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/x_k8s_server_version.md: -------------------------------------------------------------------------------- 1 | # x_k8s_server_version 2 | 3 | ## Signature 4 | 5 | `x_k8s_server_version(any)` 6 | 7 | ## Description 8 | 9 | Returns the version of a Kubernetes cluster. 10 | 11 | ## Examples 12 | 13 | ``` 14 | # `$client` is a binding pointing to a Kubernetes client 15 | 16 | x_k8s_server_version($client) 17 | ``` 18 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/x_metrics_decode.md: -------------------------------------------------------------------------------- 1 | # x_metrics_decode 2 | 3 | ## Signature 4 | 5 | `x_metrics_decode(string)` 6 | 7 | ## Description 8 | 9 | Decodes metrics in the Prometheus text format. 10 | 11 | ## Examples 12 | 13 | TODO 14 | -------------------------------------------------------------------------------- /website/docs/reference/jp/examples/zip.md: -------------------------------------------------------------------------------- 1 | # zip 2 | 3 | ## Signature 4 | 5 | `zip(array, array)` 6 | 7 | ## Description 8 | 9 | Accepts one or more arrays as arguments and returns an array of arrays in which the i-th array contains the i-th element from each of the argument arrays. The returned array is truncated to the length of the shortest argument array. 10 | 11 | ## Examples 12 | 13 | ``` 14 | zip(['a', 'b'], [`1`, `2`]) == [['a', `1`], ['b', `2`]] 15 | ``` 16 | -------------------------------------------------------------------------------- /website/docs/static/extra.css: -------------------------------------------------------------------------------- 1 | body>header>nav>a>img { 2 | border-radius: 10%; 3 | border: 1px solid #555; 4 | } 5 | 6 | td:nth-child(1) { 7 | text-wrap: nowrap; 8 | } -------------------------------------------------------------------------------- /website/docs/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/website/docs/static/favicon.ico -------------------------------------------------------------------------------- /website/docs/static/kyverno-chainsaw-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/website/docs/static/kyverno-chainsaw-horizontal.png -------------------------------------------------------------------------------- /website/docs/static/kyverno-chainsaw-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyverno/chainsaw/bab727ee05720d9d54ea7467f3597ef30717bc86/website/docs/static/kyverno-chainsaw-logo.png -------------------------------------------------------------------------------- /website/docs/step/try.md: -------------------------------------------------------------------------------- 1 | # try 2 | 3 | A `try` statement is a sequence of [operations](../operations/index.md) executed in the same order they are declared. 4 | If an operation fails the entire step is considered failed. 5 | 6 | ## Operations 7 | 8 | A `try` statement supports all [operations](../operations/index.md): 9 | 10 | - [Apply](../operations/apply.md) 11 | - [Assert](../operations/assert.md) 12 | - [Command](../operations/command.md) 13 | - [Create](../operations/create.md) 14 | - [Delete](../operations/delete.md) 15 | - [Error](../operations/error.md) 16 | - [Patch](../operations/patch.md) 17 | - [Script](../operations/script.md) 18 | - [Sleep](../operations/sleep.md) 19 | - [Update](../operations/update.md) 20 | - [Wait](../operations/helpers/wait.md) 21 | -------------------------------------------------------------------------------- /website/jp/examples/abs.md: -------------------------------------------------------------------------------- 1 | ``` 2 | abs(`-1`) == `1` 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/add.md: -------------------------------------------------------------------------------- 1 | ### With numbers 2 | 3 | ``` 4 | add(`1`, `2`) == `3` 5 | ``` 6 | 7 | ### With durations 8 | 9 | ``` 10 | add('1h', '2h') == '3h' 11 | ``` 12 | 13 | ### With quantities 14 | 15 | ``` 16 | add('1Mi', '2Mi') == '3Mi' 17 | ``` 18 | -------------------------------------------------------------------------------- /website/jp/examples/as_string.md: -------------------------------------------------------------------------------- 1 | ``` 2 | as_string('foobar') == 'foobar' 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/at.md: -------------------------------------------------------------------------------- 1 | ``` 2 | at([`10`,`15`,`20`], `1`) == `15` 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/avg.md: -------------------------------------------------------------------------------- 1 | ``` 2 | avg([`10`,`15`,`20`]) == `15` 3 | ``` -------------------------------------------------------------------------------- /website/jp/examples/base64_decode.md: -------------------------------------------------------------------------------- 1 | ``` 2 | base64_decode('Zm9vCg==') == 'foo' 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/base64_encode.md: -------------------------------------------------------------------------------- 1 | ``` 2 | base64_encode('foo') == 'Zm9vCg==' 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/ceil.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ceil(`1.9`) == `2` 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/compare.md: -------------------------------------------------------------------------------- 1 | ``` 2 | compare('a', 'a') == `0` 3 | ``` 4 | 5 | ``` 6 | compare('a', 'b') == `-1` 7 | ``` 8 | 9 | ``` 10 | compare('b', 'a') == `1` 11 | ``` 12 | -------------------------------------------------------------------------------- /website/jp/examples/concat.md: -------------------------------------------------------------------------------- 1 | ``` 2 | concat('foo', 'bar') == 'foobar' 3 | ``` -------------------------------------------------------------------------------- /website/jp/examples/contains.md: -------------------------------------------------------------------------------- 1 | ### With strings 2 | 3 | ``` 4 | contains('foobar', 'bar') == `true` 5 | ``` 6 | 7 | ``` 8 | contains('foobar', 'not') == `false` 9 | ``` 10 | 11 | ### With arrays 12 | 13 | ``` 14 | contains(['foo', 'bar'], 'bar') == `true` 15 | ``` 16 | 17 | ``` 18 | contains(['foo', 'bar'], 'not') == `true` 19 | ``` 20 | -------------------------------------------------------------------------------- /website/jp/examples/divide.md: -------------------------------------------------------------------------------- 1 | ### With numbers 2 | 3 | ``` 4 | divide(`1`, `2`) == `0.5` 5 | ``` 6 | 7 | ### With durations 8 | 9 | ``` 10 | divide('1h', '2h') == `0.5` 11 | ``` 12 | 13 | ### With quantities 14 | 15 | ``` 16 | divide('1Mi', '2Mi') == `0.5` 17 | ``` 18 | -------------------------------------------------------------------------------- /website/jp/examples/ends_with.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ends_with('foobar', 'bar') == `true` 3 | ``` 4 | 5 | ``` 6 | ends_with('foobar', 'foo') == `false` 7 | ``` 8 | -------------------------------------------------------------------------------- /website/jp/examples/env.md: -------------------------------------------------------------------------------- 1 | ``` 2 | env('MY_ENV_VAR') == 'foo' 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/equal_fold.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/find_first.md: -------------------------------------------------------------------------------- 1 | ``` 2 | find_first('subject string', 'string', `0`) == `8` 3 | ``` 4 | 5 | ``` 6 | find_first('subject string', 'string', `8`) == `8` 7 | ``` 8 | 9 | ``` 10 | find_first('subject string', 'string', `9`) == null 11 | ``` 12 | 13 | ``` 14 | find_first('subject string', 'string', `0`, `14`) == `8` 15 | ``` 16 | 17 | ``` 18 | find_first('subject string', 'string', `0`, `13`) == null 19 | ``` 20 | -------------------------------------------------------------------------------- /website/jp/examples/find_last.md: -------------------------------------------------------------------------------- 1 | ``` 2 | find_last('subject string', 'string', `0`) == `8` 3 | ``` 4 | 5 | ``` 6 | find_last('subject string', 'string', `8`) == `8` 7 | ``` 8 | 9 | ``` 10 | find_last('subject string', 'string', `9`) == null 11 | ``` 12 | 13 | ``` 14 | find_last('subject string', 'string', `0`, `14`) == `8` 15 | ``` 16 | 17 | ``` 18 | find_last('subject string', 'string', `0`, `13`) == null 19 | ``` 20 | -------------------------------------------------------------------------------- /website/jp/examples/floor.md: -------------------------------------------------------------------------------- 1 | ``` 2 | floor(`1.9`) == `1` 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/from_items.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/group_by.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/items.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/join.md: -------------------------------------------------------------------------------- 1 | ``` 2 | join('/', ['a', 'b', 'c']) == 'a/b/c' 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/json_parse.md: -------------------------------------------------------------------------------- 1 | ``` 2 | json_parse('{"foo":"bar"}') == { foo: 'bar' } 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/keys.md: -------------------------------------------------------------------------------- 1 | ``` 2 | keys({bar:'bam',foo:'baz'}) == ['bar','foo'] 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/label_match.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/length.md: -------------------------------------------------------------------------------- 1 | ``` 2 | length([`10`,`15`,`20`]) == `3` 3 | ``` 4 | 5 | ``` 6 | length([]) == `0` 7 | ``` 8 | 9 | ``` 10 | length(null) -> error 11 | ``` 12 | -------------------------------------------------------------------------------- /website/jp/examples/lookup.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/lower.md: -------------------------------------------------------------------------------- 1 | ``` 2 | lower('FOOBAR') == 'foobar' 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/map.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/max.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/max_by.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/merge.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/min.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/min_by.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/modulo.md: -------------------------------------------------------------------------------- 1 | ``` 2 | modulo(`10`, `3`) == `1` 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/multiply.md: -------------------------------------------------------------------------------- 1 | ### With numbers 2 | 3 | ``` 4 | multiply(`1`, `2`) == `2` 5 | ``` 6 | 7 | ### With durations 8 | 9 | ``` 10 | multiply('1h', `2`) == '2h' 11 | ``` 12 | 13 | ### With quantities 14 | 15 | ``` 16 | multiply('1Mi', `2`) == '2Mi' 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /website/jp/examples/not_null.md: -------------------------------------------------------------------------------- 1 | ``` 2 | not_null(null, null, 'foo') == 'foo' 3 | ``` 4 | 5 | ``` 6 | not_null(null, null) == null 7 | ``` 8 | -------------------------------------------------------------------------------- /website/jp/examples/object_from_lists.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/pad_left.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/pad_right.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/parse_json.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/parse_yaml.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/path_canonicalize.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/pattern_match.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/random.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/regex_match.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/regex_replace_all.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/regex_replace_all_literal.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/replace.md: -------------------------------------------------------------------------------- 1 | ``` 2 | replace('foobar', 'oo', 'ii') == 'fiibar' 3 | ``` 4 | 5 | ``` 6 | replace('foobar', 'o', 'i', `1`) == 'fiobar' 7 | ``` 8 | -------------------------------------------------------------------------------- /website/jp/examples/replace_all.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/reverse.md: -------------------------------------------------------------------------------- 1 | ``` 2 | reverse('abcd') == 'dcba' 3 | ``` 4 | 5 | ``` 6 | reverse([`1`, `2`, `3`, `4`]) == [`4`, `3`, `2`, `1`] 7 | ``` 8 | -------------------------------------------------------------------------------- /website/jp/examples/round.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/semver_compare.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/sort.md: -------------------------------------------------------------------------------- 1 | ``` 2 | sort(['b', 'a', 'c']) == ['a', 'b', 'c'] 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/sort_by.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/split.md: -------------------------------------------------------------------------------- 1 | ``` 2 | split('average|-|min|-|max|-|mean|-|median', '|-|', `3`) == ['average', 'min', 'max', 'mean|-|median'] 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/starts_with.md: -------------------------------------------------------------------------------- 1 | ``` 2 | starts_with('foobar', 'foo') == `true` 3 | ``` 4 | 5 | ``` 6 | starts_with('foobar', 'bar') == `false` 7 | ``` 8 | -------------------------------------------------------------------------------- /website/jp/examples/subtract.md: -------------------------------------------------------------------------------- 1 | ### With numbers 2 | 3 | ``` 4 | subtract(`2`, `1`) == `1` 5 | ``` 6 | 7 | ### With durations 8 | 9 | ``` 10 | subtract('2h', '1h') == '1h' 11 | ``` 12 | 13 | ### With quantities 14 | 15 | ``` 16 | subtract('2Mi', '1Mi') == '1Mi' 17 | ``` 18 | -------------------------------------------------------------------------------- /website/jp/examples/sum.md: -------------------------------------------------------------------------------- 1 | ``` 2 | sum(`[]`) == `0` 3 | ``` 4 | 5 | ``` 6 | sum([`10`, `15`]) == `25` 7 | ``` 8 | -------------------------------------------------------------------------------- /website/jp/examples/time_add.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/time_after.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/time_before.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/time_between.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/time_diff.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/time_now.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/time_now_utc.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/time_parse.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/time_since.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/time_to_cron.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/time_truncate.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/time_utc.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/to_array.md: -------------------------------------------------------------------------------- 1 | ``` 2 | to_array(`true`) == [`true`] 3 | ``` 4 | 5 | ``` 6 | to_array([`10`, `15`, `20`]) == [`10`, `15`, `20`] 7 | ``` 8 | 9 | ``` 10 | to_array(`[]`) == [] 11 | ``` 12 | -------------------------------------------------------------------------------- /website/jp/examples/to_boolean.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/to_lower.md: -------------------------------------------------------------------------------- 1 | ``` 2 | lower('FOOBAR') == 'foobar' 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/to_number.md: -------------------------------------------------------------------------------- 1 | ``` 2 | to_number('1.0') == `1` 3 | ``` 4 | 5 | ``` 6 | to_number(`1.0`) == `1` 7 | ``` 8 | 9 | ``` 10 | to_number(`false`) == null 11 | ``` 12 | -------------------------------------------------------------------------------- /website/jp/examples/to_string.md: -------------------------------------------------------------------------------- 1 | ``` 2 | to_string(`2`) == '2' 3 | ``` 4 | 5 | ``` 6 | to_string('foobar') == 'foobar' 7 | ``` 8 | 9 | ``` 10 | to_string(null) == 'null' 11 | ``` 12 | 13 | ``` 14 | to_string({bar:'bam',foo:'baz'}) == '{"bar":"bam","foo":"baz"}' 15 | ``` 16 | -------------------------------------------------------------------------------- /website/jp/examples/to_upper.md: -------------------------------------------------------------------------------- 1 | ``` 2 | upper('foobar') == 'FOOBAR' 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/trim.md: -------------------------------------------------------------------------------- 1 | ``` 2 | trim(' foobar ', 'fbr ') == 'ooba' 3 | ``` 4 | 5 | ``` 6 | trim(' foobar ', 'fbr') == ' foobar ' 7 | ``` 8 | -------------------------------------------------------------------------------- /website/jp/examples/trim_left.md: -------------------------------------------------------------------------------- 1 | ``` 2 | trim_left(' foobar ', 'fbr ') == 'oobar ' 3 | ``` 4 | 5 | ``` 6 | trim_left(' foobar ', 'fbr') == ' foobar ' 7 | ``` 8 | -------------------------------------------------------------------------------- /website/jp/examples/trim_prefix.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/trim_right.md: -------------------------------------------------------------------------------- 1 | ``` 2 | trim_right(' foobar ', 'fbr ') == ' fooba' 3 | ``` 4 | 5 | ``` 6 | trim_right(' foobar ', 'fbr') == ' foobar ' 7 | ``` 8 | -------------------------------------------------------------------------------- /website/jp/examples/trim_space.md: -------------------------------------------------------------------------------- 1 | ``` 2 | trim_space(' foobar ') == 'foobar' 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/truncate.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/type.md: -------------------------------------------------------------------------------- 1 | ``` 2 | type(`false`) == 'boolean' 3 | ``` 4 | 5 | ``` 6 | type(null) == 'null' 7 | ``` 8 | 9 | ``` 10 | type('foobar') == 'string' 11 | ``` 12 | -------------------------------------------------------------------------------- /website/jp/examples/upper.md: -------------------------------------------------------------------------------- 1 | ``` 2 | upper('foobar') == 'FOOBAR' 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/values.md: -------------------------------------------------------------------------------- 1 | ``` 2 | values({bar:'bam',foo:'baz'}) == ['bam','baz'] 3 | ``` 4 | -------------------------------------------------------------------------------- /website/jp/examples/wildcard.md: -------------------------------------------------------------------------------- 1 | ``` 2 | wildcard('foo*', 'foobar') == `true` 3 | ``` 4 | 5 | ``` 6 | wildcard('fooba?', 'foobar') == `true` 7 | ``` 8 | -------------------------------------------------------------------------------- /website/jp/examples/x509_decode.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/x_k8s_exists.md: -------------------------------------------------------------------------------- 1 | !!! info "Clustered resources" 2 | 3 | For clustered resources, you can leave the namespace empty `''`. 4 | 5 | ``` 6 | # `$client` is a binding pointing to a Kubernetes client 7 | 8 | x_k8s_exists($client, 'apps/v1', 'Deployment', 'crossplane-system', 'crossplane') 9 | ``` 10 | -------------------------------------------------------------------------------- /website/jp/examples/x_k8s_get.md: -------------------------------------------------------------------------------- 1 | !!! info "Clustered resources" 2 | 3 | For clustered resources, you can leave the namespace empty `''`. 4 | 5 | ``` 6 | # `$client` is a binding pointing to a Kubernetes client 7 | 8 | x_k8s_get($client, 'apps/v1', 'Deployment', 'crossplane-system', 'crossplane') 9 | ``` 10 | -------------------------------------------------------------------------------- /website/jp/examples/x_k8s_list.md: -------------------------------------------------------------------------------- 1 | !!! info "Clustered resources" 2 | 3 | For clustered resources, you can leave the namespace empty `''`. 4 | 5 | ``` 6 | # `$client` is a binding pointing to a Kubernetes client 7 | 8 | x_k8s_list($client, 'apps/v1', 'Deployment', 'crossplane-system') 9 | ``` 10 | -------------------------------------------------------------------------------- /website/jp/examples/x_k8s_resource_exists.md: -------------------------------------------------------------------------------- 1 | !!! info "Clustered resources" 2 | 3 | For clustered resources, you can leave the namespace empty `''`. 4 | 5 | ``` 6 | # `$client` is a binding pointing to a Kubernetes client 7 | 8 | x_k8s_resource_exists($client, 'apps/v1', 'Deployment') 9 | ``` 10 | -------------------------------------------------------------------------------- /website/jp/examples/x_k8s_server_version.md: -------------------------------------------------------------------------------- 1 | ``` 2 | # `$client` is a binding pointing to a Kubernetes client 3 | 4 | x_k8s_server_version($client) 5 | ``` 6 | -------------------------------------------------------------------------------- /website/jp/examples/x_metrics_decode.md: -------------------------------------------------------------------------------- 1 | TODO 2 | -------------------------------------------------------------------------------- /website/jp/examples/zip.md: -------------------------------------------------------------------------------- 1 | ``` 2 | zip(['a', 'b'], [`1`, `2`]) == [['a', `1`], ['b', `2`]] 3 | ``` 4 | --------------------------------------------------------------------------------