{ "$schema": "http://json-schema.org/draft-07/schema", "id": "https://choria.io/schemas/choria/machine/v1/manifest.json", "description": "Choria Autonomous Agent manifest", "type":"object", "required":["name","version","initial_state","transitions","watchers"], "definitions": { "ForeignMachineState": { "type": "object", "required": ["machine_name", "state"], "properties": { "machine_name": { "description": "Name of a foreign autonomous agent", "$ref":"#/definitions/GenericName" }, "state": { "description": "The name of the remote state", "$ref":"#/definitions/GenericName" } } }, "GoDuration": { "type":"string", "pattern": "^\\d+[hms]$" }, "GenericName": { "type":"string", "pattern":"^[a-zA-Z][a-zA-Z0-9_-]+$" }, "EnvironmentVariable": { "type":"string", "description": "Environment variable as accepted by Go exec package", "pattern": "^[a-zA-Z_]+[a-zA-Z0-9_]*=.+" }, "MachineSubscription": { "type": "object", "required": ["machine_name", "event"], "properties": { "machine_name": { "description": "The name of the foreign machine to subscribe to", "$ref":"#/definitions/GenericName" }, "event": { "description": "The name of the event to subscribe to", "$ref":"#/definitions/GenericName" } } }, "Transition": { "type":"object", "required": ["name", "from", "destination"], "additionalItems": false, "description": "A valid transition of the Finite State Machine", "properties": { "name": { "description": "A unique name for the transition event", "$ref":"#/definitions/GenericName" }, "from": { "description": "The names of states that this transition is valid from", "type":"array", "items": { "$ref":"#/definitions/GenericName" } }, "destination": { "description": "The name of the state to transition to when this event fires", "$ref":"#/definitions/GenericName" }, "description": { "description": "A human friendly description of the purpose of this transition", "type": "string" }, "subscribe": { "description": "Subscribe to events from foreign autonomous agents", "$ref": "#/definitions/MachineSubscription" } } }, "WatcherBase": { "type":"object", "required": ["name", "type"], "additionalItems": false, "properties": { "name": { "description": "The name of the watcher", "$ref":"#/definitions/GenericName" }, "state_match": { "description": "State names where this watcher will be active", "type":"array", "items": { "$ref":"#/definitions/GenericName" } }, "foreign_state_required": { "description": "Foreign state that must match for this watcher to be active", "$ref": "#/definitions/ForeignMachineState" }, "fail_transition": { "description": "When this watcher fails the machine will receive this transition event", "$ref":"#/definitions/GenericName" }, "success_transition": { "description": "When this watcher succeeds the machine will receive this transition event", "$ref":"#/definitions/GenericName" }, "interval": { "description": "How often this watcher will be run when in any of the valid states", "$ref":"#/definitions/GoDuration" }, "announce_interval": { "description": "How often the internal state of the watcher will be announced as events", "$ref":"#/definitions/GoDuration" } } }, "WatcherArchiveProperties": { "type": "object", "description": "Archive watcher properties", "required": ["source", "target"], "properties": { "checksum": { "description": "A sha256 hex string of the archive being downloaded", "type": "string", "pattern": "^[a-fA-F0-9]{64}$" }, "creates": { "description": "A subdirectory that the tarball will create on untar", "type": "string" }, "governor": { "description": "The optional name of a governor to use for concurrency control", "type": "string" }, "governor_timeout": { "description": "How long to try accessing the governor", "default": "5m", "$ref": "#/definitions/GoDuration" }, "insecure": { "description": "Skip TLS verification on https downloads", "type": "boolean", "default": false }, "password": { "description": "Password for accessing the source, required when a username is set", "type": "string" }, "source": { "description": "URL to the file being downloaded, only tar.gz format is supported", "type": "string" }, "target": { "description": "The directory where the tarball will be extracted", "type": "string" }, "timeout": { "description": "How long HTTP operations are allowed to take", "default": "10s", "$ref": "#/definitions/GoDuration" }, "username": { "description": "Username to use when downloading, password is required in addition", "type": "string" }, "verify": { "description": "A file in the archive made using sha256 used for verification of files in the archive after extraction and on every interval check", "type": "string" }, "verify_checksum": { "description": "A sha256 hex string of the file specified in verify", "type": "string", "pattern": "^[a-fA-F0-9]{64}$" } } }, "WatcherArchive": { "description": "A watcher that downloads, extracts and, optionally, integrity check and remediate tar.gz files.", "type": "object", "additionalItems": false, "allOf": [ { "type":"object", "required": ["type"], "properties": { "type": { "enum": ["archive"] } } }, {"$ref":"#/definitions/WatcherBase"}, { "type":"object", "required": ["properties"], "properties": { "properties": { "$ref":"#/definitions/WatcherArchiveProperties" } } } ] }, "WatcherExpressionProperties": { "type": "object", "description": "Expression watcher properties", "properties": { "fail_when": { "description": "Expression that when true causes the watcher to fail", "type": "string" }, "success_when": { "description": "Expression that when true causes the watcher to succeed", "type": "string" } } }, "WatcherExpression": { "description": "A watcher that evaluates expressions to determine success or failure states", "type": "object", "additionalItems": false, "allOf": [ { "type":"object", "required": ["type"], "properties": { "type": { "enum": ["expression"] } } }, {"$ref":"#/definitions/WatcherBase"}, { "type":"object", "required": ["properties"], "properties": { "properties": { "$ref":"#/definitions/WatcherExpressionProperties" } } } ] }, "WatcherExecProperties": { "type":"object", "description": "Exec watcher properties", "required": ["command"], "properties": { "command": { "type": "string", "description": "The path to a command to run relative to the machine root" }, "environment": { "description": "List of environment variables to pass to the executable in the form VAR=VALUE", "default": [], "type":"array", "items": { "$ref":"#/definitions/EnvironmentVariable" } }, "governor": { "description": "Limit concurrent executions of the command using a named Choria Governor", "type": "string" }, "governor_timeout": { "description": "How long to wait for a spot on the Governor prior to giving up and firing fail_transition", "type": "string", "default": "5m", "$ref":"#/definitions/GoDuration" }, "parse_as_data": { "description": "Indicates that the command returns JSON data that should be parsed as Machine data and stored", "type": "boolean", "default": false }, "suppress_success_announce": { "description": "Disable publishing announcements on every successful execution, still does regular timed ones if configured and failed ones", "default": false, "type":"boolean" }, "timeout": { "description": "How long the commands are allowed to run", "default": "10s", "$ref":"#/definitions/GoDuration" }, "disown": { "description": "Disown the process so it will survive after Choria stops", "type": "boolean", "default": false } } }, "WatcherExec": { "description": "A watcher that executes a command regularly", "type": "object", "additionalItems": false, "allOf": [ { "type":"object", "required": ["properties"], "properties": { "properties": { "$ref":"#/definitions/WatcherExecProperties" } } }, {"$ref":"#/definitions/WatcherBase"}, { "type":"object", "required": ["type"], "properties": { "type": { "enum": ["exec"] } } } ] }, "WatcherFileProperties": { "type":"object", "description": "File watcher properties", "required": ["path"], "properties": { "path": { "type": "string", "description": "The path to a file to watch relative to the watcher manifest directory" }, "gather_initial_state": { "type":"boolean", "description": "Gathers the initial file mode, stats etc for regular announces but only perform first watch after interval" }, "contents": { "type": "string", "description": "Specific content to place into the file, supports template parsing and data lookup" }, "owner": { "type": "string", "description": "What should own the file when managing content" }, "group": { "type": "string", "description": "What group should own the file when managing content" }, "mode": { "type": "string", "description": "The file mode to apply when managing content", "pattern": "^0[0-7]{3}$" } } }, "WatcherFile": { "description": "A watcher that observes the state of a file regularly", "type": "object", "additionalItems": false, "allOf": [ { "type":"object", "required": ["type"], "properties": { "type": { "enum": ["file"] } } }, {"$ref":"#/definitions/WatcherBase"}, { "type":"object", "required": ["properties"], "properties": { "properties": { "$ref":"#/definitions/WatcherFileProperties" } } } ] }, "WatcherHttpSwitchProperties": { "type": "object", "description": "HTTP Switch watcher properties", "properties": { "on_when": { "description": "When the machine is in any of these states the button will be report as on", "type": "array", "items": { "$ref": "#/definitions/GenericName" } }, "off_when": { "description": "When the machine is in any of these states the button will be report as off", "type": "array", "items": { "$ref": "#/definitions/GenericName" } }, "disable_when": { "description": "When the machine is in any of these states the button will stop functioning", "type": "array", "items": { "$ref": "#/definitions/GenericName" } }, "annotations": { "description": "Additional annotations to apply to the watcher", "type": "object", "propertyNames": { "pattern": "^[a-zA-Z_-]+$", "type": "string" } } } }, "WatcherHttpSwitch": { "description": "A watcher that provides HTTP-based switch functionality based on machine state", "type": "object", "additionalItems": false, "allOf": [ { "type":"object", "required": ["type"], "properties": { "type": { "enum": ["httpswitch"] } } }, {"$ref":"#/definitions/WatcherBase"}, { "type":"object", "required": ["properties"], "properties": { "properties": { "$ref":"#/definitions/WatcherHttpSwitchProperties" } } } ] }, "WatcherKVProperties": { "type": "object", "default": "KV watcher properties", "required": ["bucket"], "properties": { "bucket": { "description": "The Bucket name that holds the data", "type": "string", "pattern": "^[a-zA-Z0-9_-]+$" }, "key": { "description": "The key to watch for changes", "type": "string", "pattern": "\\A[-/_a-zA-Z0-9]+\\z" }, "mode": { "description": "The method used for watching the values, must be poll for bucket watch", "type": "string", "default": "poll", "enum": ["poll","watch"] }, "bucket_prefix": { "description": "When storing data prefix the data keys with the Bucket name", "type": "boolean", "default": true }, "on_successful_get": { "description": "When data was received trigger this event", "type": "string" }, "on_matching_update": { "description": "Event to trigger when data did not change since last get", "type": "string" }, "republish_trigger": { "description": "Sets up a listener for a Core NATS trigger event indicating the KV was updated", "type": "string" }, "hiera_config": { "description": "Enables parsing received data as a Choria Hierarchical Data Structure", "type": "boolean", "default": false } } }, "WatcherKV": { "description": "A watcher that observes the state of a Choria Key-Value store Bucket or Key", "type": "object", "additionalItems": false, "allOf": [ { "type":"object", "required": ["type"], "properties": { "type": { "enum": ["kv"] } } }, {"$ref":"#/definitions/WatcherBase"}, { "type":"object", "required": ["properties"], "properties": { "properties": { "$ref":"#/definitions/WatcherKVProperties" } } } ] }, "WatcherMetricProperties": { "type":"object", "description": "Metric watcher properties", "required": ["command", "interval"], "properties": { "command": { "description": "The path to the command to run to retrieve the metric", "type": "string" }, "interval": { "description": "The duration for how frequently to gather metrics", "$ref": "#/definitions/GoDuration" }, "labels": { "description": "Key=value pairs of strings of additional labels to add to gathered metrics", "type": "object", "propertyNames": { "pattern": "^[a-zA-Z_-]+$", "type": "string" } }, "skip_prometheus": { "description": "Disables publishing metrics to Prometheus", "type": "boolean", "default": false }, "store": { "description": "Stores the metric to the Machine Data", "type": "boolean", "default": false }, "http": { "description": "Expose metrics over the HTTP port", "type": "boolean", "default": false }, "graphite_host": { "description": "Graphite host to send metrics to", "type": "string" }, "graphite_port": { "description": "Graphite port to send metrics to", "type": "string" }, "graphite_prefix": { "description": "Prefix to apply to Graphite metrics", "type": "string" } } }, "WatcherMetric": { "description": "A watcher that periodically runs a command and expose metrics found to Prometheus", "type":"object", "additionalItems": false, "allOf": [ { "type":"object", "required":["properties"], "properties": { "properties": { "$ref":"#/definitions/WatcherMetricProperties" } } }, {"$ref":"#/definitions/WatcherBase"}, { "type":"object", "required": ["type"], "properties": { "type": { "enum": ["schedule"] } } } ] }, "WatcherNagiosProperties": { "type": "object", "description": "Nagios watcher properties", "required": ["plugin"], "properties": { "annotations": { "type": "object", "description": "Map of strings presented as additional annotations per check", "propertyNames": { "pattern": "^[a-zA-Z_-]+$", "type": "string" } }, "builtin": { "type": "string", "description": "Execute an internal plugin", "enum": ["goss", "heartbeat", "choria_status"] }, "plugin": { "type": "string", "description": "The Nagios plugin to run including it's arguments" }, "timeout": { "description": "How long the commands are allowed to run", "default": "10s", "$ref":"#/definitions/GoDuration" }, "gossfile": { "description": "For the goss builtin, a check specific YAML file", "type": "string" }, "last_message": { "description": "For the choria_status builtin how long ago the last RPC message should have been received, specified in go duration string format", "$ref": "#/definitions/GoDuration" }, "pubcert_expire": { "description": "For the choria_status builtin how long till the certificate expires, specified in go duration string format", "$ref": "#/definitions/GoDuration" }, "token_expire": { "description": "For the choria_status builtin how long till the JWT token expires, specified in go duration string format", "$ref": "#/definitions/GoDuration" } } }, "WatcherNagios": { "description": "A watcher that executes Nagios plugins", "type": "object", "additionalItems": false, "allOf": [ { "type":"object", "required": ["properties"], "properties": { "properties": { "$ref":"#/definitions/WatcherNagiosProperties" } } }, {"$ref":"#/definitions/WatcherBase"}, { "type":"object", "required": ["type"], "properties": { "type": { "enum": ["nagios"] } } } ] }, "WatcherPluginsProperties": { "type": "object", "description": "Plugin watcher properties", "required": ["data_item", "manager_machine_prefix"], "properties": { "data_item": { "description": "The data item key to get ManagedPlugin from, typically sourced from Key-Value store", "type": "string" }, "purge_unknown": { "description": "Will remove plugins not declared in data_item", "type": "boolean", "default": false }, "plugin_manage_interval": { "description": "The interval that created management machines will use to manage their archives", "$ref": "#/definitions/GoDuration" }, "public_key": { "description": "The optional ed25519 public key used to sign the specification, when set the specification received will be validated and any invalid specification will be discarded", "type": "string" }, "plugins_directory": { "description": "Sets the directory where plugins are being deployed into, when empty defaults to plugins directory like /etc/choria/machines", "type": "string" }, "manager_machine_prefix": { "description": "The prefix used in constructing names for the management machines", "type": "string" } } }, "WatcherPlugins": { "description": "A watcher that manages plugin deployment and lifecycle", "type": "object", "additionalItems": false, "allOf": [ { "type":"object", "required": ["type"], "properties": { "type": { "enum": ["plugins"] } } }, {"$ref":"#/definitions/WatcherBase"}, { "type":"object", "required": ["properties"], "properties": { "properties": { "$ref":"#/definitions/WatcherPluginsProperties" } } } ] }, "WatcherScheduleProperties": { "type":"object", "description": "Schedule watcher properties", "required": ["duration", "schedules"], "properties": { "start_splay": { "description": "Sleep a random period between 0 and this duration before firing the success_transition. Use this to spread a fleet of schedulers out naturally.", "$ref":"#/definitions/GoDuration" }, "duration": { "description": "How long the scheduler should stay in the success state once triggered", "$ref":"#/definitions/GoDuration" }, "schedules": { "description": "Cron like schedules for when the scheduler trigger success states", "type":"array", "items": { "type":"string" } }, "skip_trigger_on_reenter": { "description": "Skips triggering success when changing between 2 states that are both active in the scheduler", "type": "boolean", "default": false } } }, "WatcherSchedule": { "description": "A watcher that triggers transitions based on a set of cron like schedules", "type":"object", "additionalItems": false, "allOf": [ { "type":"object", "required":["properties"], "properties": { "properties": { "$ref":"#/definitions/WatcherScheduleProperties" } } }, {"$ref":"#/definitions/WatcherBase"}, { "type":"object", "required": ["type"], "properties": { "type": { "enum": ["schedule"] } } } ] }, "WatcherTimerProperties": { "type":"object", "description": "Timer watcher properties", "required": ["timer"], "properties": { "timer": { "description": "How long the timer should run for", "$ref":"#/definitions/GoDuration" }, "splay": { "description": "Spread the start of the timer randomly", "type": "boolean", "default": false } } }, "WatcherTimer": { "description": "A watcher that starts a time when a machine transitions into a state and emits an event when the timer ends", "type":"object", "additionalItems": false, "allOf": [ { "type":"object", "required":["properties"], "properties": { "properties": { "$ref":"#/definitions/WatcherTimerProperties" } } }, {"$ref":"#/definitions/WatcherBase"}, { "type":"object", "required": ["type"], "properties": { "type": { "enum": ["schedule"] } } } ] } }, "properties": { "name": { "description": "A unique name for this autonomous agent", "$ref":"#/definitions/GenericName" }, "version": { "type":"string", "description": "SemVer compatible version of the autonomous agent", "minLength": 5, "pattern": "^\\d+\\.\\d+\\.\\d+$" }, "initial_state": { "$ref":"#/definitions/GenericName" }, "splay_start": { "type":"integer", "description": "Causes a random delay on start no longer than splay_start seconds", "default":0 }, "transitions": { "type":"array", "description": "A list of events that can be fired for this autonomous agent", "minItems": 1, "items": { "$ref":"#/definitions/Transition" } }, "watchers": { "description": "Watchers to observe the environment in specific states", "type":"array", "minItems": 1, "items": { "anyOf": [ {"$ref": "#/definitions/WatcherArchive"}, {"$ref":"#/definitions/WatcherExec"}, {"$ref":"#/definitions/WatcherExpression"}, {"$ref":"#/definitions/WatcherFile"}, {"$ref":"#/definitions/WatcherHttpSwitch"}, {"$ref":"#/definitions/WatcherKV"}, {"$ref":"#/definitions/WatcherMetric"}, {"$ref":"#/definitions/WatcherNagios"}, {"$ref":"#/definitions/WatcherPlugins"}, {"$ref":"#/definitions/WatcherSchedule"}, {"$ref":"#/definitions/WatcherTimer"} ] } } } }