{
	"$schema": "http://json-schema.org/draft-07/schema#",
	"$id": "https://neotys.com/schemas/as-code/v3",
	"title": "JSON Schema for NeoLoad as-code files",
	"fileMatch": [
		"*.nl.yaml", "*.neoload.yaml", "neoload*.yaml",
		"*.nl.yml", "*.neoload.yml", "neoload*.yml",
		"*.nl.json", "*.neoload.json", "neoload*.json"
	],
	"type": "object",
	"additionalProperties": false,
	"minProperties": 1,
	"xrequired": ["name","because neoload files can be partial"],
	"properties": {
	  "$schema": { "$ref": "#/definitions/common/full_url" },
	  "name": { "$ref": "#/definitions/common/name" },
	  "includes": {
		"$id":"#root/includes",
		"title":"Includes",
		"type":"array",
		"minItems":1,
		"additionalProperties":false,
		"items": { "$ref": "#/definitions/common/text" }
	  },
	  "variables": {
		"$id":"#root/variables",
		"title":"Variables",
		"type":"array",
		"additionalItems": false,
		"minItems":1,
		"additionalProperties":false,
		"items": {
			"anyOf": [
				{ "$ref": "#/definitions/variables/constant" },
				{ "$ref": "#/definitions/variables/file" },
				{ "$ref": "#/definitions/variables/counter" },
				{ "$ref": "#/definitions/variables/random_number" },
				{ "$ref": "#/definitions/variables/javascript" }
			]
		}
	  },
	  "servers": {
		"$id":"#root/servers",
		"title":"Servers",
		"type":"array",
		"minItems": 1,
		"items": { "$ref":  "#/definitions/server" }
	  },
	  "sla_profiles":{
		"$id":"#root/sla_profiles",
		"title":"SLA Profiles",
		"type":"array",
		"minItems": 1,
		"items": { "$ref":  "#/definitions/sla" }
	  },
	  "populations":{
		"$id":"#root/populations",
		"title":"Populations",
		"type":"array",
		"minItems": 1,
		"items": { "$ref": "#/definitions/populations/population" }
	  },
	  "scenarios":{
		"$id":"#root/scenarios",
		"title":"Scenarios",
		"type":"array",
		"minItems": 1,
		"items": { "$ref": "#/definitions/scenario" }
	  },
	  "user_paths":{
		"$id":"#root/user_paths",
		"title":"User_paths",
		"type":"array",
		"minItems": 1,
		"items": { "$ref": "#/definitions/user_paths/user_path" }
	  }
	},
	"definitions":{
		"common": {
			"text":{
				"$id":"#/definitions/common/text",
				"title":"Text",
				"type":"string",
				"pattern":".*"
			},
			"positive_number":{
				"$id":"#/definitions/common/positive_number",
				"title":"Positive Number",
				"type":"integer",
				"minimum": 0
			},
			"duration":{
				"$id":"#/definitions/common/duration",
				"title":"Duration",
			  "anyOf": [
			    { "$ref": "#/definitions/common/time" },
					{ "$ref": "#/definitions/common/iterations" }
			  ]
			},
			"stop_after_options":{
				"$id":"#/definitions/common/stop_after_options",
				"title":"variation_policy.stop_after values",
			  "anyOf": [
			    { "$ref": "#/definitions/common/time" },
					{ "type": "string", "enum": ["current_iteration"] }
			  ]
			},
			"start_after_options":{
				"$id":"#/definitions/common/start_after",
				"title":"Start after",
				"anyOf":[
					{ "$ref": "#/definitions/common/time" },
					{ "$ref": "#/definitions/common/text" }
				]
			},
			"time":{
				"$id":"#/definitions/common/time",
				"title":"Time",
				"type": "string",
				"pattern": "^((\\d{1,2}[hms]{1}){1,3})+$"
			},
			"iterations":{
				"$id":"#/definitions/common/iterations",
				"title":"Iterations",
			  "type": "string",
				"pattern": "^(\\d+ iterations)$"
			},
			"name":{
				"title":"Name",
				"type":"string",
				"pattern":"^.*$"
			  },
		  "full_url": {
			  "title":"Url",
			  "type":"string",
			  "pattern": "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)"
		  },
		  "var_change_policy": {
				"type":"string",
				"default": "each_iteration",
				"enum": ["each_use", "each_request", "each_page", "each_iteration", "each_user"]
		  },
		  "var_scope": {
				"type":"string",
				"default": "global",
				"enum": ["local", "global", "unique"]
		  },
		  "var_order": {
				"type":"string",
				"default": "global",
				"enum": ["sequential", "random", "any"]
		  },
		  "var_out_of_value": {
				"type":"string",
				"default": "global",
				"enum": ["cycle", "stop_test", "no_value_code"]
		  }
		},
		"variables": {
			"generic": {
				"$id":"#/definitions/variables/generic",
				"type":"object",
				"xrequired": ["name"],
				"properties":{
					"name": { "$ref": "#/definitions/common/name" },
					"descrption": { "$ref": "#/definitions/common/text" },
					"change_policy": { "$ref": "#/definitions/common/var_change_policy" }
				}
			},
			"constant":{
				"$id":"#/definitions/variables/constant",
				"title":"Constant",
				"type":"object",
				"xrequired": ["value"],
				"allOf": [
					{ "$ref": "#/definitions/variables/generic" },
					{
						"properties":{
							"value": { "$ref": "#/definitions/common/text" }
						  }
					}
				],
				"x-d7nosupport-additionalProperties": false
			},
			"file":{
				"$id":"#/definitions/variables/file",
				"title":"File",
				"type":"object",
				"xrequired": ["path"],
				"allOf": [
					{ "$ref": "#/definitions/variables/generic" },
					{
						"properties":{
							"column_names": {
							  "type": "array",
							  "items": [ { "type": "string" } ]
							},
							"is_first_line_column_names": {
							  "type": "boolean",
							  "default": false
							},
							"start_from_line": {
								"type": "integer",
								"default": 1
							},
							"delimiter": {
								"$ref": "#/definitions/common/text",
								"default": ","
							},
							"path": { "$ref": "#/definitions/common/text" },
							"scope": { "$ref": "#/definitions/common/var_scope" },
							"order": { "$ref": "#/definitions/common/var_order" },
							"out_of_value": { "$ref": "#/definitions/common/var_out_of_value" }
						}
					}
				],
				"x-d7nosupport-additionalProperties": false
			},
			"counter":{
				"$id":"#/definitions/variables/counter",
				"title":"Counter",
				"type":"object",
				"xrequired": ["start", "end", "increment"],
				"allOf": [
					{ "$ref": "#/definitions/variables/generic" },
					{
						"properties":{
							"start": {
								"type": "number"
							},
							"end": {
								"type": "number"
							},
							"increment": {
								"type": "number"
							},
							"scope": { "$ref": "#/definitions/common/var_scope" },
							"out_of_value": { "$ref": "#/definitions/common/var_out_of_value" }
						}
					}
				],
				"x-d7nosupport-additionalProperties": false
			},
			"random_number":{
				"$id":"#/definitions/variables/random_number",
				"title":"Random Number",
				"type":"object",
				"xrequired": ["min", "max"],
				"allOf": [
					{ "$ref": "#/definitions/variables/generic" },
					{
						"properties":{
							"min": {
								"type": "number"
							},
							"max": {
								"type": "number"
							},
							"predictable": {
								"type": "boolean"
							}
						}
					}
				],
				"x-d7nosupport-additionalProperties": false
			},
			"javascript":{
				"$id":"#/definitions/variables/javascript",
				"title":"Javascript",
				"type":"object",
				"xrequired": ["script"],
				"allOf": [
					{ "$ref": "#/definitions/variables/generic" },
					{
						"properties":{
							"script": { "$ref": "#/definitions/common/text" }
						}
					}
				],
				"x-d7nosupport-additionalProperties": false
			}
		},
		"server": {
			"$id":"#/definitions/server",
			"title":"Server",
			"type":"object",
			"xrequired": ["name","host"],
			"additionalProperties": false,
			"properties":{
				"name":{ "$ref": "#/definitions/common/text" },
				"host":{ "$ref": "#/definitions/common/text" },
				"scheme":{
					"$id":"#root/servers/items/scheme",
					"type":"string",
					"enum": ["http", "https"]
				},
				"port": {
					"type": "integer"
				},
				"basic_authentication": { "$ref": "#/definitions/authentication/basic" },
				"ntlm_authentication": { "$ref": "#/definitions/authentication/ntlm" },
				"negotiate_authentication": { "$ref": "#/definitions/authentication/basic" }
			}
		},
		"authentication": {
			"auth-generic": {
				"$id":"#/definitions/authentication/auth-generic",
				"type":"object",
				"xrequired": ["login","password"],
				"properties":{
					"login":{ "$ref": "#/definitions/common/text" },
					"password":{ "$ref": "#/definitions/common/text" }
				}
			},
			"auth-generic-domain": {
				"$id":"#/definitions/authentication/auth-generic-domain",
				"type":"object",
				"allOf": [
					{ "$ref": "#/definitions/authentication/auth-generic" },
					{
						"properties":{
							"domain": { "$ref": "#/definitions/common/text" }
						  }
					}
				]
			},
			"basic": {
				"$id":"#/definitions/authentication/basic",
				"title":"Basic Authentication",
				"type":"object",
				"allOf": [
					{ "$ref": "#/definitions/authentication/auth-generic" },
					{
						"properties":{
							"realm": { "$ref": "#/definitions/common/text" }
						  }
					}
				]
			},
			"ntlm": {
				"$id":"#/definitions/authentication/ntlm",
				"title":"NTLM Authentication",
				"type":"object",
				"allOf": [
					{ "$ref": "#/definitions/authentication/auth-generic-domain" }
				]
			},
			"negotiate": {
				"$id":"#/definitions/authentication/negotiate",
				"title":"Negotiate Authentication",
				"type":"object",
				"allOf": [
					{ "$ref": "#/definitions/authentication/auth-generic-domain" }
				]
			}
		},
		"sla": {
			"$id":"#/definitions/sla",
			"title":"SLA Profile",
			"type": "object",
			"xrequired": ["name","thresholds"],
			"properties": {
				"name": { "$ref": "#/definitions/common/text" },
				"description": { "$ref": "#/definitions/common/text" },
				"thresholds": {
					"$id":"#/definitions/sla/thresholds",
					"title":"Thresholds",
					"type":"array",
					"minItems":1,
					"additionalProperties":false,
					"items": { "$ref": "#/definitions/sla/threshold" }
				  }
			},
			"threshold":{
				"$id":"#/definitions/sla/threshold",
				"title":"Threshold",
				"type":"string",
				"pattern":"^(.*?)\\s(warn\\s(>=|==|<=|>|<))(?=\\s)(.*?)per\\s(test|interval)$"
			  }
		},
		"populations": {
			"population":{
				"$id":"#/definitions/population",
				"title":"Population",
				"type":"object",
				"properties":{
					"name":{ "$ref": "#/definitions/common/text" },
					"description":{ "$ref": "#/definitions/common/text" },
					"xcomments": {
						"value": "why do we need the substructure 'name' to denote a string list?"
					},
					"user_paths":{
						"type":"array",
						"minItems":1,
						"additionalProperties":false,
						"additionalItems": false,
						"items": {
							"type": "object",
							"properties": {
								"name": { "$ref": "#/definitions/common/text" }
							}
						}
					}
				}
			},
			"constant_load":{
				"$id":"#/definitions/populations/constant_load",
				"title":"Constant Load",
				"type":"object",
				"required": ["users"],
				"properties":{
					"duration":{ "$ref": "#/definitions/common/duration"},
					"start_after":{ "$ref": "#/definitions/common/start_after_options" },
					"stop_after":{ "$ref": "#/definitions/common/stop_after_options" },
					"users":{
						"type":"integer",
						"default":1
					},
					"rampup": { "$ref": "#/definitions/common/time" }
				}
			},
			"rampup_load":{
				"$id":"#/definitions/populations/rampup_load",
				"title":"Ramp-up Load",
				"type":"object",
				"required": ["min_users","increment_users","increment_every"],
				"properties":{
					"duration":{ "$ref": "#/definitions/common/duration" },
					"start_after":{ "$ref": "#/definitions/common/start_after_options" },
					"stop_after":{ "$ref": "#/definitions/common/stop_after_options" },
					"min_users": { "$ref": "#/definitions/common/positive_number" },
					"max_users": { "$ref": "#/definitions/common/positive_number" },
					"increment_users":{
						"type": "integer",
						"default": 1
					},
					"increment_every": { "$ref": "#/definitions/common/duration" },
					"increment_rampup": { "$ref": "#/definitions/common/time" }
				},
				"additionalProperties": false
			},
			"peaks_load":{
				"$id":"#/definitions/populations/peaks_load",
				"title":"Peaks Load",
				"type":"object",
				"required": ["minimum","maximum","start"],
				"properties":{
					"minimum":{ "$ref": "#/definitions/populations/peaks_phase" },
					"maximum":{ "$ref": "#/definitions/populations/peaks_phase" },
					"start": {
						"type": "string",
						"enum": ["minimum","maximum"]
					},
					"duration":{ "$ref": "#/definitions/common/duration" },
					"start_after":{ "$ref": "#/definitions/common/start_after_options" },
					"step_rampup": { "$ref": "#/definitions/common/text" },
					"stop_after":{ "$ref": "#/definitions/common/stop_after_options" }
				},
				"additionalProperties": false
			},
			"peaks_phase":{
				"$id":"#/definitions/populations/peaks_phase",
				"title":"Peak Phase",
				"type":"object",
				"required": ["users","duration"],
				"properties":{
					"users": { "$ref": "#/definitions/common/positive_number" },
					"duration": { "$ref": "#/definitions/common/duration" }
				}
			}
		},
		"scenario":{
			"$id":"#/definitions/scenario",
			"title":"Scenario",
			"type":"object",
			"properties":{
			  "name":{ "$ref": "#/definitions/common/text" },
			  "description":{ "$ref": "#/definitions/common/text" },
			  "populations":{
					"$id":"#/definitions/scenario/populations",
					"title":"Scenario Populations",
					"type":"array",
					"minItems": 1,
					"additionalItems": false,
					"additionalProperties": false,
					"items":{
					  "$id":"#/definitions/scenario/populations/items",
					  "type":"object",
					  "required": ["name"],
						"properties":{
							"name":{ "$ref": "#/definitions/common/text" },
							"constant_load": { "$ref": "#/definitions/populations/constant_load" },
							"rampup_load": { "$ref": "#/definitions/populations/rampup_load" },
							"peaks_load": { "$ref": "#/definitions/populations/peaks_load" }
						}
					}
			  }
			}
		},
		"user_paths": {
			"user_path":{
				"$id":"#/definitions/user_paths/user_path",
				"title":"User Path",
				"type":"object",
				"required": ["name","actions"],
				"properties":{
				  "name":{ "$ref": "#/definitions/common/text" },
				  "description":{ "$ref": "#/definitions/common/text" },
				  "user_session": {
					  "type": "string",
					  "enum": ["reset_on","reset_off","reset_auto"]
				  },
				  "init": { "$ref": "#/definitions/user_paths/container" },
				  "actions": { "$ref": "#/definitions/user_paths/container" },
				  "end": { "$ref": "#/definitions/user_paths/container" }
				}
			},
			"container":{
				"$id":"#/definitions/user_paths/container",
				"title":"Containers",
				"type":"object",
				"required": ["steps"],
				"properties":{
					"sla_profile": {
						"type": "string"
					},
					"steps":{
						"title":"Steps",
						"type":"array",
						"minItems": 1,
						"items": {
							"type": "object",
							"properties": {
								"transaction": { "$ref": "#/definitions/user_paths/actions/transaction" },
								"request": { "$ref": "#/definitions/user_paths/actions/request" },
								"delay": { "$ref": "#/definitions/user_paths/actions/delay" },
								"think_time": { "$ref": "#/definitions/user_paths/actions/think_time" },
								"javascript": { "$ref": "#/definitions/user_paths/actions/javascript" },
								"if": { "$ref": "#/definitions/user_paths/actions/if" }
							},
							"additionalProperties": false
						}
					}
				}
			},
			"actions": {
				"transaction":{
					"$id":"#/definitions/user_paths/actions/transaction",
					"name": "transaction",
					"title":"Action: Transaction",
					"type":"object",
					"required": ["name","steps"],
					"properties":{
						"name": { "$ref": "#/definitions/common/text" },
						"description": { "$ref": "#/definitions/common/text" },
						"steps":{
							"title":"Steps",
							"type":"array",
							"minItems": 1,
							"items": {
								"type": "object",
								"properties": {
									"transaction": { "$ref": "#/definitions/user_paths/actions/transaction" },
									"request": { "$ref": "#/definitions/user_paths/actions/request" },
									"delay": { "$ref": "#/definitions/user_paths/actions/delay" },
									"think_time": { "$ref": "#/definitions/user_paths/actions/think_time" },
									"javascript": { "$ref": "#/definitions/user_paths/actions/javascript" },
									"if": { "$ref": "#/definitions/user_paths/actions/if" }
								},
								"additionalProperties": false
							}
						}
					},
					"additionalProperties": false
				},
				"request": {
					"$id":"#/definitions/user_paths/actions/request",
					"title":"Action: HTTP/s Request",
					"type":"object",
					"required": ["url"],
					"properties":{
						"url": { "$ref": "#/definitions/common/text" },
						"server": { "$ref": "#/definitions/common/text" },
						"method": {
							"type": "string",
							"enum": [
								"GET","POST","HEAD","PUT","DELETE","OPTIONS","TRACE"
							]
						},
						"headers": {
							"type": "array",
							"items": {
		            "type": "object",
		            "properties": {
		              "name": {
		                "type": "string"
		              },
		              "value": {
		                "type": "string"
		              }
		            }
		          }
						},
						"sla_profile": { "$ref": "#/definitions/common/text" },
						"body": { "$ref": "#/definitions/common/text" },
						"extractors": {
							"type": "array",
							"items": { "$ref": "#/definitions/user_paths/extractor" }
						}
					}
				},
				"delay": {
					"$id":"#/definitions/user_paths/actions/delay",
					"title":"Action: Delay",
					"type":"string",
					"allOf": [
						{ "$ref": "#/definitions/common/text" }
					]
				},
				"think_time": {
					"$id":"#/definitions/user_paths/actions/think_time",
					"title":"Action: Think Time",
					"type":"string",
					"allOf": [
						{ "$ref": "#/definitions/common/text" }
					]
				},
				"javascript": {
					"$id":"#/definitions/user_paths/actions/javascript",
					"title":"Action: Javascript",
					"type": "object",
					"xrequired": ["name","script"],
					"properties": {
						"name": { "$ref": "#/definitions/common/text" },
						"description": { "$ref": "#/definitions/common/text" },
						"script": { "$ref": "#/definitions/common/text" }
					}
				},
				"if": {
					"$id":"#/definitions/user_paths/actions/if",
					"title":"Action: If",
					"type": "object",
					"xrequired": ["conditions","then"],
					"properties": {
						"name": { "$ref": "#/definitions/common/text" },
						"description": { "$ref": "#/definitions/common/text" },
						"conditions": {
							"type": "array",
							"xcomments": "like GWBSR said: 'aint gonna do it', at least not this commit",
							"items": { "$ref": "#/definitions/common/text" }
						},
						"match": {
							"type": "string",
							"enum": ["any","all"],
							"default": "any"
						},
						"then": { "$ref": "#/definitions/user_paths/container" },
						"else": { "$ref": "#/definitions/user_paths/container" }
					}
				}

			},
			"extractor": {
				"type": "object",
				"xrequired": ["name"],
				"properties": {
					"name":{ "$ref": "#/definitions/common/text" },
					"from": {
						"type": "string",
						"default": "body",
						"enum": [
							"header","body","both"
						]
					},
					"xpath":{ "$ref": "#/definitions/common/text" },
					"jsonpath":{ "$ref": "#/definitions/common/text" },
					"regexp":{ "$ref": "#/definitions/common/text" },
					"match_number": {
						"type": "integer",
						"default": 1
					},
					"template":{ "$ref": "#/definitions/common/text" },
					"decode": {
						"type": "string",
						"enum": [
							"html","url"
						]
					},
					"extract_once": {
						"type": "boolean",
						"default": false
					},
					"default": {
						"type": "string",
						"default": ""
					},
					"throw_assertion_error": {
						"type": "boolean",
						"default": true
					}
				}
			}
		}
	}
}
