summaryrefslogtreecommitdiffstats
path: root/test/schemas/negative_test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:06:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:06:49 +0000
commit2fe34b6444502079dc0b84365ce82dbc92de308e (patch)
tree8fedcab52bbbc3db6c5aa909a88a7a7b81685018 /test/schemas/negative_test
parentInitial commit. (diff)
downloadansible-lint-2fe34b6444502079dc0b84365ce82dbc92de308e.tar.xz
ansible-lint-2fe34b6444502079dc0b84365ce82dbc92de308e.zip
Adding upstream version 6.17.2.upstream/6.17.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'test/schemas/negative_test')
-rw-r--r--test/schemas/negative_test/.ansible-lint4
-rw-r--r--test/schemas/negative_test/.ansible-lint.md139
-rw-r--r--test/schemas/negative_test/.config/ansible-lint.yml3
-rw-r--r--test/schemas/negative_test/.config/ansible-lint.yml.md42
-rw-r--r--test/schemas/negative_test/changelogs/invalid-date/changelogs/changelog.yaml4
-rw-r--r--test/schemas/negative_test/changelogs/invalid-date/changelogs/changelog.yaml.md40
-rw-r--r--test/schemas/negative_test/changelogs/invalid-plugin-namespace/changelogs/changelog.yaml8
-rw-r--r--test/schemas/negative_test/changelogs/invalid-plugin-namespace/changelogs/changelog.yaml.md34
-rw-r--r--test/schemas/negative_test/changelogs/list/changelogs/changelog.yaml4
-rw-r--r--test/schemas/negative_test/changelogs/list/changelogs/changelog.yaml.md34
-rw-r--r--test/schemas/negative_test/changelogs/no-semver/changelogs/changelog.yaml2
-rw-r--r--test/schemas/negative_test/changelogs/no-semver/changelogs/changelog.yaml.md34
-rw-r--r--test/schemas/negative_test/changelogs/unknown-keys/changelogs/changelog.yaml2
-rw-r--r--test/schemas/negative_test/changelogs/unknown-keys/changelogs/changelog.yaml.md34
-rw-r--r--test/schemas/negative_test/galaxy_1/galaxy.yml12
-rw-r--r--test/schemas/negative_test/galaxy_1/galaxy.yml.md34
-rw-r--r--test/schemas/negative_test/inventory/broken_dev_inventory.yml10
-rw-r--r--test/schemas/negative_test/inventory/broken_dev_inventory.yml.md34
-rw-r--r--test/schemas/negative_test/meta/runtime.yml1
-rw-r--r--test/schemas/negative_test/meta/runtime.yml.md34
-rw-r--r--test/schemas/negative_test/molecule/platforms_children/molecule.yml5
-rw-r--r--test/schemas/negative_test/molecule/platforms_children/molecule.yml.md34
-rw-r--r--test/schemas/negative_test/molecule/platforms_networks/molecule.yml7
-rw-r--r--test/schemas/negative_test/molecule/platforms_networks/molecule.yml.md49
-rw-r--r--test/schemas/negative_test/playbooks/environment.yml3
-rw-r--r--test/schemas/negative_test/playbooks/environment.yml.md138
-rw-r--r--test/schemas/negative_test/playbooks/failed_when.yml6
-rw-r--r--test/schemas/negative_test/playbooks/failed_when.yml.md177
-rw-r--r--test/schemas/negative_test/playbooks/gather_facts.yml6
-rw-r--r--test/schemas/negative_test/playbooks/gather_facts.yml.md123
-rw-r--r--test/schemas/negative_test/playbooks/gather_subset.yml6
-rw-r--r--test/schemas/negative_test/playbooks/gather_subset.yml.md123
-rw-r--r--test/schemas/negative_test/playbooks/gather_subset2.yml7
-rw-r--r--test/schemas/negative_test/playbooks/gather_subset2.yml.md277
-rw-r--r--test/schemas/negative_test/playbooks/gather_subset3.yml7
-rw-r--r--test/schemas/negative_test/playbooks/gather_subset3.yml.md303
-rw-r--r--test/schemas/negative_test/playbooks/gather_subset4.yml6
-rw-r--r--test/schemas/negative_test/playbooks/gather_subset4.yml.md123
-rw-r--r--test/schemas/negative_test/playbooks/ignore_errors.yml6
-rw-r--r--test/schemas/negative_test/playbooks/ignore_errors.yml.md203
-rw-r--r--test/schemas/negative_test/playbooks/import_playbook.yml1
-rw-r--r--test/schemas/negative_test/playbooks/import_playbook.yml.md90
-rw-r--r--test/schemas/negative_test/playbooks/import_playbook_exclusive.yml4
-rw-r--r--test/schemas/negative_test/playbooks/import_playbook_exclusive.yml.md132
-rw-r--r--test/schemas/negative_test/playbooks/invalid-failed-when.yml15
-rw-r--r--test/schemas/negative_test/playbooks/invalid-failed-when.yml.md253
-rw-r--r--test/schemas/negative_test/playbooks/invalid-serial.yml2
-rw-r--r--test/schemas/negative_test/playbooks/invalid-serial.yml.md177
-rw-r--r--test/schemas/negative_test/playbooks/invalid.yml3
-rw-r--r--test/schemas/negative_test/playbooks/invalid.yml.md77
-rw-r--r--test/schemas/negative_test/playbooks/invalid_become.yml3
-rw-r--r--test/schemas/negative_test/playbooks/invalid_become.yml.md140
-rw-r--r--test/schemas/negative_test/playbooks/local_action.yml3
-rw-r--r--test/schemas/negative_test/playbooks/local_action.yml.md141
-rw-r--r--test/schemas/negative_test/playbooks/loop.yml7
-rw-r--r--test/schemas/negative_test/playbooks/loop.yml.md141
-rw-r--r--test/schemas/negative_test/playbooks/loop2.yml7
-rw-r--r--test/schemas/negative_test/playbooks/loop2.yml.md141
-rw-r--r--test/schemas/negative_test/playbooks/no_log_partial_template.yml7
-rw-r--r--test/schemas/negative_test/playbooks/no_log_partial_template.yml.md203
-rw-r--r--test/schemas/negative_test/playbooks/no_log_string.yml7
-rw-r--r--test/schemas/negative_test/playbooks/no_log_string.yml.md203
-rw-r--r--test/schemas/negative_test/playbooks/roles.yml2
-rw-r--r--test/schemas/negative_test/playbooks/roles.yml.md114
-rw-r--r--test/schemas/negative_test/playbooks/run_once_list.yml8
-rw-r--r--test/schemas/negative_test/playbooks/run_once_list.yml.md221
-rw-r--r--test/schemas/negative_test/playbooks/tags-mapping.yml2
-rw-r--r--test/schemas/negative_test/playbooks/tags-mapping.yml.md166
-rw-r--r--test/schemas/negative_test/playbooks/tags-number.yml2
-rw-r--r--test/schemas/negative_test/playbooks/tags-number.yml.md166
-rw-r--r--test/schemas/negative_test/playbooks/tasks.yml5
-rw-r--r--test/schemas/negative_test/playbooks/tasks.yml.md192
-rw-r--r--test/schemas/negative_test/playbooks/tasks/args_integer.yml2
-rw-r--r--test/schemas/negative_test/playbooks/tasks/args_integer.yml.md99
-rw-r--r--test/schemas/negative_test/playbooks/tasks/args_string.yml2
-rw-r--r--test/schemas/negative_test/playbooks/tasks/args_string.yml.md90
-rw-r--r--test/schemas/negative_test/playbooks/tasks/become_method_invalid.yml4
-rw-r--r--test/schemas/negative_test/playbooks/tasks/become_method_invalid.yml.md203
-rw-r--r--test/schemas/negative_test/playbooks/tasks/become_method_untemplated.yml.md181
-rw-r--r--test/schemas/negative_test/playbooks/tasks/ignore_errors.yml4
-rw-r--r--test/schemas/negative_test/playbooks/tasks/ignore_errors.yml.md129
-rw-r--r--test/schemas/negative_test/playbooks/tasks/invalid_block.yml2
-rw-r--r--test/schemas/negative_test/playbooks/tasks/invalid_block.yml.md62
-rw-r--r--test/schemas/negative_test/playbooks/tasks/local_action.yml1
-rw-r--r--test/schemas/negative_test/playbooks/tasks/local_action.yml.md67
-rw-r--r--test/schemas/negative_test/playbooks/tasks/loop.yml3
-rw-r--r--test/schemas/negative_test/playbooks/tasks/loop.yml.md67
-rw-r--r--test/schemas/negative_test/playbooks/tasks/loop2.yml3
-rw-r--r--test/schemas/negative_test/playbooks/tasks/loop2.yml.md67
-rw-r--r--test/schemas/negative_test/playbooks/tasks/no_log_number.yml3
-rw-r--r--test/schemas/negative_test/playbooks/tasks/no_log_number.yml.md147
-rw-r--r--test/schemas/negative_test/playbooks/tasks/no_log_string.yml5
-rw-r--r--test/schemas/negative_test/playbooks/tasks/no_log_string.yml.md129
-rw-r--r--test/schemas/negative_test/playbooks/tasks/tags-mapping.yml3
-rw-r--r--test/schemas/negative_test/playbooks/tasks/tags-mapping.yml.md125
-rw-r--r--test/schemas/negative_test/playbooks/tasks/tags-string.yml3
-rw-r--r--test/schemas/negative_test/playbooks/tasks/tags-string.yml.md125
-rw-r--r--test/schemas/negative_test/playbooks/tasks/when_integer.yml2
-rw-r--r--test/schemas/negative_test/playbooks/tasks/when_integer.yml.md155
-rw-r--r--test/schemas/negative_test/playbooks/tasks/when_object.yml2
-rw-r--r--test/schemas/negative_test/playbooks/tasks/when_object.yml.md155
-rw-r--r--test/schemas/negative_test/playbooks/tasks/with_items_boolean.yml2
-rw-r--r--test/schemas/negative_test/playbooks/tasks/with_items_boolean.yml.md88
-rw-r--r--test/schemas/negative_test/playbooks/tasks/with_items_untemplated_string.yml2
-rw-r--r--test/schemas/negative_test/playbooks/tasks/with_items_untemplated_string.yml.md88
-rw-r--r--test/schemas/negative_test/playbooks/var_files_list_number.yml5
-rw-r--r--test/schemas/negative_test/playbooks/var_files_list_number.yml.md144
-rw-r--r--test/schemas/negative_test/playbooks/var_files_list_of_list_number.yml5
-rw-r--r--test/schemas/negative_test/playbooks/var_files_list_of_list_number.yml.md157
-rw-r--r--test/schemas/negative_test/playbooks/var_files_number.yml4
-rw-r--r--test/schemas/negative_test/playbooks/var_files_number.yml.md122
-rw-r--r--test/schemas/negative_test/playbooks/vars/asterisk.yml2
-rw-r--r--test/schemas/negative_test/playbooks/vars/asterisk.yml.md77
-rw-r--r--test/schemas/negative_test/playbooks/vars/dash-in-var-name.yml2
-rw-r--r--test/schemas/negative_test/playbooks/vars/dash-in-var-name.yml.md77
-rw-r--r--test/schemas/negative_test/playbooks/vars/list.yml3
-rw-r--r--test/schemas/negative_test/playbooks/vars/list.yml.md77
-rw-r--r--test/schemas/negative_test/playbooks/vars/numeric-var-name.yml2
-rw-r--r--test/schemas/negative_test/playbooks/vars/numeric-var-name.yml.md77
-rw-r--r--test/schemas/negative_test/playbooks/vars/play-keyword.yml2
-rw-r--r--test/schemas/negative_test/playbooks/vars/play-keyword.yml.md77
-rw-r--r--test/schemas/negative_test/playbooks/vars/python-keyword.yml3
-rw-r--r--test/schemas/negative_test/playbooks/vars/python-keyword.yml.md86
-rw-r--r--test/schemas/negative_test/playbooks/vars/varname-numeric-prefix.yml2
-rw-r--r--test/schemas/negative_test/playbooks/vars/varname-numeric-prefix.yml.md77
-rw-r--r--test/schemas/negative_test/playbooks/vas_prompt.yml7
-rw-r--r--test/schemas/negative_test/playbooks/vas_prompt.yml.md118
-rw-r--r--test/schemas/negative_test/playbooks/when.yml11
-rw-r--r--test/schemas/negative_test/playbooks/when.yml.md286
-rw-r--r--test/schemas/negative_test/reqs3/meta/requirements.yml2
-rw-r--r--test/schemas/negative_test/reqs3/meta/requirements.yml.md101
-rw-r--r--test/schemas/negative_test/roles/meta/argument_specs.yml5
-rw-r--r--test/schemas/negative_test/roles/meta/argument_specs.yml.md34
-rw-r--r--test/schemas/negative_test/roles/meta/main.yml10
-rw-r--r--test/schemas/negative_test/roles/meta/main.yml.md58
-rw-r--r--test/schemas/negative_test/roles/meta_invalid_collection/meta/main.yml10
-rw-r--r--test/schemas/negative_test/roles/meta_invalid_collection/meta/main.yml.md34
-rw-r--r--test/schemas/negative_test/roles/meta_invalid_collections/meta/main.yml11
-rw-r--r--test/schemas/negative_test/roles/meta_invalid_collections/meta/main.yml.md34
-rw-r--r--test/schemas/negative_test/roles/meta_invalid_role_namespace/meta/main.yml12
-rw-r--r--test/schemas/negative_test/roles/meta_invalid_role_namespace/meta/main.yml.md58
-rw-r--r--test/schemas/negative_test/roles/role_with_bad_deps_in_meta/meta/main.yml13
-rw-r--r--test/schemas/negative_test/roles/role_with_bad_deps_in_meta/meta/main.yml.md101
143 files changed, 8679 insertions, 0 deletions
diff --git a/test/schemas/negative_test/.ansible-lint b/test/schemas/negative_test/.ansible-lint
new file mode 100644
index 0000000..86b5116
--- /dev/null
+++ b/test/schemas/negative_test/.ansible-lint
@@ -0,0 +1,4 @@
+---
+# .ansible-lint
+rules:
+ Wrong_Rule_name:
diff --git a/test/schemas/negative_test/.ansible-lint.md b/test/schemas/negative_test/.ansible-lint.md
new file mode 100644
index 0000000..f1f2308
--- /dev/null
+++ b/test/schemas/negative_test/.ansible-lint.md
@@ -0,0 +1,139 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/rules",
+ "keyword": "enum",
+ "message": "must be equal to one of the allowed values",
+ "params": {
+ "allowedValues": [
+ "command-instead-of-module",
+ "command-instead-of-shell",
+ "deprecated-bare-vars",
+ "deprecated-local-action",
+ "deprecated-module",
+ "empty-string-compare",
+ "fqcn",
+ "fqcn[action-core]",
+ "fqcn[action]",
+ "fqcn[canonical]",
+ "fqcn[keyword]",
+ "galaxy",
+ "galaxy[no-changelog]",
+ "galaxy[no-runtime]",
+ "galaxy[tags]",
+ "galaxy[version-incorrect]",
+ "galaxy[version-missing]",
+ "ignore-errors",
+ "inline-env-var",
+ "internal-error",
+ "jinja",
+ "jinja[invalid]",
+ "jinja[spacing]",
+ "key-order",
+ "latest",
+ "literal-compare",
+ "load-failure",
+ "load-failure[not-found]",
+ "loop-var-prefix",
+ "loop-var-prefix[missing]",
+ "loop-var-prefix[wrong]",
+ "meta-incorrect",
+ "meta-no-tags",
+ "meta-runtime",
+ "meta-video-links",
+ "name",
+ "name[casing]",
+ "name[play]",
+ "name[prefix]",
+ "name[template]",
+ "no-changed-when",
+ "no-handler",
+ "no-jinja-when",
+ "no-log-password",
+ "no-prompting",
+ "no-relative-paths",
+ "no-same-owner",
+ "no-tabs",
+ "only-builtins",
+ "package-latest",
+ "parser-error",
+ "partial-become",
+ "playbook-extension",
+ "risky-file-permissions",
+ "risky-octal",
+ "risky-shell-pipe",
+ "role-name",
+ "run-once",
+ "run-once[play]",
+ "run-once[task]",
+ "sanity",
+ "sanity[bad-ignore]",
+ "sanity[cannot-ignore]",
+ "schema",
+ "syntax-check",
+ "var-naming",
+ "yaml"
+ ]
+ },
+ "propertyName": "Wrong_Rule_name",
+ "schemaPath": "#/properties/rules/propertyNames/oneOf/0/enum"
+ },
+ {
+ "instancePath": "/rules",
+ "keyword": "pattern",
+ "message": "must match pattern \"^[a-z0-9-\\[\\]]+$\"",
+ "params": {
+ "pattern": "^[a-z0-9-\\[\\]]+$"
+ },
+ "propertyName": "Wrong_Rule_name",
+ "schemaPath": "#/properties/rules/propertyNames/oneOf/1/pattern"
+ },
+ {
+ "instancePath": "/rules",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "propertyName": "Wrong_Rule_name",
+ "schemaPath": "#/properties/rules/propertyNames/oneOf"
+ },
+ {
+ "instancePath": "/rules",
+ "keyword": "propertyNames",
+ "message": "property name must be valid",
+ "params": {
+ "propertyName": "Wrong_Rule_name"
+ },
+ "schemaPath": "#/properties/rules/propertyNames"
+ },
+ {
+ "instancePath": "/rules/Wrong_Rule_name",
+ "keyword": "type",
+ "message": "must be object",
+ "params": {
+ "type": "object"
+ },
+ "schemaPath": "#/$defs/rule/type"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [],
+ "parse_errors": [
+ {
+ "filename": "negative_test/.ansible-lint",
+ "message": "Failed to parse negative_test/.ansible-lint"
+ }
+ ]
+}
+```
diff --git a/test/schemas/negative_test/.config/ansible-lint.yml b/test/schemas/negative_test/.config/ansible-lint.yml
new file mode 100644
index 0000000..c12a2ef
--- /dev/null
+++ b/test/schemas/negative_test/.config/ansible-lint.yml
@@ -0,0 +1,3 @@
+---
+# .ansible-lint
+profile: invalid_profile
diff --git a/test/schemas/negative_test/.config/ansible-lint.yml.md b/test/schemas/negative_test/.config/ansible-lint.yml.md
new file mode 100644
index 0000000..4fe331e
--- /dev/null
+++ b/test/schemas/negative_test/.config/ansible-lint.yml.md
@@ -0,0 +1,42 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/profile",
+ "keyword": "enum",
+ "message": "must be equal to one of the allowed values",
+ "params": {
+ "allowedValues": [
+ "min",
+ "basic",
+ "moderate",
+ "safety",
+ "shared",
+ "production",
+ null
+ ]
+ },
+ "schemaPath": "#/properties/profile/enum"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/.config/ansible-lint.yml",
+ "path": "$.profile",
+ "message": "'invalid_profile' is not one of ['min', 'basic', 'moderate', 'safety', 'shared', 'production', None]",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/changelogs/invalid-date/changelogs/changelog.yaml b/test/schemas/negative_test/changelogs/invalid-date/changelogs/changelog.yaml
new file mode 100644
index 0000000..2639e9a
--- /dev/null
+++ b/test/schemas/negative_test/changelogs/invalid-date/changelogs/changelog.yaml
@@ -0,0 +1,4 @@
+---
+releases:
+ 1.0.0:
+ release_date: 01-01-2020 # invalid date format, must be ISO-8601 !
diff --git a/test/schemas/negative_test/changelogs/invalid-date/changelogs/changelog.yaml.md b/test/schemas/negative_test/changelogs/invalid-date/changelogs/changelog.yaml.md
new file mode 100644
index 0000000..72b4f96
--- /dev/null
+++ b/test/schemas/negative_test/changelogs/invalid-date/changelogs/changelog.yaml.md
@@ -0,0 +1,40 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/releases/1.0.0/release_date",
+ "keyword": "pattern",
+ "message": "must match pattern \"\\d\\d\\d\\d-\\d\\d-\\d\\d\"",
+ "params": {
+ "pattern": "\\d\\d\\d\\d-\\d\\d-\\d\\d"
+ },
+ "schemaPath": "#/properties/release_date/pattern"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/changelogs/invalid-date/changelogs/changelog.yaml",
+ "path": "$.releases.1.0.0.release_date",
+ "message": "'01-01-2020' is not a 'date'",
+ "has_sub_errors": false
+ },
+ {
+ "filename": "negative_test/changelogs/invalid-date/changelogs/changelog.yaml",
+ "path": "$.releases.1.0.0.release_date",
+ "message": "'01-01-2020' does not match '\\\\d\\\\d\\\\d\\\\d-\\\\d\\\\d-\\\\d\\\\d'",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/changelogs/invalid-plugin-namespace/changelogs/changelog.yaml b/test/schemas/negative_test/changelogs/invalid-plugin-namespace/changelogs/changelog.yaml
new file mode 100644
index 0000000..99632a4
--- /dev/null
+++ b/test/schemas/negative_test/changelogs/invalid-plugin-namespace/changelogs/changelog.yaml
@@ -0,0 +1,8 @@
+---
+releases:
+ 1.0.0:
+ plugins:
+ lookup:
+ - name: reverse
+ description: Reverse magic
+ namespace: "foo" # namespace must be null for plugins and objects
diff --git a/test/schemas/negative_test/changelogs/invalid-plugin-namespace/changelogs/changelog.yaml.md b/test/schemas/negative_test/changelogs/invalid-plugin-namespace/changelogs/changelog.yaml.md
new file mode 100644
index 0000000..ef847c3
--- /dev/null
+++ b/test/schemas/negative_test/changelogs/invalid-plugin-namespace/changelogs/changelog.yaml.md
@@ -0,0 +1,34 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/releases/1.0.0/plugins/lookup/0/namespace",
+ "keyword": "type",
+ "message": "must be null",
+ "params": {
+ "type": "null"
+ },
+ "schemaPath": "#/$defs/plugin-descriptions/items/properties/namespace/type"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/changelogs/invalid-plugin-namespace/changelogs/changelog.yaml",
+ "path": "$.releases.1.0.0.plugins.lookup[0].namespace",
+ "message": "'foo' is not of type 'null'",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/changelogs/list/changelogs/changelog.yaml b/test/schemas/negative_test/changelogs/list/changelogs/changelog.yaml
new file mode 100644
index 0000000..72def5b
--- /dev/null
+++ b/test/schemas/negative_test/changelogs/list/changelogs/changelog.yaml
@@ -0,0 +1,4 @@
+---
+- this is invalid
+- as changelog must be object (mapping)
+- not an array (sequence)
diff --git a/test/schemas/negative_test/changelogs/list/changelogs/changelog.yaml.md b/test/schemas/negative_test/changelogs/list/changelogs/changelog.yaml.md
new file mode 100644
index 0000000..5938944
--- /dev/null
+++ b/test/schemas/negative_test/changelogs/list/changelogs/changelog.yaml.md
@@ -0,0 +1,34 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be object",
+ "params": {
+ "type": "object"
+ },
+ "schemaPath": "#/type"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/changelogs/list/changelogs/changelog.yaml",
+ "path": "$",
+ "message": "['this is invalid', 'as changelog must be object (mapping)', 'not an array (sequence)'] is not of type 'object'",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/changelogs/no-semver/changelogs/changelog.yaml b/test/schemas/negative_test/changelogs/no-semver/changelogs/changelog.yaml
new file mode 100644
index 0000000..d08ebd0
--- /dev/null
+++ b/test/schemas/negative_test/changelogs/no-semver/changelogs/changelog.yaml
@@ -0,0 +1,2 @@
+---
+releases: foo # <-- not a semver
diff --git a/test/schemas/negative_test/changelogs/no-semver/changelogs/changelog.yaml.md b/test/schemas/negative_test/changelogs/no-semver/changelogs/changelog.yaml.md
new file mode 100644
index 0000000..64c4665
--- /dev/null
+++ b/test/schemas/negative_test/changelogs/no-semver/changelogs/changelog.yaml.md
@@ -0,0 +1,34 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/releases",
+ "keyword": "type",
+ "message": "must be object",
+ "params": {
+ "type": "object"
+ },
+ "schemaPath": "#/properties/releases/type"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/changelogs/no-semver/changelogs/changelog.yaml",
+ "path": "$.releases",
+ "message": "'foo' is not of type 'object'",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/changelogs/unknown-keys/changelogs/changelog.yaml b/test/schemas/negative_test/changelogs/unknown-keys/changelogs/changelog.yaml
new file mode 100644
index 0000000..a97e4e2
--- /dev/null
+++ b/test/schemas/negative_test/changelogs/unknown-keys/changelogs/changelog.yaml
@@ -0,0 +1,2 @@
+---
+release: {} # <- unknown key, correct would be releases
diff --git a/test/schemas/negative_test/changelogs/unknown-keys/changelogs/changelog.yaml.md b/test/schemas/negative_test/changelogs/unknown-keys/changelogs/changelog.yaml.md
new file mode 100644
index 0000000..490bdbe
--- /dev/null
+++ b/test/schemas/negative_test/changelogs/unknown-keys/changelogs/changelog.yaml.md
@@ -0,0 +1,34 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "release"
+ },
+ "schemaPath": "#/additionalProperties"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/changelogs/unknown-keys/changelogs/changelog.yaml",
+ "path": "$",
+ "message": "Additional properties are not allowed ('release' was unexpected)",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/galaxy_1/galaxy.yml b/test/schemas/negative_test/galaxy_1/galaxy.yml
new file mode 100644
index 0000000..914d219
--- /dev/null
+++ b/test/schemas/negative_test/galaxy_1/galaxy.yml
@@ -0,0 +1,12 @@
+name: foo
+namespace: bar
+version: 1.2.3
+authors:
+ - John
+readme: ../README.md
+description: ...
+repository: https://www.github.com/my_org/my_collection
+manifest:
+ directive: # <-- typo, should be "directives"
+ - "foo"
+ omit_default_directives: true
diff --git a/test/schemas/negative_test/galaxy_1/galaxy.yml.md b/test/schemas/negative_test/galaxy_1/galaxy.yml.md
new file mode 100644
index 0000000..bbb79ec
--- /dev/null
+++ b/test/schemas/negative_test/galaxy_1/galaxy.yml.md
@@ -0,0 +1,34 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/manifest",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "directive"
+ },
+ "schemaPath": "#/properties/manifest/additionalProperties"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/galaxy_1/galaxy.yml",
+ "path": "$.manifest",
+ "message": "Additional properties are not allowed ('directive' was unexpected)",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/inventory/broken_dev_inventory.yml b/test/schemas/negative_test/inventory/broken_dev_inventory.yml
new file mode 100644
index 0000000..ce84309
--- /dev/null
+++ b/test/schemas/negative_test/inventory/broken_dev_inventory.yml
@@ -0,0 +1,10 @@
+---
+# See https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html
+ungrouped: {}
+all:
+ hosts:
+ mail.example.com:
+ children:
+ foo: {} # <-- invalid based on inventory json schema
+ vars: {}
+webservers: {}
diff --git a/test/schemas/negative_test/inventory/broken_dev_inventory.yml.md b/test/schemas/negative_test/inventory/broken_dev_inventory.yml.md
new file mode 100644
index 0000000..d4fefaf
--- /dev/null
+++ b/test/schemas/negative_test/inventory/broken_dev_inventory.yml.md
@@ -0,0 +1,34 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/all",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "foo"
+ },
+ "schemaPath": "#/$defs/special-group/additionalProperties"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/inventory/broken_dev_inventory.yml",
+ "path": "$.all",
+ "message": "Additional properties are not allowed ('foo' was unexpected)",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/meta/runtime.yml b/test/schemas/negative_test/meta/runtime.yml
new file mode 100644
index 0000000..c143dc6
--- /dev/null
+++ b/test/schemas/negative_test/meta/runtime.yml
@@ -0,0 +1 @@
+requires_ansible: ">= 2.12" # invalid as space is not allowed!
diff --git a/test/schemas/negative_test/meta/runtime.yml.md b/test/schemas/negative_test/meta/runtime.yml.md
new file mode 100644
index 0000000..761fa6f
--- /dev/null
+++ b/test/schemas/negative_test/meta/runtime.yml.md
@@ -0,0 +1,34 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/requires_ansible",
+ "keyword": "pattern",
+ "message": "must match pattern \"^[^\\s]*$\"",
+ "params": {
+ "pattern": "^[^\\s]*$"
+ },
+ "schemaPath": "#/properties/requires_ansible/pattern"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/meta/runtime.yml",
+ "path": "$.requires_ansible",
+ "message": "'>= 2.12' does not match '^[^\\\\s]*$'",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/molecule/platforms_children/molecule.yml b/test/schemas/negative_test/molecule/platforms_children/molecule.yml
new file mode 100644
index 0000000..6800584
--- /dev/null
+++ b/test/schemas/negative_test/molecule/platforms_children/molecule.yml
@@ -0,0 +1,5 @@
+driver:
+ name: delegated
+platforms:
+ - name: foo
+ children: 2 # invalid, must be list of strings
diff --git a/test/schemas/negative_test/molecule/platforms_children/molecule.yml.md b/test/schemas/negative_test/molecule/platforms_children/molecule.yml.md
new file mode 100644
index 0000000..68e09eb
--- /dev/null
+++ b/test/schemas/negative_test/molecule/platforms_children/molecule.yml.md
@@ -0,0 +1,34 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/platforms/0/children",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/properties/children/type"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/molecule/platforms_children/molecule.yml",
+ "path": "$.platforms[0].children",
+ "message": "2 is not of type 'array'",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/molecule/platforms_networks/molecule.yml b/test/schemas/negative_test/molecule/platforms_networks/molecule.yml
new file mode 100644
index 0000000..4ae9799
--- /dev/null
+++ b/test/schemas/negative_test/molecule/platforms_networks/molecule.yml
@@ -0,0 +1,7 @@
+driver:
+ name: docker
+platforms:
+ - name: docker
+ networks: # invalid, must be list of dictionaries
+ - foo
+ - bar
diff --git a/test/schemas/negative_test/molecule/platforms_networks/molecule.yml.md b/test/schemas/negative_test/molecule/platforms_networks/molecule.yml.md
new file mode 100644
index 0000000..74b8de7
--- /dev/null
+++ b/test/schemas/negative_test/molecule/platforms_networks/molecule.yml.md
@@ -0,0 +1,49 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/platforms/0/networks/0",
+ "keyword": "type",
+ "message": "must be object",
+ "params": {
+ "type": "object"
+ },
+ "schemaPath": "#/$defs/platform-network/type"
+ },
+ {
+ "instancePath": "/platforms/0/networks/1",
+ "keyword": "type",
+ "message": "must be object",
+ "params": {
+ "type": "object"
+ },
+ "schemaPath": "#/$defs/platform-network/type"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/molecule/platforms_networks/molecule.yml",
+ "path": "$.platforms[0].networks[0]",
+ "message": "'foo' is not of type 'object'",
+ "has_sub_errors": false
+ },
+ {
+ "filename": "negative_test/molecule/platforms_networks/molecule.yml",
+ "path": "$.platforms[0].networks[1]",
+ "message": "'bar' is not of type 'object'",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/environment.yml b/test/schemas/negative_test/playbooks/environment.yml
new file mode 100644
index 0000000..2064aca
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/environment.yml
@@ -0,0 +1,3 @@
+---
+- hosts: localhost
+ environment: "{{ foo }}-123" # <- invalid only a full jinja string is allowed, or a list of strings
diff --git a/test/schemas/negative_test/playbooks/environment.yml.md b/test/schemas/negative_test/playbooks/environment.yml.md
new file mode 100644
index 0000000..8923cb3
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/environment.yml.md
@@ -0,0 +1,138 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "environment"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/environment",
+ "keyword": "type",
+ "message": "must be object",
+ "params": {
+ "type": "object"
+ },
+ "schemaPath": "#/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/environment",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/environment",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/environment.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'environment': '{{ foo }}-123'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'environment', 'hosts' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'environment', 'hosts' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'environment': '{{ foo }}-123'} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].environment",
+ "message": "'{{ foo }}-123' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].environment",
+ "message": "'{{ foo }}-123' is not of type 'object'"
+ },
+ {
+ "path": "$[0].environment",
+ "message": "'{{ foo }}-123' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/failed_when.yml b/test/schemas/negative_test/playbooks/failed_when.yml
new file mode 100644
index 0000000..59b7272
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/failed_when.yml
@@ -0,0 +1,6 @@
+- hosts: localhost
+ tasks:
+ - name: foo
+ ansible.builtin.debug:
+ msg: foo!
+ failed_when: 123 # <- not ok
diff --git a/test/schemas/negative_test/playbooks/failed_when.yml.md b/test/schemas/negative_test/playbooks/failed_when.yml.md
new file mode 100644
index 0000000..e843e1f
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/failed_when.yml.md
@@ -0,0 +1,177 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/tasks/0/failed_when",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/failed_when",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/failed_when",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/2/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/failed_when",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/failed_when.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'name': 'foo', 'ansible.builtin.debug': {'msg': 'foo!'}, 'failed_when': 123}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'name': 'foo', 'ansible.builtin.debug': {'msg': 'foo!'}, 'failed_when': 123}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "{'name': 'foo', 'ansible.builtin.debug': {'msg': 'foo!'}, 'failed_when': 123} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0].failed_when",
+ "message": "123 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].failed_when",
+ "message": "123 is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].failed_when",
+ "message": "123 is not of type 'string'"
+ },
+ {
+ "path": "$[0].tasks[0].failed_when",
+ "message": "123 is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/gather_facts.yml b/test/schemas/negative_test/playbooks/gather_facts.yml
new file mode 100644
index 0000000..d1b1345
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/gather_facts.yml
@@ -0,0 +1,6 @@
+---
+- hosts: localhost
+ gather_facts: non
+ tasks:
+ - ansible.builtin.debug:
+ msg: foo
diff --git a/test/schemas/negative_test/playbooks/gather_facts.yml.md b/test/schemas/negative_test/playbooks/gather_facts.yml.md
new file mode 100644
index 0000000..0eb3a4b
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/gather_facts.yml.md
@@ -0,0 +1,123 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "gather_facts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/gather_facts",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/properties/gather_facts/type"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/gather_facts.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'gather_facts': 'non', 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'gather_facts', 'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'gather_facts', 'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'gather_facts': 'non', 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].gather_facts",
+ "message": "'non' is not of type 'boolean'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/gather_subset.yml b/test/schemas/negative_test/playbooks/gather_subset.yml
new file mode 100644
index 0000000..455d683
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/gather_subset.yml
@@ -0,0 +1,6 @@
+---
+- hosts: localhost
+ gather_subset: all
+ tasks:
+ - ansible.builtin.debug:
+ msg: foo
diff --git a/test/schemas/negative_test/playbooks/gather_subset.yml.md b/test/schemas/negative_test/playbooks/gather_subset.yml.md
new file mode 100644
index 0000000..b426a23
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/gather_subset.yml.md
@@ -0,0 +1,123 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "gather_subset"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/gather_subset",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/properties/gather_subset/type"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/gather_subset.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'gather_subset': 'all', 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'gather_subset', 'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'gather_subset', 'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'gather_subset': 'all', 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].gather_subset",
+ "message": "'all' is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/gather_subset2.yml b/test/schemas/negative_test/playbooks/gather_subset2.yml
new file mode 100644
index 0000000..d5a39ae
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/gather_subset2.yml
@@ -0,0 +1,7 @@
+---
+- hosts: localhost
+ gather_subset:
+ - invalid
+ tasks:
+ - ansible.builtin.debug:
+ msg: foo
diff --git a/test/schemas/negative_test/playbooks/gather_subset2.yml.md b/test/schemas/negative_test/playbooks/gather_subset2.yml.md
new file mode 100644
index 0000000..8d6be68
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/gather_subset2.yml.md
@@ -0,0 +1,277 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "gather_subset"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/gather_subset/0",
+ "keyword": "enum",
+ "message": "must be equal to one of the allowed values",
+ "params": {
+ "allowedValues": [
+ "all",
+ "min",
+ "all_ipv4_addresses",
+ "all_ipv6_addresses",
+ "apparmor",
+ "architecture",
+ "caps",
+ "chroot,cmdline",
+ "date_time",
+ "default_ipv4",
+ "default_ipv6",
+ "devices",
+ "distribution",
+ "distribution_major_version",
+ "distribution_release",
+ "distribution_version",
+ "dns",
+ "effective_group_ids",
+ "effective_user_id",
+ "env",
+ "facter",
+ "fips",
+ "hardware",
+ "interfaces",
+ "is_chroot",
+ "iscsi",
+ "kernel",
+ "local",
+ "lsb",
+ "machine",
+ "machine_id",
+ "mounts",
+ "network",
+ "ohai",
+ "os_family",
+ "pkg_mgr",
+ "platform",
+ "processor",
+ "processor_cores",
+ "processor_count",
+ "python",
+ "python_version",
+ "real_user_id",
+ "selinux",
+ "service_mgr",
+ "ssh_host_key_dsa_public",
+ "ssh_host_key_ecdsa_public",
+ "ssh_host_key_ed25519_public",
+ "ssh_host_key_rsa_public",
+ "ssh_host_pub_keys",
+ "ssh_pub_keys",
+ "system",
+ "system_capabilities",
+ "system_capabilities_enforced",
+ "user",
+ "user_dir",
+ "user_gecos",
+ "user_gid",
+ "user_id",
+ "user_shell",
+ "user_uid",
+ "virtual",
+ "virtualization_role",
+ "virtualization_type"
+ ]
+ },
+ "schemaPath": "#/properties/gather_subset/items/anyOf/0/enum"
+ },
+ {
+ "instancePath": "/0/gather_subset/0",
+ "keyword": "enum",
+ "message": "must be equal to one of the allowed values",
+ "params": {
+ "allowedValues": [
+ "!all",
+ "!min",
+ "!all_ipv4_addresses",
+ "!all_ipv6_addresses",
+ "!apparmor",
+ "!architecture",
+ "!caps",
+ "!chroot,cmdline",
+ "!date_time",
+ "!default_ipv4",
+ "!default_ipv6",
+ "!devices",
+ "!distribution",
+ "!distribution_major_version",
+ "!distribution_release",
+ "!distribution_version",
+ "!dns",
+ "!effective_group_ids",
+ "!effective_user_id",
+ "!env",
+ "!facter",
+ "!fips",
+ "!hardware",
+ "!interfaces",
+ "!is_chroot",
+ "!iscsi",
+ "!kernel",
+ "!local",
+ "!lsb",
+ "!machine",
+ "!machine_id",
+ "!mounts",
+ "!network",
+ "!ohai",
+ "!os_family",
+ "!pkg_mgr",
+ "!platform",
+ "!processor",
+ "!processor_cores",
+ "!processor_count",
+ "!python",
+ "!python_version",
+ "!real_user_id",
+ "!selinux",
+ "!service_mgr",
+ "!ssh_host_key_dsa_public",
+ "!ssh_host_key_ecdsa_public",
+ "!ssh_host_key_ed25519_public",
+ "!ssh_host_key_rsa_public",
+ "!ssh_host_pub_keys",
+ "!ssh_pub_keys",
+ "!system",
+ "!system_capabilities",
+ "!system_capabilities_enforced",
+ "!user",
+ "!user_dir",
+ "!user_gecos",
+ "!user_gid",
+ "!user_id",
+ "!user_shell",
+ "!user_uid",
+ "!virtual",
+ "!virtualization_role",
+ "!virtualization_type"
+ ]
+ },
+ "schemaPath": "#/properties/gather_subset/items/anyOf/1/enum"
+ },
+ {
+ "instancePath": "/0/gather_subset/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/properties/gather_subset/items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/gather_subset2.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'gather_subset': ['invalid'], 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'gather_subset', 'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'gather_subset', 'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'gather_subset': ['invalid'], 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].gather_subset[0]",
+ "message": "'invalid' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].gather_subset[0]",
+ "message": "'invalid' is not one of ['all', 'min', 'all_ipv4_addresses', 'all_ipv6_addresses', 'apparmor', 'architecture', 'caps', 'chroot,cmdline', 'date_time', 'default_ipv4', 'default_ipv6', 'devices', 'distribution', 'distribution_major_version', 'distribution_release', 'distribution_version', 'dns', 'effective_group_ids', 'effective_user_id', 'env', 'facter', 'fips', 'hardware', 'interfaces', 'is_chroot', 'iscsi', 'kernel', 'local', 'lsb', 'machine', 'machine_id', 'mounts', 'network', 'ohai', 'os_family', 'pkg_mgr', 'platform', 'processor', 'processor_cores', 'processor_count', 'python', 'python_version', 'real_user_id', 'selinux', 'service_mgr', 'ssh_host_key_dsa_public', 'ssh_host_key_ecdsa_public', 'ssh_host_key_ed25519_public', 'ssh_host_key_rsa_public', 'ssh_host_pub_keys', 'ssh_pub_keys', 'system', 'system_capabilities', 'system_capabilities_enforced', 'user', 'user_dir', 'user_gecos', 'user_gid', 'user_id', 'user_shell', 'user_uid', 'virtual', 'virtualization_role', 'virtualization_type']"
+ },
+ {
+ "path": "$[0].gather_subset[0]",
+ "message": "'invalid' is not one of ['!all', '!min', '!all_ipv4_addresses', '!all_ipv6_addresses', '!apparmor', '!architecture', '!caps', '!chroot,cmdline', '!date_time', '!default_ipv4', '!default_ipv6', '!devices', '!distribution', '!distribution_major_version', '!distribution_release', '!distribution_version', '!dns', '!effective_group_ids', '!effective_user_id', '!env', '!facter', '!fips', '!hardware', '!interfaces', '!is_chroot', '!iscsi', '!kernel', '!local', '!lsb', '!machine', '!machine_id', '!mounts', '!network', '!ohai', '!os_family', '!pkg_mgr', '!platform', '!processor', '!processor_cores', '!processor_count', '!python', '!python_version', '!real_user_id', '!selinux', '!service_mgr', '!ssh_host_key_dsa_public', '!ssh_host_key_ecdsa_public', '!ssh_host_key_ed25519_public', '!ssh_host_key_rsa_public', '!ssh_host_pub_keys', '!ssh_pub_keys', '!system', '!system_capabilities', '!system_capabilities_enforced', '!user', '!user_dir', '!user_gecos', '!user_gid', '!user_id', '!user_shell', '!user_uid', '!virtual', '!virtualization_role', '!virtualization_type']"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/gather_subset3.yml b/test/schemas/negative_test/playbooks/gather_subset3.yml
new file mode 100644
index 0000000..05e4028
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/gather_subset3.yml
@@ -0,0 +1,7 @@
+---
+- hosts: localhost
+ gather_subset:
+ - 1
+ tasks:
+ - ansible.builtin.debug:
+ msg: foo
diff --git a/test/schemas/negative_test/playbooks/gather_subset3.yml.md b/test/schemas/negative_test/playbooks/gather_subset3.yml.md
new file mode 100644
index 0000000..7dc1b13
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/gather_subset3.yml.md
@@ -0,0 +1,303 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "gather_subset"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/gather_subset/0",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/properties/gather_subset/items/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/gather_subset/0",
+ "keyword": "enum",
+ "message": "must be equal to one of the allowed values",
+ "params": {
+ "allowedValues": [
+ "all",
+ "min",
+ "all_ipv4_addresses",
+ "all_ipv6_addresses",
+ "apparmor",
+ "architecture",
+ "caps",
+ "chroot,cmdline",
+ "date_time",
+ "default_ipv4",
+ "default_ipv6",
+ "devices",
+ "distribution",
+ "distribution_major_version",
+ "distribution_release",
+ "distribution_version",
+ "dns",
+ "effective_group_ids",
+ "effective_user_id",
+ "env",
+ "facter",
+ "fips",
+ "hardware",
+ "interfaces",
+ "is_chroot",
+ "iscsi",
+ "kernel",
+ "local",
+ "lsb",
+ "machine",
+ "machine_id",
+ "mounts",
+ "network",
+ "ohai",
+ "os_family",
+ "pkg_mgr",
+ "platform",
+ "processor",
+ "processor_cores",
+ "processor_count",
+ "python",
+ "python_version",
+ "real_user_id",
+ "selinux",
+ "service_mgr",
+ "ssh_host_key_dsa_public",
+ "ssh_host_key_ecdsa_public",
+ "ssh_host_key_ed25519_public",
+ "ssh_host_key_rsa_public",
+ "ssh_host_pub_keys",
+ "ssh_pub_keys",
+ "system",
+ "system_capabilities",
+ "system_capabilities_enforced",
+ "user",
+ "user_dir",
+ "user_gecos",
+ "user_gid",
+ "user_id",
+ "user_shell",
+ "user_uid",
+ "virtual",
+ "virtualization_role",
+ "virtualization_type"
+ ]
+ },
+ "schemaPath": "#/properties/gather_subset/items/anyOf/0/enum"
+ },
+ {
+ "instancePath": "/0/gather_subset/0",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/properties/gather_subset/items/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/gather_subset/0",
+ "keyword": "enum",
+ "message": "must be equal to one of the allowed values",
+ "params": {
+ "allowedValues": [
+ "!all",
+ "!min",
+ "!all_ipv4_addresses",
+ "!all_ipv6_addresses",
+ "!apparmor",
+ "!architecture",
+ "!caps",
+ "!chroot,cmdline",
+ "!date_time",
+ "!default_ipv4",
+ "!default_ipv6",
+ "!devices",
+ "!distribution",
+ "!distribution_major_version",
+ "!distribution_release",
+ "!distribution_version",
+ "!dns",
+ "!effective_group_ids",
+ "!effective_user_id",
+ "!env",
+ "!facter",
+ "!fips",
+ "!hardware",
+ "!interfaces",
+ "!is_chroot",
+ "!iscsi",
+ "!kernel",
+ "!local",
+ "!lsb",
+ "!machine",
+ "!machine_id",
+ "!mounts",
+ "!network",
+ "!ohai",
+ "!os_family",
+ "!pkg_mgr",
+ "!platform",
+ "!processor",
+ "!processor_cores",
+ "!processor_count",
+ "!python",
+ "!python_version",
+ "!real_user_id",
+ "!selinux",
+ "!service_mgr",
+ "!ssh_host_key_dsa_public",
+ "!ssh_host_key_ecdsa_public",
+ "!ssh_host_key_ed25519_public",
+ "!ssh_host_key_rsa_public",
+ "!ssh_host_pub_keys",
+ "!ssh_pub_keys",
+ "!system",
+ "!system_capabilities",
+ "!system_capabilities_enforced",
+ "!user",
+ "!user_dir",
+ "!user_gecos",
+ "!user_gid",
+ "!user_id",
+ "!user_shell",
+ "!user_uid",
+ "!virtual",
+ "!virtualization_role",
+ "!virtualization_type"
+ ]
+ },
+ "schemaPath": "#/properties/gather_subset/items/anyOf/1/enum"
+ },
+ {
+ "instancePath": "/0/gather_subset/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/properties/gather_subset/items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/gather_subset3.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'gather_subset': [1], 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'gather_subset', 'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'gather_subset', 'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'gather_subset': [1], 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].gather_subset[0]",
+ "message": "1 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].gather_subset[0]",
+ "message": "1 is not one of ['all', 'min', 'all_ipv4_addresses', 'all_ipv6_addresses', 'apparmor', 'architecture', 'caps', 'chroot,cmdline', 'date_time', 'default_ipv4', 'default_ipv6', 'devices', 'distribution', 'distribution_major_version', 'distribution_release', 'distribution_version', 'dns', 'effective_group_ids', 'effective_user_id', 'env', 'facter', 'fips', 'hardware', 'interfaces', 'is_chroot', 'iscsi', 'kernel', 'local', 'lsb', 'machine', 'machine_id', 'mounts', 'network', 'ohai', 'os_family', 'pkg_mgr', 'platform', 'processor', 'processor_cores', 'processor_count', 'python', 'python_version', 'real_user_id', 'selinux', 'service_mgr', 'ssh_host_key_dsa_public', 'ssh_host_key_ecdsa_public', 'ssh_host_key_ed25519_public', 'ssh_host_key_rsa_public', 'ssh_host_pub_keys', 'ssh_pub_keys', 'system', 'system_capabilities', 'system_capabilities_enforced', 'user', 'user_dir', 'user_gecos', 'user_gid', 'user_id', 'user_shell', 'user_uid', 'virtual', 'virtualization_role', 'virtualization_type']"
+ },
+ {
+ "path": "$[0].gather_subset[0]",
+ "message": "1 is not of type 'string'"
+ },
+ {
+ "path": "$[0].gather_subset[0]",
+ "message": "1 is not one of ['!all', '!min', '!all_ipv4_addresses', '!all_ipv6_addresses', '!apparmor', '!architecture', '!caps', '!chroot,cmdline', '!date_time', '!default_ipv4', '!default_ipv6', '!devices', '!distribution', '!distribution_major_version', '!distribution_release', '!distribution_version', '!dns', '!effective_group_ids', '!effective_user_id', '!env', '!facter', '!fips', '!hardware', '!interfaces', '!is_chroot', '!iscsi', '!kernel', '!local', '!lsb', '!machine', '!machine_id', '!mounts', '!network', '!ohai', '!os_family', '!pkg_mgr', '!platform', '!processor', '!processor_cores', '!processor_count', '!python', '!python_version', '!real_user_id', '!selinux', '!service_mgr', '!ssh_host_key_dsa_public', '!ssh_host_key_ecdsa_public', '!ssh_host_key_ed25519_public', '!ssh_host_key_rsa_public', '!ssh_host_pub_keys', '!ssh_pub_keys', '!system', '!system_capabilities', '!system_capabilities_enforced', '!user', '!user_dir', '!user_gecos', '!user_gid', '!user_id', '!user_shell', '!user_uid', '!virtual', '!virtualization_role', '!virtualization_type']"
+ },
+ {
+ "path": "$[0].gather_subset[0]",
+ "message": "1 is not of type 'string'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/gather_subset4.yml b/test/schemas/negative_test/playbooks/gather_subset4.yml
new file mode 100644
index 0000000..816e666
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/gather_subset4.yml
@@ -0,0 +1,6 @@
+---
+- hosts: localhost
+ gather_subset: 1
+ tasks:
+ - ansible.builtin.debug:
+ msg: foo
diff --git a/test/schemas/negative_test/playbooks/gather_subset4.yml.md b/test/schemas/negative_test/playbooks/gather_subset4.yml.md
new file mode 100644
index 0000000..ada01cb
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/gather_subset4.yml.md
@@ -0,0 +1,123 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "gather_subset"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/gather_subset",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/properties/gather_subset/type"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/gather_subset4.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'gather_subset': 1, 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'gather_subset', 'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'gather_subset', 'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'gather_subset': 1, 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].gather_subset",
+ "message": "1 is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/ignore_errors.yml b/test/schemas/negative_test/playbooks/ignore_errors.yml
new file mode 100644
index 0000000..9da277f
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/ignore_errors.yml
@@ -0,0 +1,6 @@
+- hosts: localhost
+ tasks:
+ - command: echo 123
+ vars:
+ should_ignore_errors: true
+ ignore_errors: should_ignore_errors # invalid due to missing {{ }}
diff --git a/test/schemas/negative_test/playbooks/ignore_errors.yml.md b/test/schemas/negative_test/playbooks/ignore_errors.yml.md
new file mode 100644
index 0000000..61c3116
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/ignore_errors.yml.md
@@ -0,0 +1,203 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/tasks/0/ignore_errors",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/ignore_errors",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/tasks/0/ignore_errors",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0/tasks/0/ignore_errors",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/ignore_errors",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/tasks/0/ignore_errors",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/ignore_errors.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'command': 'echo 123', 'vars': {'should_ignore_errors': True}, 'ignore_errors': 'should_ignore_errors'}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'command': 'echo 123', 'vars': {'should_ignore_errors': True}, 'ignore_errors': 'should_ignore_errors'}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "{'command': 'echo 123', 'vars': {'should_ignore_errors': True}, 'ignore_errors': 'should_ignore_errors'} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].ignore_errors",
+ "message": "'should_ignore_errors' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].ignore_errors",
+ "message": "'should_ignore_errors' is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].ignore_errors",
+ "message": "'should_ignore_errors' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0].ignore_errors",
+ "message": "'should_ignore_errors' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].ignore_errors",
+ "message": "'should_ignore_errors' is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].ignore_errors",
+ "message": "'should_ignore_errors' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/import_playbook.yml b/test/schemas/negative_test/playbooks/import_playbook.yml
new file mode 100644
index 0000000..b6d8ec2
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/import_playbook.yml
@@ -0,0 +1 @@
+- ansible.builtin.import_playbook: {} # only freeform/string is allowed
diff --git a/test/schemas/negative_test/playbooks/import_playbook.yml.md b/test/schemas/negative_test/playbooks/import_playbook.yml.md
new file mode 100644
index 0000000..def3dce
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/import_playbook.yml.md
@@ -0,0 +1,90 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0/ansible.builtin.import_playbook",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/patternProperties/%5E(ansible%5C.builtin%5C.)%3Fimport_playbook%24/type"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "not",
+ "message": "must NOT be valid",
+ "params": {},
+ "schemaPath": "#/allOf/0/not"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'hosts'",
+ "params": {
+ "missingProperty": "hosts"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/import_playbook.yml",
+ "path": "$[0]",
+ "message": "{'ansible.builtin.import_playbook': {}} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "{'ansible.builtin.import_playbook': {}} should not be valid under {'required': ['ansible.builtin.import_playbook']}"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0].ansible.builtin.import_playbook",
+ "message": "{} is not of type 'string'"
+ },
+ {
+ "path": "$[0]",
+ "message": "Additional properties are not allowed ('ansible.builtin.import_playbook' was unexpected)"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'ansible.builtin.import_playbook': {}} should not be valid under {'required': ['ansible.builtin.import_playbook']}"
+ },
+ {
+ "path": "$[0]",
+ "message": "'hosts' is a required property"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/import_playbook_exclusive.yml b/test/schemas/negative_test/playbooks/import_playbook_exclusive.yml
new file mode 100644
index 0000000..ef2b5f6
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/import_playbook_exclusive.yml
@@ -0,0 +1,4 @@
+---
+# invalid because you cannot have both entries in the same time:
+- ansible.builtin.import_playbook: foo.yml
+ import_playbook: other.yml
diff --git a/test/schemas/negative_test/playbooks/import_playbook_exclusive.yml.md b/test/schemas/negative_test/playbooks/import_playbook_exclusive.yml.md
new file mode 100644
index 0000000..184a434
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/import_playbook_exclusive.yml.md
@@ -0,0 +1,132 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "not",
+ "message": "must NOT be valid",
+ "params": {},
+ "schemaPath": "#/oneOf/0/not"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "not",
+ "message": "must NOT be valid",
+ "params": {},
+ "schemaPath": "#/oneOf/1/not"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "not",
+ "message": "must NOT be valid",
+ "params": {},
+ "schemaPath": "#/allOf/0/not"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "not",
+ "message": "must NOT be valid",
+ "params": {},
+ "schemaPath": "#/allOf/1/not"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'hosts'",
+ "params": {
+ "missingProperty": "hosts"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "import_playbook"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/import_playbook_exclusive.yml",
+ "path": "$[0]",
+ "message": "{'ansible.builtin.import_playbook': 'foo.yml', 'import_playbook': 'other.yml'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "{'ansible.builtin.import_playbook': 'foo.yml', 'import_playbook': 'other.yml'} should not be valid under {'required': ['ansible.builtin.import_playbook']}"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "{'ansible.builtin.import_playbook': 'foo.yml', 'import_playbook': 'other.yml'} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'ansible.builtin.import_playbook': 'foo.yml', 'import_playbook': 'other.yml'} should not be valid under {'required': ['import_playbook']}"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'ansible.builtin.import_playbook': 'foo.yml', 'import_playbook': 'other.yml'} should not be valid under {'required': ['ansible.builtin.import_playbook']}"
+ },
+ {
+ "path": "$[0]",
+ "message": "Additional properties are not allowed ('ansible.builtin.import_playbook', 'import_playbook' were unexpected)"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'ansible.builtin.import_playbook': 'foo.yml', 'import_playbook': 'other.yml'} should not be valid under {'required': ['ansible.builtin.import_playbook']}"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'ansible.builtin.import_playbook': 'foo.yml', 'import_playbook': 'other.yml'} should not be valid under {'required': ['import_playbook']}"
+ },
+ {
+ "path": "$[0]",
+ "message": "'hosts' is a required property"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/invalid-failed-when.yml b/test/schemas/negative_test/playbooks/invalid-failed-when.yml
new file mode 100644
index 0000000..075f166
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/invalid-failed-when.yml
@@ -0,0 +1,15 @@
+- hosts: localhost
+ tasks:
+ - debug:
+ msg: "failed_when should not accept numeric"
+ failed_when: 123
+
+ - debug:
+ msg: "failed_when should not accept sequence"
+ failed_when:
+ - foo
+ - bar
+
+ - debug:
+ msg: "failed_when should not accept map"
+ failed_when: {}
diff --git a/test/schemas/negative_test/playbooks/invalid-failed-when.yml.md b/test/schemas/negative_test/playbooks/invalid-failed-when.yml.md
new file mode 100644
index 0000000..3a41059
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/invalid-failed-when.yml.md
@@ -0,0 +1,253 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/tasks/0/failed_when",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/failed_when",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/failed_when",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/2/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/failed_when",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ },
+ {
+ "instancePath": "/0/tasks/2",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/tasks/2/failed_when",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/2/failed_when",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/tasks/2/failed_when",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/2/type"
+ },
+ {
+ "instancePath": "/0/tasks/2/failed_when",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf"
+ },
+ {
+ "instancePath": "/0/tasks/2",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/invalid-failed-when.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'debug': {'msg': 'failed_when should not accept numeric'}, 'failed_when': 123}, {'debug': {'msg': 'failed_when should not accept sequence'}, 'failed_when': ['foo', 'bar']}, {'debug': {'msg': 'failed_when should not accept map'}, 'failed_when': {}}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'debug': {'msg': 'failed_when should not accept numeric'}, 'failed_when': 123}, {'debug': {'msg': 'failed_when should not accept sequence'}, 'failed_when': ['foo', 'bar']}, {'debug': {'msg': 'failed_when should not accept map'}, 'failed_when': {}}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "{'debug': {'msg': 'failed_when should not accept numeric'}, 'failed_when': 123} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0].failed_when",
+ "message": "123 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].failed_when",
+ "message": "123 is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].failed_when",
+ "message": "123 is not of type 'string'"
+ },
+ {
+ "path": "$[0].tasks[0].failed_when",
+ "message": "123 is not of type 'array'"
+ },
+ {
+ "path": "$[0].tasks[2]",
+ "message": "{'debug': {'msg': 'failed_when should not accept map'}, 'failed_when': {}} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[2]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].tasks[2].failed_when",
+ "message": "{} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[2].failed_when",
+ "message": "{} is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[2].failed_when",
+ "message": "{} is not of type 'string'"
+ },
+ {
+ "path": "$[0].tasks[2].failed_when",
+ "message": "{} is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/invalid-serial.yml b/test/schemas/negative_test/playbooks/invalid-serial.yml
new file mode 100644
index 0000000..f2ffd3c
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/invalid-serial.yml
@@ -0,0 +1,2 @@
+- hosts: localhost
+ serial: 10%BAD
diff --git a/test/schemas/negative_test/playbooks/invalid-serial.yml.md b/test/schemas/negative_test/playbooks/invalid-serial.yml.md
new file mode 100644
index 0000000..5c48b21
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/invalid-serial.yml.md
@@ -0,0 +1,177 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "serial"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/serial",
+ "keyword": "type",
+ "message": "must be integer",
+ "params": {
+ "type": "integer"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/serial",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\d+\\.?\\d*%?$\"",
+ "params": {
+ "pattern": "^\\d+\\.?\\d*%?$"
+ },
+ "schemaPath": "#/oneOf/1/pattern"
+ },
+ {
+ "instancePath": "/0/serial",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/serial",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0/serial",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/properties/serial/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/serial",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/properties/serial/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/invalid-serial.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'serial': '10%BAD'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts', 'serial' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts', 'serial' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'serial': '10%BAD'} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].serial",
+ "message": "'10%BAD' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].serial",
+ "message": "'10%BAD' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].serial",
+ "message": "'10%BAD' is not of type 'integer'"
+ },
+ {
+ "path": "$[0].serial",
+ "message": "'10%BAD' does not match '^\\\\d+\\\\.?\\\\d*%?$'"
+ },
+ {
+ "path": "$[0].serial",
+ "message": "'10%BAD' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ },
+ {
+ "path": "$[0].serial",
+ "message": "'10%BAD' is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/invalid.yml b/test/schemas/negative_test/playbooks/invalid.yml
new file mode 100644
index 0000000..e34d3c9
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/invalid.yml
@@ -0,0 +1,3 @@
+- name: foo
+ hosts: localhost # <-- not allowed with import_playbook
+ import_playbook: included.yml
diff --git a/test/schemas/negative_test/playbooks/invalid.yml.md b/test/schemas/negative_test/playbooks/invalid.yml.md
new file mode 100644
index 0000000..c3435dd
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/invalid.yml.md
@@ -0,0 +1,77 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "not",
+ "message": "must NOT be valid",
+ "params": {},
+ "schemaPath": "#/allOf/1/not"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "import_playbook"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/invalid.yml",
+ "path": "$[0]",
+ "message": "{'name': 'foo', 'hosts': 'localhost', 'import_playbook': 'included.yml'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "{'name': 'foo', 'hosts': 'localhost', 'import_playbook': 'included.yml'} should not be valid under {'required': ['import_playbook']}"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts' does not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "Additional properties are not allowed ('import_playbook' was unexpected)"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'name': 'foo', 'hosts': 'localhost', 'import_playbook': 'included.yml'} should not be valid under {'required': ['import_playbook']}"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/invalid_become.yml b/test/schemas/negative_test/playbooks/invalid_become.yml
new file mode 100644
index 0000000..0cc6721
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/invalid_become.yml
@@ -0,0 +1,3 @@
+---
+- hosts: localhost
+ become: yes # <- invalid based on json schema
diff --git a/test/schemas/negative_test/playbooks/invalid_become.yml.md b/test/schemas/negative_test/playbooks/invalid_become.yml.md
new file mode 100644
index 0000000..37d730d
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/invalid_become.yml.md
@@ -0,0 +1,140 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "become"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/become",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/become",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/become",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/invalid_become.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'become': 'yes'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'become', 'hosts' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'become', 'hosts' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'become': 'yes'} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].become",
+ "message": "'yes' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].become",
+ "message": "'yes' is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].become",
+ "message": "'yes' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/local_action.yml b/test/schemas/negative_test/playbooks/local_action.yml
new file mode 100644
index 0000000..9e01b1d
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/local_action.yml
@@ -0,0 +1,3 @@
+- hosts: localhost
+ tasks:
+ - local_action: [] # <-- only string or dict is allowed
diff --git a/test/schemas/negative_test/playbooks/local_action.yml.md b/test/schemas/negative_test/playbooks/local_action.yml.md
new file mode 100644
index 0000000..17f6244
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/local_action.yml.md
@@ -0,0 +1,141 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/tasks/0/local_action",
+ "keyword": "type",
+ "message": "must be string,object",
+ "params": {
+ "type": [
+ "string",
+ "object"
+ ]
+ },
+ "schemaPath": "#/properties/local_action/type"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/local_action.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'local_action': []}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'local_action': []}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "{'local_action': []} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0].local_action",
+ "message": "[] is not of type 'string', 'object'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/loop.yml b/test/schemas/negative_test/playbooks/loop.yml
new file mode 100644
index 0000000..fd02ec5
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/loop.yml
@@ -0,0 +1,7 @@
+---
+- hosts: localhost
+ tasks:
+ - name: that should pass
+ ansible.builtin.debug:
+ var: item
+ loop: 123 # <-- number is not valid
diff --git a/test/schemas/negative_test/playbooks/loop.yml.md b/test/schemas/negative_test/playbooks/loop.yml.md
new file mode 100644
index 0000000..88df838
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/loop.yml.md
@@ -0,0 +1,141 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/tasks/0/loop",
+ "keyword": "type",
+ "message": "must be string,array",
+ "params": {
+ "type": [
+ "string",
+ "array"
+ ]
+ },
+ "schemaPath": "#/properties/loop/type"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/loop.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'name': 'that should pass', 'ansible.builtin.debug': {'var': 'item'}, 'loop': 123}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'name': 'that should pass', 'ansible.builtin.debug': {'var': 'item'}, 'loop': 123}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "{'name': 'that should pass', 'ansible.builtin.debug': {'var': 'item'}, 'loop': 123} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0].loop",
+ "message": "123 is not of type 'string', 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/loop2.yml b/test/schemas/negative_test/playbooks/loop2.yml
new file mode 100644
index 0000000..7c9f2db
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/loop2.yml
@@ -0,0 +1,7 @@
+---
+- hosts: localhost
+ tasks:
+ - name: that should pass
+ ansible.builtin.debug:
+ var: item
+ loop: {} # <-- map is not valid
diff --git a/test/schemas/negative_test/playbooks/loop2.yml.md b/test/schemas/negative_test/playbooks/loop2.yml.md
new file mode 100644
index 0000000..df60a41
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/loop2.yml.md
@@ -0,0 +1,141 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/tasks/0/loop",
+ "keyword": "type",
+ "message": "must be string,array",
+ "params": {
+ "type": [
+ "string",
+ "array"
+ ]
+ },
+ "schemaPath": "#/properties/loop/type"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/loop2.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'name': 'that should pass', 'ansible.builtin.debug': {'var': 'item'}, 'loop': {}}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'name': 'that should pass', 'ansible.builtin.debug': {'var': 'item'}, 'loop': {}}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "{'name': 'that should pass', 'ansible.builtin.debug': {'var': 'item'}, 'loop': {}} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0].loop",
+ "message": "{} is not of type 'string', 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/no_log_partial_template.yml b/test/schemas/negative_test/playbooks/no_log_partial_template.yml
new file mode 100644
index 0000000..224aba8
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/no_log_partial_template.yml
@@ -0,0 +1,7 @@
+- hosts: localhost
+ vars:
+ some_var: true
+ tasks:
+ - ansible.builtin.debug:
+ msg: foo
+ no_log: "foo-{{ some_var }}" # <-- partial templating not allowed here
diff --git a/test/schemas/negative_test/playbooks/no_log_partial_template.yml.md b/test/schemas/negative_test/playbooks/no_log_partial_template.yml.md
new file mode 100644
index 0000000..ee73686
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/no_log_partial_template.yml.md
@@ -0,0 +1,203 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/tasks/0/no_log",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/no_log",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/tasks/0/no_log",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0/tasks/0/no_log",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/no_log",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/tasks/0/no_log",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/no_log_partial_template.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'vars': {'some_var': True}, 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}, 'no_log': 'foo-{{ some_var }}'}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'vars': {'some_var': True}, 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}, 'no_log': 'foo-{{ some_var }}'}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "{'ansible.builtin.debug': {'msg': 'foo'}, 'no_log': 'foo-{{ some_var }}'} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].no_log",
+ "message": "'foo-{{ some_var }}' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].no_log",
+ "message": "'foo-{{ some_var }}' is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].no_log",
+ "message": "'foo-{{ some_var }}' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0].no_log",
+ "message": "'foo-{{ some_var }}' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].no_log",
+ "message": "'foo-{{ some_var }}' is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].no_log",
+ "message": "'foo-{{ some_var }}' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/no_log_string.yml b/test/schemas/negative_test/playbooks/no_log_string.yml
new file mode 100644
index 0000000..caf88e2
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/no_log_string.yml
@@ -0,0 +1,7 @@
+- hosts: localhost
+ vars:
+ some_var: true
+ tasks:
+ - ansible.builtin.debug:
+ msg: foo
+ no_log: some_var # <-- bad, jinja use must be explicit
diff --git a/test/schemas/negative_test/playbooks/no_log_string.yml.md b/test/schemas/negative_test/playbooks/no_log_string.yml.md
new file mode 100644
index 0000000..c8213c0
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/no_log_string.yml.md
@@ -0,0 +1,203 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/tasks/0/no_log",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/no_log",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/tasks/0/no_log",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0/tasks/0/no_log",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/no_log",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/tasks/0/no_log",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/no_log_string.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'vars': {'some_var': True}, 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}, 'no_log': 'some_var'}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'vars': {'some_var': True}, 'tasks': [{'ansible.builtin.debug': {'msg': 'foo'}, 'no_log': 'some_var'}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "{'ansible.builtin.debug': {'msg': 'foo'}, 'no_log': 'some_var'} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].no_log",
+ "message": "'some_var' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].no_log",
+ "message": "'some_var' is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].no_log",
+ "message": "'some_var' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0].no_log",
+ "message": "'some_var' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].no_log",
+ "message": "'some_var' is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].no_log",
+ "message": "'some_var' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/roles.yml b/test/schemas/negative_test/playbooks/roles.yml
new file mode 100644
index 0000000..e24445a
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/roles.yml
@@ -0,0 +1,2 @@
+- hosts: localhost
+ roles: xxx # must be array
diff --git a/test/schemas/negative_test/playbooks/roles.yml.md b/test/schemas/negative_test/playbooks/roles.yml.md
new file mode 100644
index 0000000..9b4e25a
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/roles.yml.md
@@ -0,0 +1,114 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "roles"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/roles",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/properties/roles/type"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/roles.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'roles': 'xxx'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts', 'roles' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts', 'roles' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'roles': 'xxx'} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].roles",
+ "message": "'xxx' is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/run_once_list.yml b/test/schemas/negative_test/playbooks/run_once_list.yml
new file mode 100644
index 0000000..0dd2cd5
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/run_once_list.yml
@@ -0,0 +1,8 @@
+- hosts: localhost
+ tasks:
+ - name: foo2
+ ansible.builtin.debug:
+ msg: foo!
+ run_once: # invalid due to schema, also ansible does not allow lists
+ - "{{ true }}"
+ - xxx
diff --git a/test/schemas/negative_test/playbooks/run_once_list.yml.md b/test/schemas/negative_test/playbooks/run_once_list.yml.md
new file mode 100644
index 0000000..84b7dc1
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/run_once_list.yml.md
@@ -0,0 +1,221 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/tasks/0/run_once",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/run_once",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/run_once",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/full-jinja/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/run_once",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0/tasks/0/run_once",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/run_once",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/run_once",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/full-jinja/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/run_once",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/run_once_list.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'name': 'foo2', 'ansible.builtin.debug': {'msg': 'foo!'}, 'run_once': ['{{ true }}', 'xxx']}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tasks': [{'name': 'foo2', 'ansible.builtin.debug': {'msg': 'foo!'}, 'run_once': ['{{ true }}', 'xxx']}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "{'name': 'foo2', 'ansible.builtin.debug': {'msg': 'foo!'}, 'run_once': ['{{ true }}', 'xxx']} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].run_once",
+ "message": "['{{ true }}', 'xxx'] is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].run_once",
+ "message": "['{{ true }}', 'xxx'] is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].run_once",
+ "message": "['{{ true }}', 'xxx'] is not of type 'string'"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0].run_once",
+ "message": "['{{ true }}', 'xxx'] is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].run_once",
+ "message": "['{{ true }}', 'xxx'] is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].run_once",
+ "message": "['{{ true }}', 'xxx'] is not of type 'string'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tags-mapping.yml b/test/schemas/negative_test/playbooks/tags-mapping.yml
new file mode 100644
index 0000000..8c6da3d
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tags-mapping.yml
@@ -0,0 +1,2 @@
+- hosts: localhost
+ tags: {} # <-- not allowed
diff --git a/test/schemas/negative_test/playbooks/tags-mapping.yml.md b/test/schemas/negative_test/playbooks/tags-mapping.yml.md
new file mode 100644
index 0000000..aada0c6
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tags-mapping.yml.md
@@ -0,0 +1,166 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/$defs/tags/anyOf"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/$defs/tags/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tags-mapping.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tags': {}} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts' does not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts' does not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tags': {}} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "{} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "{} is not of type 'string'"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "{} is not of type 'array'"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "{} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "{} is not of type 'string'"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "{} is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tags-number.yml b/test/schemas/negative_test/playbooks/tags-number.yml
new file mode 100644
index 0000000..1872ced
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tags-number.yml
@@ -0,0 +1,2 @@
+- hosts: localhost
+ tags: 123 # <-- not allowed
diff --git a/test/schemas/negative_test/playbooks/tags-number.yml.md b/test/schemas/negative_test/playbooks/tags-number.yml.md
new file mode 100644
index 0000000..3d32737
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tags-number.yml.md
@@ -0,0 +1,166 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/$defs/tags/anyOf"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/$defs/tags/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tags-number.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tags': 123} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts' does not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts' does not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'tags': 123} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "123 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "123 is not of type 'string'"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "123 is not of type 'array'"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "123 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "123 is not of type 'string'"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "123 is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks.yml b/test/schemas/negative_test/playbooks/tasks.yml
new file mode 100644
index 0000000..2464a73
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks.yml
@@ -0,0 +1,5 @@
+- hosts: localhost
+ pre_tasks: foo # <-- must be array
+ post_tasks: {} # <-- must be array
+ tasks: 1 # <-- must be array
+ handlers: 1.0 # <-- must be array
diff --git a/test/schemas/negative_test/playbooks/tasks.yml.md b/test/schemas/negative_test/playbooks/tasks.yml.md
new file mode 100644
index 0000000..309912b
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks.yml.md
@@ -0,0 +1,192 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "pre_tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "post_tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "handlers"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/handlers",
+ "keyword": "type",
+ "message": "must be array,null",
+ "params": {
+ "type": [
+ "array",
+ "null"
+ ]
+ },
+ "schemaPath": "#/type"
+ },
+ {
+ "instancePath": "/0/post_tasks",
+ "keyword": "type",
+ "message": "must be array,null",
+ "params": {
+ "type": [
+ "array",
+ "null"
+ ]
+ },
+ "schemaPath": "#/type"
+ },
+ {
+ "instancePath": "/0/pre_tasks",
+ "keyword": "type",
+ "message": "must be array,null",
+ "params": {
+ "type": [
+ "array",
+ "null"
+ ]
+ },
+ "schemaPath": "#/type"
+ },
+ {
+ "instancePath": "/0/tasks",
+ "keyword": "type",
+ "message": "must be array,null",
+ "params": {
+ "type": [
+ "array",
+ "null"
+ ]
+ },
+ "schemaPath": "#/type"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'pre_tasks': 'foo', 'post_tasks': {}, 'tasks': 1, 'handlers': 1.0} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'handlers', 'hosts', 'post_tasks', 'pre_tasks', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'handlers', 'hosts', 'post_tasks', 'pre_tasks', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'pre_tasks': 'foo', 'post_tasks': {}, 'tasks': 1, 'handlers': 1.0} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].handlers",
+ "message": "1.0 is not of type 'array', 'null'"
+ },
+ {
+ "path": "$[0].post_tasks",
+ "message": "{} is not of type 'array', 'null'"
+ },
+ {
+ "path": "$[0].pre_tasks",
+ "message": "'foo' is not of type 'array', 'null'"
+ },
+ {
+ "path": "$[0].tasks",
+ "message": "1 is not of type 'array', 'null'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/args_integer.yml b/test/schemas/negative_test/playbooks/tasks/args_integer.yml
new file mode 100644
index 0000000..b831039
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/args_integer.yml
@@ -0,0 +1,2 @@
+- action: foo
+ args: 123 # invalid
diff --git a/test/schemas/negative_test/playbooks/tasks/args_integer.yml.md b/test/schemas/negative_test/playbooks/tasks/args_integer.yml.md
new file mode 100644
index 0000000..8820251
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/args_integer.yml.md
@@ -0,0 +1,99 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/args",
+ "keyword": "type",
+ "message": "must be object",
+ "params": {
+ "type": "object"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/args",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/args",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/full-jinja/type"
+ },
+ {
+ "instancePath": "/0/args",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/args_integer.yml",
+ "path": "$[0]",
+ "message": "{'action': 'foo', 'args': 123} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].args",
+ "message": "123 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].args",
+ "message": "123 is not of type 'object'"
+ },
+ {
+ "path": "$[0].args",
+ "message": "123 is not of type 'string'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/args_string.yml b/test/schemas/negative_test/playbooks/tasks/args_string.yml
new file mode 100644
index 0000000..121da6d
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/args_string.yml
@@ -0,0 +1,2 @@
+- action: foo
+ args: "{{ }}123" # invalid as only full jinja2 expressions are allowed
diff --git a/test/schemas/negative_test/playbooks/tasks/args_string.yml.md b/test/schemas/negative_test/playbooks/tasks/args_string.yml.md
new file mode 100644
index 0000000..6359a14
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/args_string.yml.md
@@ -0,0 +1,90 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/args",
+ "keyword": "type",
+ "message": "must be object",
+ "params": {
+ "type": "object"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/args",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/args",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/args_string.yml",
+ "path": "$[0]",
+ "message": "{'action': 'foo', 'args': '{{ }}123'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].args",
+ "message": "'{{ }}123' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].args",
+ "message": "'{{ }}123' is not of type 'object'"
+ },
+ {
+ "path": "$[0].args",
+ "message": "'{{ }}123' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/become_method_invalid.yml b/test/schemas/negative_test/playbooks/tasks/become_method_invalid.yml
new file mode 100644
index 0000000..9a6bc99
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/become_method_invalid.yml
@@ -0,0 +1,4 @@
+- command: echo 123
+ vars:
+ sudo_var: doo
+ become_method: true
diff --git a/test/schemas/negative_test/playbooks/tasks/become_method_invalid.yml.md b/test/schemas/negative_test/playbooks/tasks/become_method_invalid.yml.md
new file mode 100644
index 0000000..fc1e692
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/become_method_invalid.yml.md
@@ -0,0 +1,203 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "enum",
+ "message": "must be equal to one of the allowed values",
+ "params": {
+ "allowedValues": [
+ "ansible.builtin.sudo",
+ "ansible.builtin.su",
+ "community.general.pbrun",
+ "community.general.pfexec",
+ "ansible.builtin.runas",
+ "community.general.dzdo",
+ "community.general.ksu",
+ "community.general.doas",
+ "community.general.machinectl",
+ "community.general.pmrun",
+ "community.general.sesu",
+ "community.general.sudosu"
+ ]
+ },
+ "schemaPath": "#/anyOf/0/enum"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/full-jinja/type"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/anyOf/2/type"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/anyOf"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "enum",
+ "message": "must be equal to one of the allowed values",
+ "params": {
+ "allowedValues": [
+ "ansible.builtin.sudo",
+ "ansible.builtin.su",
+ "community.general.pbrun",
+ "community.general.pfexec",
+ "ansible.builtin.runas",
+ "community.general.dzdo",
+ "community.general.ksu",
+ "community.general.doas",
+ "community.general.machinectl",
+ "community.general.pmrun",
+ "community.general.sesu",
+ "community.general.sudosu"
+ ]
+ },
+ "schemaPath": "#/anyOf/0/enum"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/full-jinja/type"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/anyOf/2/type"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/become_method_invalid.yml",
+ "path": "$[0]",
+ "message": "{'command': 'echo 123', 'vars': {'sudo_var': 'doo'}, 'become_method': True} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0].become_method",
+ "message": "True is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "True is not one of ['ansible.builtin.sudo', 'ansible.builtin.su', 'community.general.pbrun', 'community.general.pfexec', 'ansible.builtin.runas', 'community.general.dzdo', 'community.general.ksu', 'community.general.doas', 'community.general.machinectl', 'community.general.pmrun', 'community.general.sesu', 'community.general.sudosu']"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "True is not of type 'string'"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "True is not of type 'string'"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "True is not of type 'string'"
+ },
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "True is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "True is not one of ['ansible.builtin.sudo', 'ansible.builtin.su', 'community.general.pbrun', 'community.general.pfexec', 'ansible.builtin.runas', 'community.general.dzdo', 'community.general.ksu', 'community.general.doas', 'community.general.machinectl', 'community.general.pmrun', 'community.general.sesu', 'community.general.sudosu']"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "True is not of type 'string'"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "True is not of type 'string'"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "True is not of type 'string'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/become_method_untemplated.yml.md b/test/schemas/negative_test/playbooks/tasks/become_method_untemplated.yml.md
new file mode 100644
index 0000000..47a6554
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/become_method_untemplated.yml.md
@@ -0,0 +1,181 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "enum",
+ "message": "must be equal to one of the allowed values",
+ "params": {
+ "allowedValues": [
+ "sudo",
+ "su",
+ "pbrun",
+ "pfexec",
+ "runas",
+ "dzdo",
+ "ksu",
+ "doas",
+ "machinectl",
+ "pmrun",
+ "sesu",
+ "sudosu"
+ ]
+ },
+ "schemaPath": "#/oneOf/0/enum"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "pattern",
+ "message": "must match pattern \"^[A-Z][a-z][0-9]._$\"",
+ "params": {
+ "pattern": "^[A-Z][a-z][0-9]._$"
+ },
+ "schemaPath": "#/oneOf/2/pattern"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "enum",
+ "message": "must be equal to one of the allowed values",
+ "params": {
+ "allowedValues": [
+ "sudo",
+ "su",
+ "pbrun",
+ "pfexec",
+ "runas",
+ "dzdo",
+ "ksu",
+ "doas",
+ "machinectl",
+ "pmrun",
+ "sesu",
+ "sudosu"
+ ]
+ },
+ "schemaPath": "#/oneOf/0/enum"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "pattern",
+ "message": "must match pattern \"^[A-Z][a-z][0-9]._$\"",
+ "params": {
+ "pattern": "^[A-Z][a-z][0-9]._$"
+ },
+ "schemaPath": "#/oneOf/2/pattern"
+ },
+ {
+ "instancePath": "/0/become_method",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/become_method_untemplated.yml",
+ "path": "$[0]",
+ "message": "{'command': 'echo 123', 'vars': {'sudo_var': 'doo'}, 'become_method': 'sudo_var'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0].become_method",
+ "message": "'sudo_var' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "'sudo_var' is not one of ['sudo', 'su', 'pbrun', 'pfexec', 'runas', 'dzdo', 'ksu', 'doas', 'machinectl', 'pmrun', 'sesu', 'sudosu']"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "'sudo_var' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "'sudo_var' does not match '^[A-Z][a-z][0-9]._$'"
+ },
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "'sudo_var' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "'sudo_var' is not one of ['sudo', 'su', 'pbrun', 'pfexec', 'runas', 'dzdo', 'ksu', 'doas', 'machinectl', 'pmrun', 'sesu', 'sudosu']"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "'sudo_var' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ },
+ {
+ "path": "$[0].become_method",
+ "message": "'sudo_var' does not match '^[A-Z][a-z][0-9]._$'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/ignore_errors.yml b/test/schemas/negative_test/playbooks/tasks/ignore_errors.yml
new file mode 100644
index 0000000..4f8cbb3
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/ignore_errors.yml
@@ -0,0 +1,4 @@
+- command: echo 123
+ vars:
+ should_ignore_errors: true
+ ignore_errors: should_ignore_errors # invalid due to missing {{ }}
diff --git a/test/schemas/negative_test/playbooks/tasks/ignore_errors.yml.md b/test/schemas/negative_test/playbooks/tasks/ignore_errors.yml.md
new file mode 100644
index 0000000..559a200
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/ignore_errors.yml.md
@@ -0,0 +1,129 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/ignore_errors",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/ignore_errors",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/ignore_errors",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0/ignore_errors",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/ignore_errors",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/ignore_errors",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/ignore_errors.yml",
+ "path": "$[0]",
+ "message": "{'command': 'echo 123', 'vars': {'should_ignore_errors': True}, 'ignore_errors': 'should_ignore_errors'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0].ignore_errors",
+ "message": "'should_ignore_errors' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].ignore_errors",
+ "message": "'should_ignore_errors' is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].ignore_errors",
+ "message": "'should_ignore_errors' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ },
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].ignore_errors",
+ "message": "'should_ignore_errors' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].ignore_errors",
+ "message": "'should_ignore_errors' is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].ignore_errors",
+ "message": "'should_ignore_errors' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/invalid_block.yml b/test/schemas/negative_test/playbooks/tasks/invalid_block.yml
new file mode 100644
index 0000000..6fef6d1
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/invalid_block.yml
@@ -0,0 +1,2 @@
+---
+- block: {} # <-- invalid, should be array
diff --git a/test/schemas/negative_test/playbooks/tasks/invalid_block.yml.md b/test/schemas/negative_test/playbooks/tasks/invalid_block.yml.md
new file mode 100644
index 0000000..bf4b30e
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/invalid_block.yml.md
@@ -0,0 +1,62 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0/block",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/properties/block/type"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "not",
+ "message": "must NOT be valid",
+ "params": {},
+ "schemaPath": "#/allOf/3/not"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/invalid_block.yml",
+ "path": "$[0]",
+ "message": "{'block': {}} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "{'block': {}} should not be valid under {'required': ['block']}"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0].block",
+ "message": "{} is not of type 'array'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'block': {}} should not be valid under {'required': ['block']}"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/local_action.yml b/test/schemas/negative_test/playbooks/tasks/local_action.yml
new file mode 100644
index 0000000..d601ff5
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/local_action.yml
@@ -0,0 +1 @@
+- local_action: [] # <-- only string or dict is allowed
diff --git a/test/schemas/negative_test/playbooks/tasks/local_action.yml.md b/test/schemas/negative_test/playbooks/tasks/local_action.yml.md
new file mode 100644
index 0000000..cf67e7b
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/local_action.yml.md
@@ -0,0 +1,67 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/local_action",
+ "keyword": "type",
+ "message": "must be string,object",
+ "params": {
+ "type": [
+ "string",
+ "object"
+ ]
+ },
+ "schemaPath": "#/properties/local_action/type"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/local_action.yml",
+ "path": "$[0]",
+ "message": "{'local_action': []} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].local_action",
+ "message": "[] is not of type 'string', 'object'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/loop.yml b/test/schemas/negative_test/playbooks/tasks/loop.yml
new file mode 100644
index 0000000..651d262
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/loop.yml
@@ -0,0 +1,3 @@
+- ansible.builtin.debug:
+ var: item
+ loop: {} # <-- map is not valid
diff --git a/test/schemas/negative_test/playbooks/tasks/loop.yml.md b/test/schemas/negative_test/playbooks/tasks/loop.yml.md
new file mode 100644
index 0000000..de8277f
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/loop.yml.md
@@ -0,0 +1,67 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/loop",
+ "keyword": "type",
+ "message": "must be string,array",
+ "params": {
+ "type": [
+ "string",
+ "array"
+ ]
+ },
+ "schemaPath": "#/properties/loop/type"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/loop.yml",
+ "path": "$[0]",
+ "message": "{'ansible.builtin.debug': {'var': 'item'}, 'loop': {}} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].loop",
+ "message": "{} is not of type 'string', 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/loop2.yml b/test/schemas/negative_test/playbooks/tasks/loop2.yml
new file mode 100644
index 0000000..ec2642f
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/loop2.yml
@@ -0,0 +1,3 @@
+- ansible.builtin.debug:
+ var: item
+ loop: 123 # <-- number is not valid
diff --git a/test/schemas/negative_test/playbooks/tasks/loop2.yml.md b/test/schemas/negative_test/playbooks/tasks/loop2.yml.md
new file mode 100644
index 0000000..c36d7c9
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/loop2.yml.md
@@ -0,0 +1,67 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/loop",
+ "keyword": "type",
+ "message": "must be string,array",
+ "params": {
+ "type": [
+ "string",
+ "array"
+ ]
+ },
+ "schemaPath": "#/properties/loop/type"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/loop2.yml",
+ "path": "$[0]",
+ "message": "{'ansible.builtin.debug': {'var': 'item'}, 'loop': 123} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].loop",
+ "message": "123 is not of type 'string', 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/no_log_number.yml b/test/schemas/negative_test/playbooks/tasks/no_log_number.yml
new file mode 100644
index 0000000..4fa8da2
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/no_log_number.yml
@@ -0,0 +1,3 @@
+- ansible.builtin.debug:
+ msg: foo
+ no_log: 123 # <-- bad
diff --git a/test/schemas/negative_test/playbooks/tasks/no_log_number.yml.md b/test/schemas/negative_test/playbooks/tasks/no_log_number.yml.md
new file mode 100644
index 0000000..4b9516c
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/no_log_number.yml.md
@@ -0,0 +1,147 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/full-jinja/type"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/full-jinja/type"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/no_log_number.yml",
+ "path": "$[0]",
+ "message": "{'ansible.builtin.debug': {'msg': 'foo'}, 'no_log': 123} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0].no_log",
+ "message": "123 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].no_log",
+ "message": "123 is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].no_log",
+ "message": "123 is not of type 'string'"
+ },
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].no_log",
+ "message": "123 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].no_log",
+ "message": "123 is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].no_log",
+ "message": "123 is not of type 'string'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/no_log_string.yml b/test/schemas/negative_test/playbooks/tasks/no_log_string.yml
new file mode 100644
index 0000000..0e0b71a
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/no_log_string.yml
@@ -0,0 +1,5 @@
+- ansible.builtin.debug:
+ msg: foo
+ vars:
+ some_var: true
+ no_log: some_var # <-- bad, jinja use must be explicit
diff --git a/test/schemas/negative_test/playbooks/tasks/no_log_string.yml.md b/test/schemas/negative_test/playbooks/tasks/no_log_string.yml.md
new file mode 100644
index 0000000..6742175
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/no_log_string.yml.md
@@ -0,0 +1,129 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/no_log",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/no_log_string.yml",
+ "path": "$[0]",
+ "message": "{'ansible.builtin.debug': {'msg': 'foo'}, 'vars': {'some_var': True}, 'no_log': 'some_var'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0].no_log",
+ "message": "'some_var' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].no_log",
+ "message": "'some_var' is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].no_log",
+ "message": "'some_var' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ },
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].no_log",
+ "message": "'some_var' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].no_log",
+ "message": "'some_var' is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].no_log",
+ "message": "'some_var' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/tags-mapping.yml b/test/schemas/negative_test/playbooks/tasks/tags-mapping.yml
new file mode 100644
index 0000000..39fe8c7
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/tags-mapping.yml
@@ -0,0 +1,3 @@
+- ansible.builtin.debug:
+ msg: foo
+ tags: {} # <-- not allowed
diff --git a/test/schemas/negative_test/playbooks/tasks/tags-mapping.yml.md b/test/schemas/negative_test/playbooks/tasks/tags-mapping.yml.md
new file mode 100644
index 0000000..d860605
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/tags-mapping.yml.md
@@ -0,0 +1,125 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/$defs/tags/anyOf"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/$defs/tags/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/tags-mapping.yml",
+ "path": "$[0]",
+ "message": "{'ansible.builtin.debug': {'msg': 'foo'}, 'tags': {}} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0].tags",
+ "message": "{} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "{} is not of type 'string'"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "{} is not of type 'array'"
+ },
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "{} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "{} is not of type 'string'"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "{} is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/tags-string.yml b/test/schemas/negative_test/playbooks/tasks/tags-string.yml
new file mode 100644
index 0000000..6512fb5
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/tags-string.yml
@@ -0,0 +1,3 @@
+- ansible.builtin.debug:
+ msg: foo
+ tags: 123 # <-- not allowed
diff --git a/test/schemas/negative_test/playbooks/tasks/tags-string.yml.md b/test/schemas/negative_test/playbooks/tasks/tags-string.yml.md
new file mode 100644
index 0000000..0bb7ed0
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/tags-string.yml.md
@@ -0,0 +1,125 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/$defs/tags/anyOf"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/tags/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/tags",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/$defs/tags/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/tags-string.yml",
+ "path": "$[0]",
+ "message": "{'ansible.builtin.debug': {'msg': 'foo'}, 'tags': 123} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0].tags",
+ "message": "123 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "123 is not of type 'string'"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "123 is not of type 'array'"
+ },
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "123 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "123 is not of type 'string'"
+ },
+ {
+ "path": "$[0].tags",
+ "message": "123 is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/when_integer.yml b/test/schemas/negative_test/playbooks/tasks/when_integer.yml
new file mode 100644
index 0000000..7758503
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/when_integer.yml
@@ -0,0 +1,2 @@
+- action: foo
+ when: 123 # invalid, number is not accepted
diff --git a/test/schemas/negative_test/playbooks/tasks/when_integer.yml.md b/test/schemas/negative_test/playbooks/tasks/when_integer.yml.md
new file mode 100644
index 0000000..bc59cc4
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/when_integer.yml.md
@@ -0,0 +1,155 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/2/type"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/2/type"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/when_integer.yml",
+ "path": "$[0]",
+ "message": "{'action': 'foo', 'when': 123} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0].when",
+ "message": "123 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].when",
+ "message": "123 is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].when",
+ "message": "123 is not of type 'string'"
+ },
+ {
+ "path": "$[0].when",
+ "message": "123 is not of type 'array'"
+ },
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].when",
+ "message": "123 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].when",
+ "message": "123 is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].when",
+ "message": "123 is not of type 'string'"
+ },
+ {
+ "path": "$[0].when",
+ "message": "123 is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/when_object.yml b/test/schemas/negative_test/playbooks/tasks/when_object.yml
new file mode 100644
index 0000000..430605d
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/when_object.yml
@@ -0,0 +1,2 @@
+- action: foo
+ when: {} # invalid, object is not accepted
diff --git a/test/schemas/negative_test/playbooks/tasks/when_object.yml.md b/test/schemas/negative_test/playbooks/tasks/when_object.yml.md
new file mode 100644
index 0000000..6c28d0c
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/when_object.yml.md
@@ -0,0 +1,155 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/2/type"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/2/type"
+ },
+ {
+ "instancePath": "/0/when",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/when_object.yml",
+ "path": "$[0]",
+ "message": "{'action': 'foo', 'when': {}} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0].when",
+ "message": "{} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].when",
+ "message": "{} is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].when",
+ "message": "{} is not of type 'string'"
+ },
+ {
+ "path": "$[0].when",
+ "message": "{} is not of type 'array'"
+ },
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].when",
+ "message": "{} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].when",
+ "message": "{} is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].when",
+ "message": "{} is not of type 'string'"
+ },
+ {
+ "path": "$[0].when",
+ "message": "{} is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/with_items_boolean.yml b/test/schemas/negative_test/playbooks/tasks/with_items_boolean.yml
new file mode 100644
index 0000000..eff6ea0
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/with_items_boolean.yml
@@ -0,0 +1,2 @@
+- command: echo 123
+ with_items: true # invalid, must be a list or templated string
diff --git a/test/schemas/negative_test/playbooks/tasks/with_items_boolean.yml.md b/test/schemas/negative_test/playbooks/tasks/with_items_boolean.yml.md
new file mode 100644
index 0000000..ffc8ef8
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/with_items_boolean.yml.md
@@ -0,0 +1,88 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/with_items",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/full-jinja/type"
+ },
+ {
+ "instancePath": "/0/with_items",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/properties/with_items/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/with_items",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/properties/with_items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/with_items_boolean.yml",
+ "path": "$[0]",
+ "message": "{'command': 'echo 123', 'with_items': True} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].with_items",
+ "message": "True is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].with_items",
+ "message": "True is not of type 'string'"
+ },
+ {
+ "path": "$[0].with_items",
+ "message": "True is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/tasks/with_items_untemplated_string.yml b/test/schemas/negative_test/playbooks/tasks/with_items_untemplated_string.yml
new file mode 100644
index 0000000..257ffe2
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/with_items_untemplated_string.yml
@@ -0,0 +1,2 @@
+- command: echo 123
+ with_items: foobar # invalid, probably user wanted "{{ foobar }}"?
diff --git a/test/schemas/negative_test/playbooks/tasks/with_items_untemplated_string.yml.md b/test/schemas/negative_test/playbooks/tasks/with_items_untemplated_string.yml.md
new file mode 100644
index 0000000..158b0ee
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/tasks/with_items_untemplated_string.yml.md
@@ -0,0 +1,88 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/with_items",
+ "keyword": "pattern",
+ "message": "must match pattern \"^\\{[\\{%](.|[\r\n])*[\\}%]\\}$\"",
+ "params": {
+ "pattern": "^\\{[\\{%](.|[\r\n])*[\\}%]\\}$"
+ },
+ "schemaPath": "#/$defs/full-jinja/pattern"
+ },
+ {
+ "instancePath": "/0/with_items",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/properties/with_items/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/with_items",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/properties/with_items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/tasks/with_items_untemplated_string.yml",
+ "path": "$[0]",
+ "message": "{'command': 'echo 123', 'with_items': 'foobar'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].with_items",
+ "message": "'foobar' is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].with_items",
+ "message": "'foobar' does not match '^\\\\{[\\\\{%](.|[\\r\\n])*[\\\\}%]\\\\}$'"
+ },
+ {
+ "path": "$[0].with_items",
+ "message": "'foobar' is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/var_files_list_number.yml b/test/schemas/negative_test/playbooks/var_files_list_number.yml
new file mode 100644
index 0000000..9f3d8dd
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/var_files_list_number.yml
@@ -0,0 +1,5 @@
+---
+- name: var_files should not accept array[number]
+ hosts: localhost
+ vars_files:
+ - 0
diff --git a/test/schemas/negative_test/playbooks/var_files_list_number.yml.md b/test/schemas/negative_test/playbooks/var_files_list_number.yml.md
new file mode 100644
index 0000000..e915593
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/var_files_list_number.yml.md
@@ -0,0 +1,144 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/vars_files",
+ "keyword": "type",
+ "message": "must be object",
+ "params": {
+ "type": "object"
+ },
+ "schemaPath": "#/patternProperties/vars/type"
+ },
+ {
+ "instancePath": "/0/vars_files/0",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/properties/vars_files/items/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/vars_files/0",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/properties/vars_files/items/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/vars_files/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/properties/vars_files/items/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/var_files_list_number.yml",
+ "path": "$[0]",
+ "message": "{'name': 'var_files should not accept array[number]', 'hosts': 'localhost', 'vars_files': [0]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts' does not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts' does not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'name': 'var_files should not accept array[number]', 'hosts': 'localhost', 'vars_files': [0]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].vars_files",
+ "message": "[0] is not of type 'object'"
+ },
+ {
+ "path": "$[0].vars_files[0]",
+ "message": "0 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].vars_files[0]",
+ "message": "0 is not of type 'string'"
+ },
+ {
+ "path": "$[0].vars_files[0]",
+ "message": "0 is not of type 'array'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/var_files_list_of_list_number.yml b/test/schemas/negative_test/playbooks/var_files_list_of_list_number.yml
new file mode 100644
index 0000000..7170010
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/var_files_list_of_list_number.yml
@@ -0,0 +1,5 @@
+---
+- name: var_files should not accept array[number]
+ hosts: localhost
+ vars_files:
+ - [0, 1]
diff --git a/test/schemas/negative_test/playbooks/var_files_list_of_list_number.yml.md b/test/schemas/negative_test/playbooks/var_files_list_of_list_number.yml.md
new file mode 100644
index 0000000..3494498
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/var_files_list_of_list_number.yml.md
@@ -0,0 +1,157 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/vars_files",
+ "keyword": "type",
+ "message": "must be object",
+ "params": {
+ "type": "object"
+ },
+ "schemaPath": "#/patternProperties/vars/type"
+ },
+ {
+ "instancePath": "/0/vars_files/0",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/properties/vars_files/items/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/vars_files/0/0",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/properties/vars_files/items/oneOf/1/items/type"
+ },
+ {
+ "instancePath": "/0/vars_files/0/1",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/properties/vars_files/items/oneOf/1/items/type"
+ },
+ {
+ "instancePath": "/0/vars_files/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/properties/vars_files/items/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/var_files_list_of_list_number.yml",
+ "path": "$[0]",
+ "message": "{'name': 'var_files should not accept array[number]', 'hosts': 'localhost', 'vars_files': [[0, 1]]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts' does not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts' does not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'name': 'var_files should not accept array[number]', 'hosts': 'localhost', 'vars_files': [[0, 1]]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].vars_files",
+ "message": "[[0, 1]] is not of type 'object'"
+ },
+ {
+ "path": "$[0].vars_files[0]",
+ "message": "[0, 1] is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].vars_files[0]",
+ "message": "[0, 1] is not of type 'string'"
+ },
+ {
+ "path": "$[0].vars_files[0][0]",
+ "message": "0 is not of type 'string'"
+ },
+ {
+ "path": "$[0].vars_files[0][1]",
+ "message": "1 is not of type 'string'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/var_files_number.yml b/test/schemas/negative_test/playbooks/var_files_number.yml
new file mode 100644
index 0000000..fe26650
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/var_files_number.yml
@@ -0,0 +1,4 @@
+---
+- name: var_files should not accept number
+ hosts: localhost
+ vars_files: 0
diff --git a/test/schemas/negative_test/playbooks/var_files_number.yml.md b/test/schemas/negative_test/playbooks/var_files_number.yml.md
new file mode 100644
index 0000000..fa97e7e
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/var_files_number.yml.md
@@ -0,0 +1,122 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/vars_files",
+ "keyword": "type",
+ "message": "must be object",
+ "params": {
+ "type": "object"
+ },
+ "schemaPath": "#/patternProperties/vars/type"
+ },
+ {
+ "instancePath": "/0/vars_files",
+ "keyword": "type",
+ "message": "must be array,string,null",
+ "params": {
+ "type": [
+ "array",
+ "string",
+ "null"
+ ]
+ },
+ "schemaPath": "#/properties/vars_files/type"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/var_files_number.yml",
+ "path": "$[0]",
+ "message": "{'name': 'var_files should not accept number', 'hosts': 'localhost', 'vars_files': 0} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts' does not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts' does not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'name': 'var_files should not accept number', 'hosts': 'localhost', 'vars_files': 0} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].vars_files",
+ "message": "0 is not of type 'object'"
+ },
+ {
+ "path": "$[0].vars_files",
+ "message": "0 is not of type 'array', 'string', 'null'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/vars/asterisk.yml b/test/schemas/negative_test/playbooks/vars/asterisk.yml
new file mode 100644
index 0000000..9dd2200
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/asterisk.yml
@@ -0,0 +1,2 @@
+---
+"*foo": ... # invalid var name
diff --git a/test/schemas/negative_test/playbooks/vars/asterisk.yml.md b/test/schemas/negative_test/playbooks/vars/asterisk.yml.md
new file mode 100644
index 0000000..1ea9a98
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/asterisk.yml.md
@@ -0,0 +1,77 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "*foo"
+ },
+ "schemaPath": "#/anyOf/0/additionalProperties"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/anyOf/1/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be null",
+ "params": {
+ "type": "null"
+ },
+ "schemaPath": "#/anyOf/2/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/vars/asterisk.yml",
+ "path": "$",
+ "message": "{'*foo': '...'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$",
+ "message": "{'*foo': '...'} is not of type 'string'"
+ },
+ "sub_errors": [
+ {
+ "path": "$",
+ "message": "'*foo' does not match any of the regexes: '^(?!(False|None|True|and|any_errors_fatal|as|assert|async|await|become|become_exe|become_flags|become_method|become_user|break|check_mode|class|collections|connection|continue|debugger|def|del|diff|elif|else|environment|except|fact_path|finally|for|force_handlers|from|gather_facts|gather_subset|gather_timeout|global|handlers|hosts|if|ignore_errors|ignore_unreachable|import|in|is|lambda|max_fail_percentage|module_defaults|name|no_log|nonlocal|not|or|order|pass|port|post_tasks|pre_tasks|raise|remote_user|return|roles|run_once|serial|strategy|tags|tasks|throttle|timeout|try|vars|vars_files|vars_prompt|while|with|yield)$)[a-zA-Z_][\\\\w]*$'"
+ },
+ {
+ "path": "$",
+ "message": "{'*foo': '...'} is not of type 'string'"
+ },
+ {
+ "path": "$",
+ "message": "{'*foo': '...'} is not of type 'null'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/vars/dash-in-var-name.yml b/test/schemas/negative_test/playbooks/vars/dash-in-var-name.yml
new file mode 100644
index 0000000..216de64
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/dash-in-var-name.yml
@@ -0,0 +1,2 @@
+---
+foo-bar: ... # invalid var name
diff --git a/test/schemas/negative_test/playbooks/vars/dash-in-var-name.yml.md b/test/schemas/negative_test/playbooks/vars/dash-in-var-name.yml.md
new file mode 100644
index 0000000..b862e69
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/dash-in-var-name.yml.md
@@ -0,0 +1,77 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "foo-bar"
+ },
+ "schemaPath": "#/anyOf/0/additionalProperties"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/anyOf/1/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be null",
+ "params": {
+ "type": "null"
+ },
+ "schemaPath": "#/anyOf/2/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/vars/dash-in-var-name.yml",
+ "path": "$",
+ "message": "{'foo-bar': '...'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$",
+ "message": "{'foo-bar': '...'} is not of type 'string'"
+ },
+ "sub_errors": [
+ {
+ "path": "$",
+ "message": "'foo-bar' does not match any of the regexes: '^(?!(False|None|True|and|any_errors_fatal|as|assert|async|await|become|become_exe|become_flags|become_method|become_user|break|check_mode|class|collections|connection|continue|debugger|def|del|diff|elif|else|environment|except|fact_path|finally|for|force_handlers|from|gather_facts|gather_subset|gather_timeout|global|handlers|hosts|if|ignore_errors|ignore_unreachable|import|in|is|lambda|max_fail_percentage|module_defaults|name|no_log|nonlocal|not|or|order|pass|port|post_tasks|pre_tasks|raise|remote_user|return|roles|run_once|serial|strategy|tags|tasks|throttle|timeout|try|vars|vars_files|vars_prompt|while|with|yield)$)[a-zA-Z_][\\\\w]*$'"
+ },
+ {
+ "path": "$",
+ "message": "{'foo-bar': '...'} is not of type 'string'"
+ },
+ {
+ "path": "$",
+ "message": "{'foo-bar': '...'} is not of type 'null'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/vars/list.yml b/test/schemas/negative_test/playbooks/vars/list.yml
new file mode 100644
index 0000000..909a4d7
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/list.yml
@@ -0,0 +1,3 @@
+# invalid vars file, as sequence is not allowed
+- foo
+- bar
diff --git a/test/schemas/negative_test/playbooks/vars/list.yml.md b/test/schemas/negative_test/playbooks/vars/list.yml.md
new file mode 100644
index 0000000..e2c9bf5
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/list.yml.md
@@ -0,0 +1,77 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be object",
+ "params": {
+ "type": "object"
+ },
+ "schemaPath": "#/anyOf/0/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/anyOf/1/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be null",
+ "params": {
+ "type": "null"
+ },
+ "schemaPath": "#/anyOf/2/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/vars/list.yml",
+ "path": "$",
+ "message": "['foo', 'bar'] is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$",
+ "message": "['foo', 'bar'] is not of type 'object'"
+ },
+ "sub_errors": [
+ {
+ "path": "$",
+ "message": "['foo', 'bar'] is not of type 'object'"
+ },
+ {
+ "path": "$",
+ "message": "['foo', 'bar'] is not of type 'string'"
+ },
+ {
+ "path": "$",
+ "message": "['foo', 'bar'] is not of type 'null'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/vars/numeric-var-name.yml b/test/schemas/negative_test/playbooks/vars/numeric-var-name.yml
new file mode 100644
index 0000000..826150d
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/numeric-var-name.yml
@@ -0,0 +1,2 @@
+---
+12: ... # invalid var name
diff --git a/test/schemas/negative_test/playbooks/vars/numeric-var-name.yml.md b/test/schemas/negative_test/playbooks/vars/numeric-var-name.yml.md
new file mode 100644
index 0000000..7ddcff6
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/numeric-var-name.yml.md
@@ -0,0 +1,77 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "12"
+ },
+ "schemaPath": "#/anyOf/0/additionalProperties"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/anyOf/1/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be null",
+ "params": {
+ "type": "null"
+ },
+ "schemaPath": "#/anyOf/2/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/vars/numeric-var-name.yml",
+ "path": "$",
+ "message": "{'12': '...'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$",
+ "message": "{'12': '...'} is not of type 'string'"
+ },
+ "sub_errors": [
+ {
+ "path": "$",
+ "message": "'12' does not match any of the regexes: '^(?!(False|None|True|and|any_errors_fatal|as|assert|async|await|become|become_exe|become_flags|become_method|become_user|break|check_mode|class|collections|connection|continue|debugger|def|del|diff|elif|else|environment|except|fact_path|finally|for|force_handlers|from|gather_facts|gather_subset|gather_timeout|global|handlers|hosts|if|ignore_errors|ignore_unreachable|import|in|is|lambda|max_fail_percentage|module_defaults|name|no_log|nonlocal|not|or|order|pass|port|post_tasks|pre_tasks|raise|remote_user|return|roles|run_once|serial|strategy|tags|tasks|throttle|timeout|try|vars|vars_files|vars_prompt|while|with|yield)$)[a-zA-Z_][\\\\w]*$'"
+ },
+ {
+ "path": "$",
+ "message": "{'12': '...'} is not of type 'string'"
+ },
+ {
+ "path": "$",
+ "message": "{'12': '...'} is not of type 'null'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/vars/play-keyword.yml b/test/schemas/negative_test/playbooks/vars/play-keyword.yml
new file mode 100644
index 0000000..7d277ed
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/play-keyword.yml
@@ -0,0 +1,2 @@
+---
+environment: ... # invalid var name
diff --git a/test/schemas/negative_test/playbooks/vars/play-keyword.yml.md b/test/schemas/negative_test/playbooks/vars/play-keyword.yml.md
new file mode 100644
index 0000000..6b88b2a
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/play-keyword.yml.md
@@ -0,0 +1,77 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "environment"
+ },
+ "schemaPath": "#/anyOf/0/additionalProperties"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/anyOf/1/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be null",
+ "params": {
+ "type": "null"
+ },
+ "schemaPath": "#/anyOf/2/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/vars/play-keyword.yml",
+ "path": "$",
+ "message": "{'environment': '...'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$",
+ "message": "{'environment': '...'} is not of type 'string'"
+ },
+ "sub_errors": [
+ {
+ "path": "$",
+ "message": "'environment' does not match any of the regexes: '^(?!(False|None|True|and|any_errors_fatal|as|assert|async|await|become|become_exe|become_flags|become_method|become_user|break|check_mode|class|collections|connection|continue|debugger|def|del|diff|elif|else|environment|except|fact_path|finally|for|force_handlers|from|gather_facts|gather_subset|gather_timeout|global|handlers|hosts|if|ignore_errors|ignore_unreachable|import|in|is|lambda|max_fail_percentage|module_defaults|name|no_log|nonlocal|not|or|order|pass|port|post_tasks|pre_tasks|raise|remote_user|return|roles|run_once|serial|strategy|tags|tasks|throttle|timeout|try|vars|vars_files|vars_prompt|while|with|yield)$)[a-zA-Z_][\\\\w]*$'"
+ },
+ {
+ "path": "$",
+ "message": "{'environment': '...'} is not of type 'string'"
+ },
+ {
+ "path": "$",
+ "message": "{'environment': '...'} is not of type 'null'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/vars/python-keyword.yml b/test/schemas/negative_test/playbooks/vars/python-keyword.yml
new file mode 100644
index 0000000..7b9d01d
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/python-keyword.yml
@@ -0,0 +1,3 @@
+---
+async: ... # invalid var name
+lambda: ... # invalid var name
diff --git a/test/schemas/negative_test/playbooks/vars/python-keyword.yml.md b/test/schemas/negative_test/playbooks/vars/python-keyword.yml.md
new file mode 100644
index 0000000..ca42f74
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/python-keyword.yml.md
@@ -0,0 +1,86 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "async"
+ },
+ "schemaPath": "#/anyOf/0/additionalProperties"
+ },
+ {
+ "instancePath": "",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "lambda"
+ },
+ "schemaPath": "#/anyOf/0/additionalProperties"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/anyOf/1/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be null",
+ "params": {
+ "type": "null"
+ },
+ "schemaPath": "#/anyOf/2/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/vars/python-keyword.yml",
+ "path": "$",
+ "message": "{'async': '...', 'lambda': '...'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$",
+ "message": "{'async': '...', 'lambda': '...'} is not of type 'string'"
+ },
+ "sub_errors": [
+ {
+ "path": "$",
+ "message": "'async', 'lambda' do not match any of the regexes: '^(?!(False|None|True|and|any_errors_fatal|as|assert|async|await|become|become_exe|become_flags|become_method|become_user|break|check_mode|class|collections|connection|continue|debugger|def|del|diff|elif|else|environment|except|fact_path|finally|for|force_handlers|from|gather_facts|gather_subset|gather_timeout|global|handlers|hosts|if|ignore_errors|ignore_unreachable|import|in|is|lambda|max_fail_percentage|module_defaults|name|no_log|nonlocal|not|or|order|pass|port|post_tasks|pre_tasks|raise|remote_user|return|roles|run_once|serial|strategy|tags|tasks|throttle|timeout|try|vars|vars_files|vars_prompt|while|with|yield)$)[a-zA-Z_][\\\\w]*$'"
+ },
+ {
+ "path": "$",
+ "message": "{'async': '...', 'lambda': '...'} is not of type 'string'"
+ },
+ {
+ "path": "$",
+ "message": "{'async': '...', 'lambda': '...'} is not of type 'null'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/vars/varname-numeric-prefix.yml b/test/schemas/negative_test/playbooks/vars/varname-numeric-prefix.yml
new file mode 100644
index 0000000..5f97995
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/varname-numeric-prefix.yml
@@ -0,0 +1,2 @@
+---
+5foo: ... # invalid var name
diff --git a/test/schemas/negative_test/playbooks/vars/varname-numeric-prefix.yml.md b/test/schemas/negative_test/playbooks/vars/varname-numeric-prefix.yml.md
new file mode 100644
index 0000000..8b73b0a
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vars/varname-numeric-prefix.yml.md
@@ -0,0 +1,77 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "5foo"
+ },
+ "schemaPath": "#/anyOf/0/additionalProperties"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/anyOf/1/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be null",
+ "params": {
+ "type": "null"
+ },
+ "schemaPath": "#/anyOf/2/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/vars/varname-numeric-prefix.yml",
+ "path": "$",
+ "message": "{'5foo': '...'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$",
+ "message": "{'5foo': '...'} is not of type 'string'"
+ },
+ "sub_errors": [
+ {
+ "path": "$",
+ "message": "'5foo' does not match any of the regexes: '^(?!(False|None|True|and|any_errors_fatal|as|assert|async|await|become|become_exe|become_flags|become_method|become_user|break|check_mode|class|collections|connection|continue|debugger|def|del|diff|elif|else|environment|except|fact_path|finally|for|force_handlers|from|gather_facts|gather_subset|gather_timeout|global|handlers|hosts|if|ignore_errors|ignore_unreachable|import|in|is|lambda|max_fail_percentage|module_defaults|name|no_log|nonlocal|not|or|order|pass|port|post_tasks|pre_tasks|raise|remote_user|return|roles|run_once|serial|strategy|tags|tasks|throttle|timeout|try|vars|vars_files|vars_prompt|while|with|yield)$)[a-zA-Z_][\\\\w]*$'"
+ },
+ {
+ "path": "$",
+ "message": "{'5foo': '...'} is not of type 'string'"
+ },
+ {
+ "path": "$",
+ "message": "{'5foo': '...'} is not of type 'null'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/vas_prompt.yml b/test/schemas/negative_test/playbooks/vas_prompt.yml
new file mode 100644
index 0000000..a90d131
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vas_prompt.yml
@@ -0,0 +1,7 @@
+- hosts: localhost
+ vars_prompt:
+ - name: username
+ prompt: What is your username?
+ private: false
+ tags: # tags were never supported, https://github.com/ansible/ansible/issues/1780
+ - foo
diff --git a/test/schemas/negative_test/playbooks/vas_prompt.yml.md b/test/schemas/negative_test/playbooks/vas_prompt.yml.md
new file mode 100644
index 0000000..d2d809d
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/vas_prompt.yml.md
@@ -0,0 +1,118 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/vars_prompt",
+ "keyword": "type",
+ "message": "must be object",
+ "params": {
+ "type": "object"
+ },
+ "schemaPath": "#/patternProperties/vars/type"
+ },
+ {
+ "instancePath": "/0/vars_prompt/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tags"
+ },
+ "schemaPath": "#/$defs/vars_prompt/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/vas_prompt.yml",
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'vars_prompt': [{'name': 'username', 'prompt': 'What is your username?', 'private': False, 'tags': ['foo']}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'hosts' does not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'hosts' does not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'hosts': 'localhost', 'vars_prompt': [{'name': 'username', 'prompt': 'What is your username?', 'private': False, 'tags': ['foo']}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].vars_prompt",
+ "message": "[{'name': 'username', 'prompt': 'What is your username?', 'private': False, 'tags': ['foo']}] is not of type 'object'"
+ },
+ {
+ "path": "$[0].vars_prompt[0]",
+ "message": "Additional properties are not allowed ('tags' was unexpected)"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/playbooks/when.yml b/test/schemas/negative_test/playbooks/when.yml
new file mode 100644
index 0000000..c48bdc1
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/when.yml
@@ -0,0 +1,11 @@
+---
+- name: Test for when (failure)
+ hosts: localhost
+ gather_facts: false
+ tasks:
+ - name: Testing for when is passed a list
+ ansible.builtin.debug:
+ msg: "this is ok"
+ when:
+ - true
+ - 123
diff --git a/test/schemas/negative_test/playbooks/when.yml.md b/test/schemas/negative_test/playbooks/when.yml.md
new file mode 100644
index 0000000..4c23dcb
--- /dev/null
+++ b/test/schemas/negative_test/playbooks/when.yml.md
@@ -0,0 +1,286 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'ansible.builtin.import_playbook'",
+ "params": {
+ "missingProperty": "ansible.builtin.import_playbook"
+ },
+ "schemaPath": "#/oneOf/0/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "required",
+ "message": "must have required property 'import_playbook'",
+ "params": {
+ "missingProperty": "import_playbook"
+ },
+ "schemaPath": "#/oneOf/1/required"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/oneOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "hosts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "gather_facts"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "tasks"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "required",
+ "message": "must have required property 'block'",
+ "params": {
+ "missingProperty": "block"
+ },
+ "schemaPath": "#/required"
+ },
+ {
+ "instancePath": "/0/tasks/0/when",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/when",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/when/1",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/2/items/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/when/1",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/2/items/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/when/1",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/$defs/complex_conditional/oneOf/2/items/anyOf"
+ },
+ {
+ "instancePath": "/0/tasks/0/when",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf"
+ },
+ {
+ "instancePath": "/0/tasks/0/when",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/when",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/1/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/when/1",
+ "keyword": "type",
+ "message": "must be boolean",
+ "params": {
+ "type": "boolean"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/2/items/anyOf/0/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/when/1",
+ "keyword": "type",
+ "message": "must be string",
+ "params": {
+ "type": "string"
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf/2/items/anyOf/1/type"
+ },
+ {
+ "instancePath": "/0/tasks/0/when/1",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/$defs/complex_conditional/oneOf/2/items/anyOf"
+ },
+ {
+ "instancePath": "/0/tasks/0/when",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/$defs/complex_conditional/oneOf"
+ },
+ {
+ "instancePath": "/0/tasks/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/items/anyOf"
+ },
+ {
+ "instancePath": "/0",
+ "keyword": "oneOf",
+ "message": "must match exactly one schema in oneOf",
+ "params": {
+ "passingSchemas": null
+ },
+ "schemaPath": "#/items/oneOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/playbooks/when.yml",
+ "path": "$[0]",
+ "message": "{'name': 'Test for when (failure)', 'hosts': 'localhost', 'gather_facts': False, 'tasks': [{'name': 'Testing for when is passed a list', 'ansible.builtin.debug': {'msg': 'this is ok'}, 'when': [True, 123]}]} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$[0]",
+ "message": "'gather_facts', 'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ "sub_errors": [
+ {
+ "path": "$[0]",
+ "message": "'gather_facts', 'hosts', 'tasks' do not match any of the regexes: '^(ansible\\\\.builtin\\\\.)?import_playbook$', 'name', 'tags', 'vars', 'when'"
+ },
+ {
+ "path": "$[0]",
+ "message": "{'name': 'Test for when (failure)', 'hosts': 'localhost', 'gather_facts': False, 'tasks': [{'name': 'Testing for when is passed a list', 'ansible.builtin.debug': {'msg': 'this is ok'}, 'when': [True, 123]}]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0]",
+ "message": "'ansible.builtin.import_playbook' is a required property"
+ },
+ {
+ "path": "$[0]",
+ "message": "'import_playbook' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "{'name': 'Testing for when is passed a list', 'ansible.builtin.debug': {'msg': 'this is ok'}, 'when': [True, 123]} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].when",
+ "message": "[True, 123] is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].when",
+ "message": "[True, 123] is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].when",
+ "message": "[True, 123] is not of type 'string'"
+ },
+ {
+ "path": "$[0].tasks[0].when[1]",
+ "message": "123 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].when[1]",
+ "message": "123 is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].when[1]",
+ "message": "123 is not of type 'string'"
+ },
+ {
+ "path": "$[0].tasks[0]",
+ "message": "'block' is a required property"
+ },
+ {
+ "path": "$[0].tasks[0].when",
+ "message": "[True, 123] is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].when",
+ "message": "[True, 123] is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].when",
+ "message": "[True, 123] is not of type 'string'"
+ },
+ {
+ "path": "$[0].tasks[0].when[1]",
+ "message": "123 is not valid under any of the given schemas"
+ },
+ {
+ "path": "$[0].tasks[0].when[1]",
+ "message": "123 is not of type 'boolean'"
+ },
+ {
+ "path": "$[0].tasks[0].when[1]",
+ "message": "123 is not of type 'string'"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/reqs3/meta/requirements.yml b/test/schemas/negative_test/reqs3/meta/requirements.yml
new file mode 100644
index 0000000..f28aebb
--- /dev/null
+++ b/test/schemas/negative_test/reqs3/meta/requirements.yml
@@ -0,0 +1,2 @@
+# this should fail validation
+foo: bar
diff --git a/test/schemas/negative_test/reqs3/meta/requirements.yml.md b/test/schemas/negative_test/reqs3/meta/requirements.yml.md
new file mode 100644
index 0000000..5de6643
--- /dev/null
+++ b/test/schemas/negative_test/reqs3/meta/requirements.yml.md
@@ -0,0 +1,101 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/anyOf/0/type"
+ },
+ {
+ "instancePath": "",
+ "keyword": "required",
+ "message": "must have required property 'collections'",
+ "params": {
+ "missingProperty": "collections"
+ },
+ "schemaPath": "#/anyOf/0/required"
+ },
+ {
+ "instancePath": "",
+ "keyword": "required",
+ "message": "must have required property 'roles'",
+ "params": {
+ "missingProperty": "roles"
+ },
+ "schemaPath": "#/anyOf/1/required"
+ },
+ {
+ "instancePath": "",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/anyOf"
+ },
+ {
+ "instancePath": "",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "foo"
+ },
+ "schemaPath": "#/additionalProperties"
+ },
+ {
+ "instancePath": "",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/anyOf"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/reqs3/meta/requirements.yml",
+ "path": "$",
+ "message": "{'foo': 'bar'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$",
+ "message": "{'foo': 'bar'} is not of type 'array'"
+ },
+ "sub_errors": [
+ {
+ "path": "$",
+ "message": "{'foo': 'bar'} is not of type 'array'"
+ },
+ {
+ "path": "$",
+ "message": "Additional properties are not allowed ('foo' was unexpected)"
+ },
+ {
+ "path": "$",
+ "message": "{'foo': 'bar'} is not valid under any of the given schemas"
+ },
+ {
+ "path": "$",
+ "message": "'collections' is a required property"
+ },
+ {
+ "path": "$",
+ "message": "'roles' is a required property"
+ }
+ ]
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/roles/meta/argument_specs.yml b/test/schemas/negative_test/roles/meta/argument_specs.yml
new file mode 100644
index 0000000..ddc9862
--- /dev/null
+++ b/test/schemas/negative_test/roles/meta/argument_specs.yml
@@ -0,0 +1,5 @@
+---
+argument_specs:
+ main:
+ foo: bar # <-- invalid based on json schema
+ options: {}
diff --git a/test/schemas/negative_test/roles/meta/argument_specs.yml.md b/test/schemas/negative_test/roles/meta/argument_specs.yml.md
new file mode 100644
index 0000000..34da932
--- /dev/null
+++ b/test/schemas/negative_test/roles/meta/argument_specs.yml.md
@@ -0,0 +1,34 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/argument_specs/main",
+ "keyword": "additionalProperties",
+ "message": "must NOT have additional properties",
+ "params": {
+ "additionalProperty": "foo"
+ },
+ "schemaPath": "#/additionalProperties"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/roles/meta/argument_specs.yml",
+ "path": "$.argument_specs.main",
+ "message": "Additional properties are not allowed ('foo' was unexpected)",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/roles/meta/main.yml b/test/schemas/negative_test/roles/meta/main.yml
new file mode 100644
index 0000000..3ed9a8c
--- /dev/null
+++ b/test/schemas/negative_test/roles/meta/main.yml
@@ -0,0 +1,10 @@
+galaxy_info:
+ description: bar
+ min_ansible_version: "2.9"
+ company: foo
+ license: MIT
+ galaxy_tags: database # <-- invalid, must be a list of strings
+ platforms:
+ - name: Alpine
+ versions:
+ - all
diff --git a/test/schemas/negative_test/roles/meta/main.yml.md b/test/schemas/negative_test/roles/meta/main.yml.md
new file mode 100644
index 0000000..2c9e99b
--- /dev/null
+++ b/test/schemas/negative_test/roles/meta/main.yml.md
@@ -0,0 +1,58 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/galaxy_info",
+ "keyword": "required",
+ "message": "must have required property 'author'",
+ "params": {
+ "missingProperty": "author"
+ },
+ "schemaPath": "#/allOf/0/then/required"
+ },
+ {
+ "instancePath": "/galaxy_info",
+ "keyword": "if",
+ "message": "must match \"then\" schema",
+ "params": {
+ "failingKeyword": "then"
+ },
+ "schemaPath": "#/allOf/0/if"
+ },
+ {
+ "instancePath": "/galaxy_info/galaxy_tags",
+ "keyword": "type",
+ "message": "must be array",
+ "params": {
+ "type": "array"
+ },
+ "schemaPath": "#/properties/galaxy_tags/type"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/roles/meta/main.yml",
+ "path": "$.galaxy_info",
+ "message": "'author' is a required property",
+ "has_sub_errors": false
+ },
+ {
+ "filename": "negative_test/roles/meta/main.yml",
+ "path": "$.galaxy_info.galaxy_tags",
+ "message": "'database' is not of type 'array'",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/roles/meta_invalid_collection/meta/main.yml b/test/schemas/negative_test/roles/meta_invalid_collection/meta/main.yml
new file mode 100644
index 0000000..1fa41eb
--- /dev/null
+++ b/test/schemas/negative_test/roles/meta_invalid_collection/meta/main.yml
@@ -0,0 +1,10 @@
+collections:
+ - foo # invalid pattern
+galaxy_info:
+ standalone: false # role inside a collection
+ description: foo
+ license: bar
+ platforms:
+ - name: Fedora
+ versions:
+ - all
diff --git a/test/schemas/negative_test/roles/meta_invalid_collection/meta/main.yml.md b/test/schemas/negative_test/roles/meta_invalid_collection/meta/main.yml.md
new file mode 100644
index 0000000..1b8dcd0
--- /dev/null
+++ b/test/schemas/negative_test/roles/meta_invalid_collection/meta/main.yml.md
@@ -0,0 +1,34 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/collections/0",
+ "keyword": "pattern",
+ "message": "must match pattern \"^[a-z_]+\\.[a-z_]+$\"",
+ "params": {
+ "pattern": "^[a-z_]+\\.[a-z_]+$"
+ },
+ "schemaPath": "#/$defs/collections/items/pattern"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/roles/meta_invalid_collection/meta/main.yml",
+ "path": "$.collections[0]",
+ "message": "'foo' does not match '^[a-z_]+\\\\.[a-z_]+$'",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/roles/meta_invalid_collections/meta/main.yml b/test/schemas/negative_test/roles/meta_invalid_collections/meta/main.yml
new file mode 100644
index 0000000..488928c
--- /dev/null
+++ b/test/schemas/negative_test/roles/meta_invalid_collections/meta/main.yml
@@ -0,0 +1,11 @@
+# role inside a collection
+collections:
+ - FOO.BAR # invalid pattern, need to use lowercase
+galaxy_info:
+ standalone: false
+ description: foo
+ license: bar
+ platforms:
+ - name: Fedora
+ versions:
+ - all
diff --git a/test/schemas/negative_test/roles/meta_invalid_collections/meta/main.yml.md b/test/schemas/negative_test/roles/meta_invalid_collections/meta/main.yml.md
new file mode 100644
index 0000000..5d775f0
--- /dev/null
+++ b/test/schemas/negative_test/roles/meta_invalid_collections/meta/main.yml.md
@@ -0,0 +1,34 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/collections/0",
+ "keyword": "pattern",
+ "message": "must match pattern \"^[a-z_]+\\.[a-z_]+$\"",
+ "params": {
+ "pattern": "^[a-z_]+\\.[a-z_]+$"
+ },
+ "schemaPath": "#/$defs/collections/items/pattern"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/roles/meta_invalid_collections/meta/main.yml",
+ "path": "$.collections[0]",
+ "message": "'FOO.BAR' does not match '^[a-z_]+\\\\.[a-z_]+$'",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/roles/meta_invalid_role_namespace/meta/main.yml b/test/schemas/negative_test/roles/meta_invalid_role_namespace/meta/main.yml
new file mode 100644
index 0000000..e50e5b7
--- /dev/null
+++ b/test/schemas/negative_test/roles/meta_invalid_role_namespace/meta/main.yml
@@ -0,0 +1,12 @@
+---
+# old standalone role
+galaxy_info:
+ description: foo
+ min_ansible_version: "2.9"
+ namespace: foo-bar
+ company: foo
+ license: MIT
+ platforms:
+ - name: Alpine
+ versions:
+ - all
diff --git a/test/schemas/negative_test/roles/meta_invalid_role_namespace/meta/main.yml.md b/test/schemas/negative_test/roles/meta_invalid_role_namespace/meta/main.yml.md
new file mode 100644
index 0000000..ad7e9d3
--- /dev/null
+++ b/test/schemas/negative_test/roles/meta_invalid_role_namespace/meta/main.yml.md
@@ -0,0 +1,58 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/galaxy_info",
+ "keyword": "required",
+ "message": "must have required property 'author'",
+ "params": {
+ "missingProperty": "author"
+ },
+ "schemaPath": "#/allOf/0/then/required"
+ },
+ {
+ "instancePath": "/galaxy_info",
+ "keyword": "if",
+ "message": "must match \"then\" schema",
+ "params": {
+ "failingKeyword": "then"
+ },
+ "schemaPath": "#/allOf/0/if"
+ },
+ {
+ "instancePath": "/galaxy_info/namespace",
+ "keyword": "pattern",
+ "message": "must match pattern \"^[a-z][a-z0-9_]+$\"",
+ "params": {
+ "pattern": "^[a-z][a-z0-9_]+$"
+ },
+ "schemaPath": "#/properties/namespace/pattern"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/roles/meta_invalid_role_namespace/meta/main.yml",
+ "path": "$.galaxy_info",
+ "message": "'author' is a required property",
+ "has_sub_errors": false
+ },
+ {
+ "filename": "negative_test/roles/meta_invalid_role_namespace/meta/main.yml",
+ "path": "$.galaxy_info.namespace",
+ "message": "'foo-bar' does not match '^[a-z][a-z0-9_]+$'",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```
diff --git a/test/schemas/negative_test/roles/role_with_bad_deps_in_meta/meta/main.yml b/test/schemas/negative_test/roles/role_with_bad_deps_in_meta/meta/main.yml
new file mode 100644
index 0000000..81d4d3d
--- /dev/null
+++ b/test/schemas/negative_test/roles/role_with_bad_deps_in_meta/meta/main.yml
@@ -0,0 +1,13 @@
+# old standalone role
+galaxy_info:
+ description: bar
+ min_ansible_version: "2.9"
+ company: foo
+ license: MIT
+ platforms:
+ - name: Alpine
+ versions:
+ - all
+
+dependencies:
+ - version: foo # invalid, should have at least name, role or src properties
diff --git a/test/schemas/negative_test/roles/role_with_bad_deps_in_meta/meta/main.yml.md b/test/schemas/negative_test/roles/role_with_bad_deps_in_meta/meta/main.yml.md
new file mode 100644
index 0000000..f09b1ac
--- /dev/null
+++ b/test/schemas/negative_test/roles/role_with_bad_deps_in_meta/meta/main.yml.md
@@ -0,0 +1,101 @@
+# ajv errors
+
+```json
+[
+ {
+ "instancePath": "/dependencies/0",
+ "keyword": "required",
+ "message": "must have required property 'role'",
+ "params": {
+ "missingProperty": "role"
+ },
+ "schemaPath": "#/anyOf/0/required"
+ },
+ {
+ "instancePath": "/dependencies/0",
+ "keyword": "required",
+ "message": "must have required property 'src'",
+ "params": {
+ "missingProperty": "src"
+ },
+ "schemaPath": "#/anyOf/1/required"
+ },
+ {
+ "instancePath": "/dependencies/0",
+ "keyword": "required",
+ "message": "must have required property 'name'",
+ "params": {
+ "missingProperty": "name"
+ },
+ "schemaPath": "#/anyOf/2/required"
+ },
+ {
+ "instancePath": "/dependencies/0",
+ "keyword": "anyOf",
+ "message": "must match a schema in anyOf",
+ "params": {},
+ "schemaPath": "#/anyOf"
+ },
+ {
+ "instancePath": "/galaxy_info",
+ "keyword": "required",
+ "message": "must have required property 'author'",
+ "params": {
+ "missingProperty": "author"
+ },
+ "schemaPath": "#/allOf/0/then/required"
+ },
+ {
+ "instancePath": "/galaxy_info",
+ "keyword": "if",
+ "message": "must match \"then\" schema",
+ "params": {
+ "failingKeyword": "then"
+ },
+ "schemaPath": "#/allOf/0/if"
+ }
+]
+```
+
+# check-jsonschema
+
+stdout:
+
+```json
+{
+ "status": "fail",
+ "errors": [
+ {
+ "filename": "negative_test/roles/role_with_bad_deps_in_meta/meta/main.yml",
+ "path": "$.dependencies[0]",
+ "message": "{'version': 'foo'} is not valid under any of the given schemas",
+ "has_sub_errors": true,
+ "best_match": {
+ "path": "$.dependencies[0]",
+ "message": "'role' is a required property"
+ },
+ "sub_errors": [
+ {
+ "path": "$.dependencies[0]",
+ "message": "'role' is a required property"
+ },
+ {
+ "path": "$.dependencies[0]",
+ "message": "'src' is a required property"
+ },
+ {
+ "path": "$.dependencies[0]",
+ "message": "'name' is a required property"
+ }
+ ]
+ },
+ {
+ "filename": "negative_test/roles/role_with_bad_deps_in_meta/meta/main.yml",
+ "path": "$.galaxy_info",
+ "message": "'author' is a required property",
+ "has_sub_errors": false
+ }
+ ],
+ "parse_errors": []
+}
+```