{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "description": "Parameters to instantiate ERP5",
  "type": "object",
  "additionalProperties": false,
  "definitions": {
    "routing-rule-list": {
      "description": "Maps the path received in requests to given zope path. Rules are applied in the order they are given, after 'internal-path' from 'frontend' parameter. This also supports legacy frontends, using Rapid CDN with \"zope\" type.",
      "type": "array",
      "default": [
        [
          "/",
          "/"
        ]
      ],
      "items": {
        "type": "array",
        "minItems": 2,
        "maxItems": 2,
        "items": [
          {
            "title": "External path",
            "description": "Path as received from the outside world, based on VirtualHostRoot element.",
            "type": "string"
          },
          {
            "title": "Internal path",
            "description": "Zope path, based on Zope root object, the external path should correspond to. '%(site-id)s' is replaced by the site-id value, and '%%' replaced by '%'.",
            "type": "string"
          }
        ]
      }
    },
    "tcpv4port": {
      "$ref": "./schemas-definitions.json#/tcpv4port"
    }
  },
  "properties": {
    "sla-dict": {
      "description": "Where to request instances. Each key is a query string for criterions (e.g. \"computer_guid=foo\"), and each value is a list of partition references (notes: Zope partitions reference must be prefixed with \"zope-\", frontends must be prefixed with \"frontend-\").",
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "string"
        },
        "uniqueItems": true
      },
      "type": "object"
    },
    "site-id": {
      "description": "ERP5Site object's id. An empty value disables automatic site creation.",
      "default": "erp5",
      "type": "string"
    },
    "bt5": {
      "description": "A space-separated list of Business Templates to install at automatic site creation (e.g. \"erp5_full_text_mroonga_catalog erp5_base\"). By default, all configurators are installed.",
      "type": "string"
    },
    "id-store-interval": {
      "description": "Set Store Interval of default SQL Non Continuous Increasing Id Generator at automatic site creation. If unset, the value from the erp5_core Business Template is not touched.",
      "type": "integer"
    },
    "timezone": {
      "description": "Zope's timezone. Possible values are determined by host's libc, and typically come from a separate package (tzdata, ...)",
      "default": "UTC",
      "type": "string"
    },
    "deadlock-debugger-password": {
      "description": "Password for /manage_debug_threads",
      "type": "string"
    },
    "inituser-login": {
      "description": "Login of the initial/rescue user",
      "default": "zope",
      "type": "string"
    },
    "inituser-password": {
      "description": "Password of the initial/rescue user",
      "type": "string"
    },
    "developer-list": {
      "description": "List of logins which should get the Developer role (required to modify portal_components' content), defaulting to inituser-login's value",
      "items": {
        "pattern": "^\\S+$",
        "type": "string"
      },
      "uniqueItems": true,
      "type": "array"
    },
    "activity-timeout": {
      "description": "How long a CMFActivity-initiated transaction may last, in seconds",
      "default": null,
      "type": [
        "number",
        "null"
      ]
    },
    "publisher-timeout": {
      "description": "How long a publisher-initiated transaction may last, in seconds",
      "default": 300,
      "type": [
        "number",
        "null"
      ]
    },
    "with-max-rlimit-nofile": {
      "description": "Set open file descriptors soft limit to hard limit",
      "type": "boolean"
    },
    "python-hash-seed": {
      "description": "Sets the value of `PYTHONHASHSEED` environment variable for zope processes and test runner. If not provided, zope processes use python default (`0` for python2, `random` for python3) and test runner choose a different `PYTHONHASHSEED` for each execution.",
      "oneOf": [
        {
          "type": "number"
        },
        {
          "const": "random",
          "type": "string"
        }
      ]
    },
    "family-override": {
      "description": "Family-wide options, possibly overriding global options",
      "default": {},
      "patternProperties": {
        "^[a-zA-Z0-9_-]+$": {
          "default": {},
          "properties": {
            "webdav": {
              "description": "Serve webdav queries, implies timerserver-interval=0 (disabled)",
              "default": false,
              "type": "boolean"
            },
            "activity-timeout": {
              "description": "Override global activity timeout",
              "type": [
                "number",
                "null"
              ]
            },
            "publisher-timeout": {
              "description": "Override global publisher timeout",
              "type": [
                "number",
                "null"
              ]
            }
          },
          "type": "object"
        }
      },
      "type": "object"
    },
    "hostalias-dict": {
      "description": "Hostname-to-domain-name mapping",
      "default": {},
      "additionalProperties": {
        "description": "A hostname to which current entry will resolve",
        "type": "string"
      },
      "type": "object"
    },
    "hosts-dict": {
      "description": "Host entries to be used in addition to and/or overriding auto-generated ones (erp5-catalog-0, erp5-memcached-persistent, erp5-memcached-volatile and erp5-smtp)",
      "patternProperties": {
        ".*": {
          "description": "An IP or domain name to which current entry will resolve",
          "type": "string"
        }
      },
      "type": "object"
    },
    "frontend": {
      "description": "Frontend shared instances requests parameters. When this parameter is unset, the system defaults to requesting a frontend, but only when exactly one family exists in `zope-partition-dict`. For more complex zope partition layout, the frontend layout also have to be explicitly defined.",
      "default": {
        "default": {}
      },
      "patternProperties": {
        "^[a-zA-Z0-9_-]+$": {
          "required": [
            "zope-family"
          ],
          "properties": {
            "zope-family": {
              "description": "The zope family to which the requests will be routed.",
              "type": "string"
            },
            "internal-path": {
              "description": "Internal path from the backend. `%(site-id)s` is substituted by the site id.",
              "type": "string",
              "default": "/%(site-id)s"
            },
            "software-url": {
              "description": "Software URL of the frontend shared instance.",
              "type": "string",
              "format": "uri",
              "default": "http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg"
            },
            "software-type": {
              "description": "Software type of the frontend shared instance.",
              "type": "string"
            },
            "instance-parameters": {
              "description": "Instance parameters for the frontend shared instance.",
              "$ref": "../rapid-cdn/instance-slave-input-schema.json"
            }
          },
          "type": "object"
        }
      },
      "type": "object"
    },
    "zope-partition-dict": {
      "description": "Zope layout definition",
      "default": {
        "1": {}
      },
      "patternProperties": {
        "^[a-zA-Z0-9_-]+$": {
          "additionalProperties": false,
          "properties": {
            "family": {
              "description": "The family this partition is part of. For example: 'public', 'admin', 'backoffice', 'web-service'... Each family gets its own balancer entry. It has no special meaning for the system.",
              "default": "default",
              "type": "string",
              "pattern": "^[a-zA-Z0-9_-]+$"
            },
            "instance-count": {
              "description": "Number of Zopes to setup on this partition",
              "default": 1,
              "type": "integer"
            },
            "thread-amount": {
              "description": "Number of worker threads for each created Zope process",
              "default": 4,
              "type": "integer"
            },
            "timerserver-interval": {
              "description": "Timerserver tick period, in seconds, or 0 to disable",
              "default": 1,
              "type": "number"
            },
            "private-dev-shm": {
              "description": "Size of private /dev/shm for wendelin.core. If sysctl kernel.unprivileged_userns_clone exists, it must be set to 1.",
              "type": "string"
            },
            "ssl-authentication": {
              "title": "Enable SSL Client authentication on this zope instance.",
              "description": "If set to true, will set SSL Client verification to required on apache VirtualHost which allow to access this zope instance.",
              "type": "boolean",
              "default": false
            },
            "longrequest-logger-interval": {
              "description": "Period, in seconds, with which LongRequestLogger polls worker thread stack traces, or -1 to disable",
              "default": -1,
              "type": "integer"
            },
            "longrequest-logger-timeout": {
              "description": "Transaction duration after which LongRequestLogger will start logging its stack trace, in seconds",
              "default": 1,
              "type": "integer"
            },
            "large-file-threshold": {
              "description": "Requests bigger than this size get saved into a temporary file instead of being read completely into memory, in bytes",
              "default": "10MB",
              "type": "string"
            },
            "port-base": {
              "allOf": [
                {
                  "$ref": "#/definitions/tcpv4port"
                },
                {
                  "description": "Start allocating ports at this value. Useful if one needs to make several partitions share the same port range (ie, several partitions bound to a single address)",
                  "default": 2200
                }
              ]
            }
          },
          "type": "object"
        }
      },
      "type": "object"
    },
    "kumofs": {
      "description": "Persistent memcached service",
      "allOf": [
        {
          "$ref": "./instance-kumofs-schema.json"
        },
        {
          "properties": {
            "tcpv4-port": {
              "default": 2000
            }
          }
        }
      ],
      "type": "object"
    },
    "memcached": {
      "description": "Volatile memcached service",
      "allOf": [
        {
          "$ref": "./instance-kumofs-schema.json"
        },
        {
          "properties": {
            "tcpv4-port": {
              "default": 2010
            }
          }
        }
      ],
      "type": "object"
    },
    "cloudooo-url-list": {
      "description": "Format conversion service URLs",
      "type": "array",
      "items": {
        "pattern": "^https?://",
        "type": "string",
        "format": "uri"
      }
    },
    "cloudooo-retry-count": {
      "description": "Define retry count for cloudooo in network error case in test",
      "type": "integer",
      "default": 2
    },
    "smtp": {
      "description": "Mail queuing and relay service",
      "allOf": [
        {
          "$ref": "./instance-smtp-schema.json"
        },
        {
          "properties": {
            "tcpv4-port": {
              "default": 2010
            }
          }
        }
      ],
      "type": "object"
    },
    "mariadb": {
      "description": "Relational database service",
      "allOf": [
        {
          "$ref": "./instance-mariadb-schema.json"
        },
        {
          "properties": {
            "tcpv4-port": {
              "default": 2099
            }
          }
        }
      ],
      "type": "object"
    },
    "zodb-zeo": {
      "description": "Common settings ZEO servers",
      "additionalProperties": false,
      "properties": {
        "tcpv4-port": {
          "allOf": [
            {
              "$ref": "#/definitions/tcpv4port"
            },
            {
              "description": "Start allocating ports at this value, going upward"
            }
          ]
        },
        "backup-periodicity": {
          "description": "When to backup, specified in the same format as for systemd.time(7) calendar events (years & seconds not supported, DoW & DoM can not be combined). Enter 'never' to disable backups.",
          "default": "daily",
          "type": "string"
        },
        "tidstorage-repozo-path": {
          "description": "Directory for backup timestamp and tidstorage status files.",
          "default": "~/srv/backup/tidstorage",
          "type": "string"
        }
      },
      "type": "object"
    },
    "zodb": {
      "description": "Zope Object DataBase mountpoints. See https://github.com/zopefoundation/ZODB/blob/4/src/ZODB/component.xml for extra options.",
      "items": {
        "required": [
          "type"
        ],
        "properties": {
          "name": {
            "description": "Database name",
            "default": "main",
            "type": "string"
          },
          "mount-point": {
            "description": "Mount point",
            "default": "/",
            "type": "string"
          },
          "storage-dict": {
            "description": "Storage configuration. For NEO, 'logfile' is automatically set (see https://lab.nexedi.com/nexedi/neoppod/blob/master/neo/client/component.xml for other settings).",
            "properties": {
              "ssl": {
                "description": "For external NEO. Pass false if you want to disable SSL or pass custom values for ca/cert/key.",
                "default": true,
                "type": "boolean"
              }
            },
            "patternProperties": {
              ".!$": {
                "$ref": "#/properties/zodb/items/patternProperties/.!$"
              }
            },
            "additionalProperties": {
              "$ref": "#/properties/zodb/items/additionalProperties"
            },
            "type": "object"
          },
          "type": true,
          "server": true
        },
        "oneOf": [
          {
            "title": "zeo",
            "properties": {
              "type": {
                "description": "Storage type",
                "const": "zeo"
              },
              "server": {
                "description": "Instantiate a server. If missing, 'storage-dict' must contain the necessary properties to mount the ZODB. The partition reference is 'zodb'.",
                "$ref": "./instance-zeo-schema.json"
              }
            }
          },
          {
            "title": "neo",
            "properties": {
              "type": {
                "description": "Storage type",
                "const": "neo"
              },
              "server": {
                "description": "Instantiate a server. If missing, 'storage-dict' must contain the necessary properties to mount the ZODB. Partitions references are 'neo-0', 'neo-1', ...",
                "$ref": "../neoppod/instance-neo-input-schema.json#/definitions/neo-cluster"
              }
            }
          }
        ],
        "patternProperties": {
          ".!$": {
            "description": "Override with the value of the first item whose zope id matches against the pattern.",
            "items": {
              "items": [
                {
                  "description": "Override pattern (Python regular expression).",
                  "type": "string"
                },
                {
                  "description": "Override value (parameter for matching nodes).",
                  "type": [
                    "integer",
                    "string"
                  ]
                }
              ],
              "type": "array"
            },
            "type": "array"
          }
        },
        "additionalProperties": {
          "type": [
            "integer",
            "string"
          ]
        },
        "type": "object"
      },
      "type": "array"
    },
    "jupyter": {
      "description": "Jupyter subinstance parameters",
      "additionalProperties": false,
      "properties": {
        "enable": {
          "description": "Whether to enable creation of associated Jupyter subinstance",
          "default": false,
          "type": "boolean"
        },
        "zope-family": {
          "description": "Zope family to connect Jupyter to by default",
          "default": "<first instantiated Zope family>",
          "type": "string"
        }
      },
      "type": "object"
    },
    "wcfs": {
      "description": "Parameters for wendelin.core filesystem",
      "additionalProperties": false,
      "properties": {
        "enable": {
          "description": "Whether to enable WCFS filesystem and use it to access ZBigArray/ZBigFile data. In WCFS mode wendelin.core clients (Zope/ERP5 processes) share in-RAM cache for in-ZODB data without duplicating it for every client. This cache sharing does not affect correctness as isolation property is continued to be provided to every client.",
          "default": false,
          "type": "boolean"
        }
      }
    },
    "wendelin-core-zblk-fmt": {
      "description": "In wendelin.core there are 2 formats for storing data, so called ZBlk0 and ZBlk1. See https://lab.nexedi.com/nexedi/wendelin.core/blob/2e5e1d3d/bigfile/file_zodb.py#L19 for more details.",
      "default": "",
      "type": "string"
    },
    "caucase": {
      "description": "Caucase certificate authority parameters",
      "allOf": [
        {
          "properties": {
            "url": {
              "title": "Caucase URL",
              "description": "URL of existing caucase instance to use. If empty, caucase instances will be deployed inside partitions.",
              "default": "",
              "type": "string",
              "format": "uri"
            }
          }
        },
        {
          "$ref": "../caucase/instance-caucase-input-schema.json"
        }
      ],
      "type": "object"
    },
    "test-runner": {
      "description": "Test runner parameters.",
      "additionalProperties": false,
      "properties": {
        "enabled": {
          "description": "Generate helper scripts to run test suite.",
          "default": true,
          "type": "boolean"
        },
        "coverage": {
          "type": "object",
          "title": "Coverage",
          "description": "Coverage configuration",
          "additionalProperties": false,
          "properties": {
            "enabled": {
              "description": "Collect python coverage data during test run.",
              "default": false,
              "type": "boolean"
            },
            "include": {
              "description": "File name patterns to include in coverage data, relative to software buildout's directory. Default to all repositories defined in software by ${erp5_repository_list:repository_id_list}.",
              "type": "array",
              "items": {
                "type": "string"
              },
              "examples": [
                [
                  "parts/erp5/*",
                  "parts/custom-repository/*",
                  "develop-eggs/custom-egg/*"
                ]
              ]
            },
            "branch": {
              "description": "Enable branch coverage",
              "type": "boolean",
              "default": false
            },
            "upload-url": {
              "description": "URL to upload coverage data. This is interpreted as a RFC 6570 URI Template, with the following parameters: test_name, test_result_id and test_result_revision. The request will be a PUT request with the coverage file content as body, suitable for WebDav servers. If the URL contains user and password, they will be used to attempt authentication using Digest and Basic authentication schemes.",
              "type": "string",
              "format": "uri",
              "examples": [
                "https://user:password@example.com/{test_result_id}/{test_name}.coverage.sqlite3"
              ]
            }
          }
        },
        "node-count": {
          "description": "Number of tests this instance can execute in parallel. This must be at least equal to the number of nodes configured on testnode running the test",
          "default": 3,
          "type": "integer"
        },
        "extra-database-count": {
          "description": "Number of extra databases this instance tests will need.",
          "default": 3,
          "type": "integer"
        },
        "selenium": {
          "default": {
            "target": "firefox"
          },
          "examples": [
            {
              "target": "selenium-server",
              "server-url": "https://selenium.example.com",
              "desired-capabilities": {
                "browserName": "firefox",
                "version": "68.0.2esr",
                "acceptInsecureCerts": true
              }
            },
            {
              "target": "selenium-server",
              "server-url": "https://selenium.example.com",
              "desired-capabilities": {
                "browserName": "chrome",
                "version": "91.0.4472.101"
              }
            }
          ],
          "oneOf": [
            {
              "type": "object",
              "title": "Selenium Server",
              "description": "Configuration for Selenium server",
              "additionalProperties": false,
              "required": [
                "desired-capabilities",
                "server-url",
                "target"
              ],
              "properties": {
                "target": {
                  "description": "Target system",
                  "type": "string",
                  "const": "selenium-server",
                  "default": "selenium-server"
                },
                "server-url": {
                  "description": "URL of the selenium server",
                  "type": "string",
                  "format": "uri"
                },
                "verify-server-certificate": {
                  "description": "Verify the SSL/TLS certificate of the selenium server when using HTTPS",
                  "type": "boolean",
                  "default": true
                },
                "server-ca-certificate": {
                  "description": "PEM encoded bundle of CA certificates to verify the SSL/TLS certificate of the selenium server when using HTTPS",
                  "type": "string",
                  "default": "Root certificates from http://certifi.io/en/latest/"
                },
                "desired-capabilities": {
                  "description": "Desired browser capabilities",
                  "required": [
                    "browserName"
                  ],
                  "type": "object",
                  "properties": {
                    "browserName": {
                      "description": "Name of the browser being used",
                      "type": "string",
                      "examples": [
                        "firefox",
                        "chrome",
                        "safari"
                      ]
                    },
                    "version": {
                      "description": "The browser version",
                      "type": "string"
                    }
                  }
                }
              }
            },
            {
              "type": "object",
              "title": "Firefox",
              "description": "Configuration for using firefox running as a sub-process",
              "additionalProperties": false,
              "properties": {
                "target": {
                  "description": "Target system",
                  "const": "firefox",
                  "type": "string",
                  "default": "firefox"
                }
              }
            }
          ]
        },
        "random-activity-priority": {
          "type": "string",
          "title": "Random Activity Priority",
          "description": "Control `random_activity_priority` argument of test runner. Can be set to an empty string to automatically generate a seed for each test."
        }
      },
      "type": "object"
    },
    "balancer": {
      "description": "HTTP(S) load balancer proxy parameters",
      "properties": {
        "path-routing-list": {
          "$ref": "#/definitions/routing-rule-list",
          "title": "Global path routing rules"
        },
        "family-path-routing-dict": {
          "type": "object",
          "title": "Family-specific path routing rules",
          "description": "Applied, only for the eponymous family, before global path routing rules.",
          "patternProperties": {
            ".+": {
              "$ref": "#/definitions/routing-rule-list"
            }
          }
        },
        "ssl": {
          "description": "HTTPS certificate generation parameters",
          "additionalProperties": false,
          "properties": {
            "frontend-caucase-url-list": {
              "title": "Frontend Caucase URL List",
              "description": "List of URLs of caucase service of frontend groups to authenticate access from them.",
              "type": "array",
              "items": {
                "type": "string",
                "format": "uri"
              },
              "uniqueItems": true
            },
            "csr": {
              "title": "csr",
              "description": "PEM-encoded certificate signature request to request server certificate with.",
              "type": "string"
            },
            "max-crl-update-delay": {
              "title": "Periodicity of CRL update (days)",
              "description": "CRL will be updated from caucase at least this often.",
              "type": "number",
              "default": 1.0
            }
          },
          "type": "object"
        }
      },
      "type": "object"
    }
  }
}
