# Hooks You can define arbitrary number of hooks that subscribe different events. The hook system is modular and different kind of hook types can be enabled. ## Configuration Following configuration keys need to be defined for all hooks: * `events`: which events to subscribe. Needs to be an array. See below for the list of available events. * `type`: what hook class to use. See below for the list of available hook types. ## Events * `node_success`: triggered when configuration is successfully pulled from a node and right before storing the configuration. * `node_fail`: triggered after `retries` amount of failed node pulls. * `post_store`: triggered after node configuration is stored (this is executed only when the configuration has changed). * `nodes_done`: triggered after finished fetching all nodes. ## Hook type: exec The `exec` hook type allows users to run an arbitrary shell command or a binary when triggered. The command is executed on a separate child process either in synchronous or asynchronous fashion. Non-zero exit values cause errors to be logged. STDOUT and STDERR are currently not collected. Command is executed with the following environment: ```text OX_EVENT OX_NODE_NAME OX_NODE_IP OX_NODE_FROM OX_NODE_MSG OX_NODE_GROUP OX_NODE_MODEL OX_JOB_STATUS OX_JOB_TIME OX_REPO_COMMITREF OX_REPO_NAME ``` Exec hook recognizes following configuration keys: * `timeout`: hard timeout for the command execution. SIGTERM will be sent to the child process after the timeout has elapsed. Default: 60 * `async`: influences whether main thread will wait for the command execution. Set this true for long running commands so node pull is not blocked. Default: false * `cmd`: command to run. ### exec hook configuration example ```yaml hooks: name_for_example_hook1: type: exec events: [node_success] cmd: 'echo "Node success $OX_NODE_NAME" >> /tmp/ox_node_success.log' name_for_example_hook2: type: exec events: [post_store, node_fail] cmd: 'echo "Doing long running stuff for $OX_NODE_NAME" >> /tmp/ox_node_stuff.log; sleep 60' async: true timeout: 120 ``` ## Hook type: githubrepo The `githubrepo` hook executes a `git push` to a configured `remote_repo` when the specified event is triggered. Several authentication methods are supported: * Provide a `password` for username + password authentication * Provide both a `publickey` and a `privatekey` for ssh key-based authentication * Don't provide any credentials for ssh-agent authentication The username will be set to the relevant part of the `remote_repo` URI, with a fallback to `git`. It is also possible to provide one by setting the `username` configuration key. For ssh key-based authentication, it is possible to set the environment variable `OXIDIZED_SSH_PASSPHRASE` to a passphrase if the private key requires it. `githubrepo` hook recognizes the following configuration keys: * `remote_repo`: the remote repository to be pushed to. * `username`: username for repository auth. * `password`: password for repository auth. * `publickey`: public key for repository auth. * `privatekey`: private key for repository auth. When using groups, each group must have a unique entry in the `remote_repo` config. ```yaml hooks: push_to_remote: remote_repo: routers: git@git.intranet:oxidized/routers.git switches: git@git.intranet:oxidized/switches.git firewalls: git@git.intranet:oxidized/firewalls.git ``` ### githubrepo hook configuration example Authenticate with a username and a password: ```yaml hooks: push_to_remote: type: githubrepo events: [post_store] remote_repo: git@git.intranet:oxidized/test.git username: user password: pass ``` Authenticate with the username `git` and an ssh key: ```yaml hooks: push_to_remote: type: githubrepo events: [post_store] remote_repo: git@git.intranet:oxidized/test.git publickey: /root/.ssh/id_rsa.pub privatekey: /root/.ssh/id_rsa ``` ## Hook type: awssns The `awssns` hook publishes messages to AWS SNS topics. This allows you to notify other systems of device configuration changes, for example a config orchestration pipeline. Multiple services can subscribe to the same AWS topic. Fields sent in the message: * `event`: Event type (e.g. `node_success`) * `group`: Group name * `model`: Model name (e.g. `eos`) * `node`: Device hostname ### awssns hook configuration example ```yaml hooks: hook_script: type: awssns events: [node_fail,node_success,post_store] region: us-east-1 topic_arn: arn:aws:sns:us-east-1:1234567:oxidized-test-backup_events ``` AWS SNS hook requires the following configuration keys: * `region`: AWS Region name * `topic_arn`: ASN Topic reference Your AWS credentials should be stored in `~/.aws/credentials`. ## Hook type: slackdiff The `slackdiff` hook posts colorized config diffs to a [Slack](http://www.slack.com) channel of your choice. It only triggers for `post_store` events. You will need to manually install the `slack-api` gem on your system: ```shell gem install slack-api ``` ### slackdiff hook configuration example ```yaml hooks: slack: type: slackdiff events: [post_store] token: SLACK_BOT_TOKEN channel: "#network-changes" ``` Optionally you can disable snippets and post a formatted message, for instance linking to a commit in a git repo. Named parameters `%{node}`, `%{group}`, `%{model}` and `%{commitref}` are available. ```yaml hooks: slack: type: slackdiff events: [post_store] token: SLACK_BOT_TOKEN channel: "#network-changes" diff: false message: "%{node} %{group} %{model} updated https://git.intranet/network-changes/commit/%{commitref}" ``` Note the channel name must be in quotes. ## Hook type: ciscosparkdiff The `ciscosparkdiff` hook posts config diffs to a [Cisco Spark](https://www.ciscospark.com/) space of your choice. It only triggers for `post_store` events. You will need to manually install the `cisco_spark` gem on your system (see [cisco_spark-ruby](https://github.com/NGMarmaduke/cisco_spark-ruby): ```shell gem install cisco_spark ``` ### ciscosparkdiff hook configuration example ```yaml hooks: ciscospark: type: ciscosparkdiff events: [post_store] accesskey: [SPARK_BOT_API_OR_OAUTH_KEY](https://developer.ciscospark.com/apps.html) space: [SPARK_SPACE_ID](https://developer.ciscospark.com/endpoint-rooms-get.html) diff: true ``` Optionally you can disable snippets and post a formatted message, for instance linking to a commit in a git repo. Named parameters `%{node}`, `%{group}`, `%{model}` and `%{commitref}` are available. ```yaml hooks: ciscospark: type: ciscosparkdiff events: [post_store] accesskey: [SPARK_BOT_API_OR_OAUTH_KEY](https://developer.ciscospark.com/apps.html) space: [SPARK_SPACE_ID](https://developer.ciscospark.com/endpoint-rooms-get.html) diff: false message: "%{node} %{group} %{model} updated https://git.intranet/network-changes/commit/%{commitref}" ``` Note the space and access tokens must be in quotes. ## Hook type: xmppdiff The `xmppdiff` hook posts config diffs to a [XMPP](https://en.wikipedia.org/wiki/XMPP) chatroom of your choice. It only triggers for `post_store` events. You will need to manually install the `xmpp4r` gem on your system: ```shell gem install xmpp4r ``` ### xmppdiff hook configuration example ```yaml hooks: xmpp: type: xmppdiff events: [post_store] jid: "user@server.tld/resource" password: "password" channel: "room@server.tld" nick: "nickname" ``` Note the channel name must be in quotes.