{"id":13647403,"url":"https://github.com/nginxinc/crossplane","last_synced_at":"2025-05-14T22:09:41.557Z","repository":{"id":41203329,"uuid":"105075134","full_name":"nginxinc/crossplane","owner":"nginxinc","description":"Quick and reliable way to convert NGINX configurations into JSON and back.","archived":false,"fork":false,"pushed_at":"2024-05-20T13:38:24.000Z","size":361,"stargazers_count":726,"open_issues_count":22,"forks_count":87,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-05-14T08:58:06.082Z","etag":null,"topics":["configuration-builder","configuration-parser","json","json-conversion","json-converter","nginx","nginx-configs","nginx-configuration","nginx-configurator","parser"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nginxinc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.rst","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-27T22:18:23.000Z","updated_at":"2025-05-08T16:10:26.000Z","dependencies_parsed_at":"2024-01-14T10:08:59.615Z","dependency_job_id":"4a65b911-17a5-4e5c-acfa-53c6a9e1fb02","html_url":"https://github.com/nginxinc/crossplane","commit_stats":{"total_commits":180,"total_committers":15,"mean_commits":12.0,"dds":0.2055555555555556,"last_synced_commit":"3e616a890e9ad53c236bc934de0e0ed3ad290ee4"},"previous_names":["nginxinc/nginx-conf"],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nginxinc%2Fcrossplane","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nginxinc%2Fcrossplane/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nginxinc%2Fcrossplane/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nginxinc%2Fcrossplane/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nginxinc","download_url":"https://codeload.github.com/nginxinc/crossplane/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254235701,"owners_count":22036964,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration-builder","configuration-parser","json","json-conversion","json-converter","nginx","nginx-configs","nginx-configuration","nginx-configurator","parser"],"created_at":"2024-08-02T01:03:32.525Z","updated_at":"2025-05-14T22:09:36.541Z","avatar_url":"https://github.com/nginxinc.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"![Crossplane Logo](https://raw.githubusercontent.com/nginxinc/crossplane/master/ext/crossplane-logo.png)\n\u003ch1 align=\"center\"\u003ecrossplane\u003c/h1\u003e\n\u003ch3 align=\"center\"\u003eReliable and fast NGINX configuration file parser and builder\u003c/h3\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://github.com/nginxinc/crossplane/actions/workflows/crossplane-ci.yml\"\u003e\u003cimg src=\"https://github.com/nginxinc/crossplane/actions/workflows/crossplane-ci.yml/badge.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/nginxinc/crossplane/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/release/nginxinc/crossplane.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://pypi.python.org/pypi/crossplane\"\u003e\u003cimg src=\"https://img.shields.io/pypi/l/crossplane.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://pypi.python.org/pypi/crossplane\"\u003e\u003cimg src=\"https://img.shields.io/pypi/pyversions/crossplane.svg\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n  - [Install](#install)\n  - [Command Line Interface](#command-line-interface)\n      - [crossplane parse](#crossplane-parse)\n      - [crossplane build](#crossplane-build)\n      - [crossplane lex](#crossplane-lex)\n      - [crossplane format](#crossplane-format)\n      - [crossplane minify](#crossplane-minify)\n  - [Python Module](#python-module)\n      - [crossplane.parse()](#crossplaneparse)\n      - [crossplane.build()](#crossplanebuild)\n      - [crossplane.lex()](#crossplanelex)\n  - [Other Languages](#other-languages)\n\n## Install\n\nYou can install both the [Command Line\nInterface](#command-line-interface) and [Python Module](#python-module)\nvia:\n\n    pip install crossplane\n\n## Command Line Interface\n\n```\nusage: crossplane \u003ccommand\u003e [options]\n\nvarious operations for nginx config files\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -V, --version         show program's version number and exit\n\ncommands:\n  parse                 parses a json payload for an nginx config\n  build                 builds an nginx config from a json payload\n  lex                   lexes tokens from an nginx config file\n  minify                removes all whitespace from an nginx config\n  format                formats an nginx config file\n  help                  show help for commands\n```\n\n### crossplane parse\n\nThis command will take a path to a main NGINX config file as input, then\nparse the entire config into the schema defined below, and dumps the\nentire thing as a JSON payload.\n\n```\nusage: crossplane parse [-h] [-o OUT] [-i NUM] [--ignore DIRECTIVES]\n                        [--no-catch] [--tb-onerror] [--single-file]\n                        [--include-comments] [--strict]\n                        filename\n\nparses a json payload for an nginx config\n\npositional arguments:\n  filename              the nginx config file\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -o OUT, --out OUT     write output to a file\n  -i NUM, --indent NUM  number of spaces to indent output\n  --ignore DIRECTIVES   ignore directives (comma-separated)\n  --no-catch            only collect first error in file\n  --tb-onerror          include tracebacks in config errors\n  --combine             use includes to create one single file\n  --single-file         do not include other config files\n  --include-comments    include comments in json\n  --strict              raise errors for unknown directives\n```\n\n**Privacy and Security**\n\nSince `crossplane` is usually used to create payloads that are sent to\ndifferent servers, it's important to keep security in mind. For that\nreason, the `--ignore` option was added. It can be used to keep certain\nsensitive directives out of the payload output entirely.\n\nFor example, we always use the equivalent of this flag in the [NGINX Amplify\nAgent](https://github.com/nginxinc/nginx-amplify-agent/) out of respect\nfor our users'\n    privacy:\n\n    --ignore=auth_basic_user_file,secure_link_secret,ssl_certificate_key,ssl_client_certificate,ssl_password_file,ssl_stapling_file,ssl_trusted_certificate\n\n#### Schema\n\n**Response Object**\n\n```js\n{\n    \"status\": String, // \"ok\" or \"failed\" if \"errors\" is not empty\n    \"errors\": Array,  // aggregation of \"errors\" from Config objects\n    \"config\": Array   // Array of Config objects\n}\n```\n\n**Config Object**\n\n```js\n{\n    \"file\": String,   // the full path of the config file\n    \"status\": String, // \"ok\" or \"failed\" if errors is not empty array\n    \"errors\": Array,  // Array of Error objects\n    \"parsed\": Array   // Array of Directive objects\n}\n```\n\n**Directive Object**\n\n```js\n{\n    \"directive\": String, // the name of the directive\n    \"line\": Number,      // integer line number the directive started on\n    \"args\": Array,       // Array of String arguments\n    \"includes\": Array,   // Array of integers (included iff this is an include directive)\n    \"block\": Array       // Array of Directive Objects (included iff this is a block)\n}\n```\n\n\u003cdiv class=\"note\"\u003e\n\n\u003cdiv class=\"admonition-title\"\u003e\n\nNote\n\n\u003c/div\u003e\n\nIf this is an `include` directive and the `--single-file` flag was not\nused, an `\"includes\"` value will be used that holds an Array of indices\nof the configs that are included by this directive.\n\nIf this is a block directive, a `\"block\"` value will be used that holds\nan Array of more Directive Objects that define the block context.\n\n\u003c/div\u003e\n\n**Error Object**\n\n```js\n{\n    \"file\": String,     // the full path of the config file\n    \"line\": Number,     // integer line number the directive that caused the error\n    \"error\": String,    // the error message\n    \"callback\": Object  // only included iff an \"onerror\" function was passed to parse()\n}\n```\n\n\u003cdiv class=\"note\"\u003e\n\n\u003cdiv class=\"admonition-title\"\u003e\n\nNote\n\n\u003c/div\u003e\n\nIf the `--tb-onerror` flag was used by crossplane parse, `\"callback\"`\nwill contain a string that represents the traceback that the error\ncaused.\n\n\u003c/div\u003e\n\n#### Example\n\nThe main NGINX config file is at `/etc/nginx/nginx.conf`:\n\n```nginx\nevents {\n    worker_connections 1024;\n}\n\nhttp {\n    include conf.d/*.conf;\n}\n```\n\nAnd this config file is at `/etc/nginx/conf.d/servers.conf`:\n\n```nginx\nserver {\n    listen 8080;\n    location / {\n        try_files 'foo bar' baz;\n    }\n}\n\nserver {\n    listen 8081;\n    location / {\n        return 200 'success!';\n    }\n}\n```\n\nSo then if you run this:\n\n    crossplane parse --indent=4 /etc/nginx/nginx.conf\n\nThe prettified JSON output would look like this:\n\n```js\n{\n    \"status\": \"ok\",\n    \"errors\": [],\n    \"config\": [\n        {\n            \"file\": \"/etc/nginx/nginx.conf\",\n            \"status\": \"ok\",\n            \"errors\": [],\n            \"parsed\": [\n                {\n                    \"directive\": \"events\",\n                    \"line\": 1,\n                    \"args\": [],\n                    \"block\": [\n                        {\n                            \"directive\": \"worker_connections\",\n                            \"line\": 2,\n                            \"args\": [\n                                \"1024\"\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"directive\": \"http\",\n                    \"line\": 5,\n                    \"args\": [],\n                    \"block\": [\n                        {\n                            \"directive\": \"include\",\n                            \"line\": 6,\n                            \"args\": [\n                                \"conf.d/*.conf\"\n                            ],\n                            \"includes\": [\n                                1\n                            ]\n                        }\n                    ]\n                }\n            ]\n        },\n        {\n            \"file\": \"/etc/nginx/conf.d/servers.conf\",\n            \"status\": \"ok\",\n            \"errors\": [],\n            \"parsed\": [\n                {\n                    \"directive\": \"server\",\n                    \"line\": 1,\n                    \"args\": [],\n                    \"block\": [\n                        {\n                            \"directive\": \"listen\",\n                            \"line\": 2,\n                            \"args\": [\n                                \"8080\"\n                            ]\n                        },\n                        {\n                            \"directive\": \"location\",\n                            \"line\": 3,\n                            \"args\": [\n                                \"/\"\n                            ],\n                            \"block\": [\n                                {\n                                    \"directive\": \"try_files\",\n                                    \"line\": 4,\n                                    \"args\": [\n                                        \"foo bar\",\n                                        \"baz\"\n                                    ]\n                                }\n                            ]\n                        }\n                    ]\n                },\n                {\n                    \"directive\": \"server\",\n                    \"line\": 8,\n                    \"args\": [],\n                    \"block\": [\n                        {\n                            \"directive\": \"listen\",\n                            \"line\": 9,\n                            \"args\": [\n                                \"8081\"\n                            ]\n                        },\n                        {\n                            \"directive\": \"location\",\n                            \"line\": 10,\n                            \"args\": [\n                                \"/\"\n                            ],\n                            \"block\": [\n                                {\n                                    \"directive\": \"return\",\n                                    \"line\": 11,\n                                    \"args\": [\n                                        \"200\",\n                                        \"success!\"\n                                    ]\n                                }\n                            ]\n                        }\n                    ]\n                }\n            ]\n        }\n    ]\n}\n```\n\n#### crossplane parse (advanced)\n\nThis tool uses two flags that can change how `crossplane` handles\nerrors.\n\nThe first, `--no-catch`, can be used if you'd prefer that crossplane\nquit parsing after the first error it finds.\n\nThe second, `--tb-onerror`, will add a `\"callback\"` key to all error\nobjects in the JSON output, each containing a string representation of\nthe traceback that would have been raised by the parser if the exception\nhad not been caught. This can be useful for logging purposes.\n\n### crossplane build\n\nThis command will take a path to a file as input. The file should\ncontain a JSON representation of an NGINX config that has the structure\ndefined above. Saving and using the output from `crossplane parse` to\nrebuild your config files should not cause any differences in content\nexcept for the formatting.\n\n```\nusage: crossplane build [-h] [-d PATH] [-f] [-i NUM | -t] [--no-headers]\n                        [--stdout] [-v]\n                        filename\n\nbuilds an nginx config from a json payload\n\npositional arguments:\n  filename              the file with the config payload\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -v, --verbose         verbose output\n  -d PATH, --dir PATH   the base directory to build in\n  -f, --force           overwrite existing files\n  -i NUM, --indent NUM  number of spaces to indent output\n  -t, --tabs            indent with tabs instead of spaces\n  --no-headers          do not write header to configs\n  --stdout              write configs to stdout instead\n```\n\n### crossplane lex\n\nThis command takes an NGINX config file, splits it into tokens by\nremoving whitespace and comments, and dumps the list of tokens as a JSON\narray.\n\n```\nusage: crossplane lex [-h] [-o OUT] [-i NUM] [-n] filename\n\nlexes tokens from an nginx config file\n\npositional arguments:\n  filename              the nginx config file\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -o OUT, --out OUT     write output to a file\n  -i NUM, --indent NUM  number of spaces to indent output\n  -n, --line-numbers    include line numbers in json payload\n```\n\n#### Example\n\nPassing in this NGINX config file at `/etc/nginx/nginx.conf`:\n\n```nginx\nevents {\n    worker_connections 1024;\n}\n\nhttp {\n    include conf.d/*.conf;\n}\n```\n\nBy running:\n\n    crossplane lex /etc/nginx/nginx.conf\n\nWill result in this JSON\noutput:\n\n```js\n[\"events\",\"{\",\"worker_connections\",\"1024\",\";\",\"}\",\"http\",\"{\",\"include\",\"conf.d/*.conf\",\";\",\"}\"]\n```\n\nHowever, if you decide to use the `--line-numbers` flag, your output\nwill look\nlike:\n\n```js\n[[\"events\",1],[\"{\",1],[\"worker_connections\",2],[\"1024\",2],[\";\",2],[\"}\",3],[\"http\",5],[\"{\",5],[\"include\",6],[\"conf.d/*.conf\",6],[\";\",6],[\"}\",7]]\n```\n\n### crossplane format\n\nThis is a quick and dirty tool that uses [crossplane\nparse](#crossplane-parse) internally to format an NGINX config file.\nIt serves the purpose of demonstrating what you can do with `crossplane`'s\nparsing abilities. It is not meant to be a fully fleshed out, feature-rich\nformatting tool. If that is what you are looking for, then you may want to\nlook writing your own using crossplane's Python API.\n\n```\nusage: crossplane format [-h] [-o OUT] [-i NUM | -t] filename\n\nformats an nginx config file\n\npositional arguments:\n  filename              the nginx config file\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -o OUT, --out OUT     write output to a file\n  -i NUM, --indent NUM  number of spaces to indent output\n  -t, --tabs            indent with tabs instead of spaces\n```\n\n### crossplane minify\n\nThis is a simple and fun little tool that uses [crossplane\nlex](#crossplane-lex) internally to remove as much whitespace from an\nNGINX config file as possible without affecting what it does. It can't\nimagine it will have much of a use to most people, but it demonstrates\nthe kinds of things you can do with `crossplane`'s lexing abilities.\n\n```\nusage: crossplane minify [-h] [-o OUT] filename\n\nremoves all whitespace from an nginx config\n\npositional arguments:\n  filename           the nginx config file\n\noptional arguments:\n  -h, --help         show this help message and exit\n  -o OUT, --out OUT  write output to a file\n```\n\n## Python Module\n\nIn addition to the command line tool, you can import `crossplane` as a\npython module. There are two basic functions that the module will\nprovide you: `parse` and `lex`.\n\n### crossplane.parse()\n\n```python\nimport crossplane\npayload = crossplane.parse('/etc/nginx/nginx.conf')\n```\n\nThis will return the same payload as described in the [crossplane\nparse](#crossplane-parse) section, except it will be Python dicts and\nnot one giant JSON string.\n\n### crossplane.build()\n\n```python\nimport crossplane\nconfig = crossplane.build(\n    [{\n        \"directive\": \"events\",\n        \"args\": [],\n        \"block\": [{\n            \"directive\": \"worker_connections\",\n            \"args\": [\"1024\"]\n        }]\n    }]\n)\n```\n\nThis will return a single string that contains an entire NGINX config\nfile.\n\n### crossplane.lex()\n\n```python\nimport crossplane\ntokens = crossplane.lex('/etc/nginx/nginx.conf')\n```\n\n`crossplane.lex` generates 2-tuples. Inserting these pairs into a list\nwill result in a long list similar to what you can see in the\n[crossplane lex](#crossplane-lex) section when the `--line-numbers` flag\nis used, except it will obviously be a Python list of tuples and not one\ngiant JSON string.\n\n## Other Languages\n\n- Go port by [@aluttik](https://github.com/aluttik):\n    \u003chttps://github.com/aluttik/go-crossplane\u003e\n- Ruby port by [@gdanko](https://github.com/gdanko):\n    \u003chttps://github.com/gdanko/crossplane\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnginxinc%2Fcrossplane","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnginxinc%2Fcrossplane","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnginxinc%2Fcrossplane/lists"}