{"id":22452615,"url":"https://github.com/totaltechgeek/trident","last_synced_at":"2025-03-27T12:42:27.948Z","repository":{"id":255923589,"uuid":"853897944","full_name":"TotalTechGeek/trident","owner":"TotalTechGeek","description":"Trident Configuration Templating Engine","archived":false,"fork":false,"pushed_at":"2025-01-21T17:31:58.000Z","size":424,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-01T17:13:45.443Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TotalTechGeek.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-07T20:56:16.000Z","updated_at":"2025-01-21T17:32:02.000Z","dependencies_parsed_at":"2024-10-23T18:18:02.254Z","dependency_job_id":"182d9f2e-3f3e-42b3-b4d2-8634cd542f51","html_url":"https://github.com/TotalTechGeek/trident","commit_stats":null,"previous_names":["totaltechgeek/trident"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TotalTechGeek%2Ftrident","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TotalTechGeek%2Ftrident/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TotalTechGeek%2Ftrident/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TotalTechGeek%2Ftrident/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TotalTechGeek","download_url":"https://codeload.github.com/TotalTechGeek/trident/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245850122,"owners_count":20682632,"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":[],"created_at":"2024-12-06T06:11:52.578Z","updated_at":"2025-03-27T12:42:27.713Z","avatar_url":"https://github.com/TotalTechGeek.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Trident\n\n## Introduction\n\nTrident is a manifest-based templating engine for reusing configuration files. It is designed to be simple \u0026 flexible.\n\nIt takes inspiration from [Kustomize](https://github.com/kubernetes-sigs/kustomize) and [Helm](https://helm.sh), but is designed to be more generative \u0026 general-purpose.\n\n### Concepts\n\n- **Base Configurations** These are un-templated configurations that are used as the base for your output.\n- **Templates** This is a YAML file that describes any patches to apply to the base configuration. Unlike Kustomize, Trident templates are indeed templates, and can contain templating logic. (This is not a condemnation of Kustomize, which is a great tool, but rather a different design choice.)\n- **Manifest**: A YAML file that describes a set of resources. \n- **Schema** An optional [JSON Schema Specification](https://json-schema.org/learn/getting-started-step-by-step) to be applied to each resource defined in the manifest. This is useful for validation or applying defaults.\n\nBut to elaborate, imagine that you have a base configuration, and 15 services that can borrow from this base configuration. \n\nWith Trident, you can set up your base configuration, and define a manifest that describes the 15 services. The template can take values from the manifest, and apply them to the base configurations, and output 15 different sets of configurations.\n\n### Example\n\nHere's a potential example of a Trident manifest:\n\n```yaml\n# manifest.yaml\nname: Users\nreplicas: 3\n--- \nname: Orders\nreplicas: 5\n--- \nname: Payments\nreplicas: 2\n```\n\nYou could define a base configuration that looks like this:\n\n```yaml\n# base/deployment.yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: Unknown\nspec:\n    replicas: 1\n```\n\nAnd a template that looks like this:\n\n```yaml\n# template.yaml\n$in: base/deployment.yaml\n$out: {{name}}/deployment.yaml\nmetadata:\n  name: {{name}}\nspec:\n  replicas: {{replicas}}\n```\n    \nWhen you run Trident, it will apply the manifest to the template, and merge the results with the base configuration. The output would be three different deployment files, one for each service.\n\nIf you wanted, you could also specify a schema to make sure that the output is valid:\n\n```json\n{\n    \"type\": \"object\",\n    \"properties\": {\n        \"name\": {\n            \"type\": \"string\"\n        },\n        \"replicas\": {\n            \"type\": \"integer\",\n            \"minimum\": 1,\n            \"default\": 1\n        }\n    },\n    \"required\": [\"name\", \"replicas\"]\n}\n```\n\nWhich would ensure that the manifest is valid \u0026 apply defaults if necessary.\n\nTemplates can also specify that multiple resources should be outputted, and can be output to different directories / any depth. \n\nTo define multiple resources in the template, you can use the `---` separator, like in the manifest.\n\n### Templating Language\n\nTrident uses Handlebars as its templating language. This is a simple, flexible language that is easy to learn. \n\nYou can read more about Handlebars [here](https://handlebarsjs.com/).\n\nWe have added a few custom helpers to make it easier to work with configurations,\n\nHelper | Description | Example\n-- | -- | --\njson | Outputs the JSON representation of the object | `{{json env}}`\nmerge | Merges two or more objects together | `{{merge env $values.env}}`\ndefault | Sets a default value if the value is not present, I would recommend using schema instead though | `{{default replicas 1}}` \nobject | Constructs a new object | `{{object \"key\" \"value\" \"key2\" \"value2\"}}`\nor | Returns the first non-falsy value | `{{or env $values.env}}`\nmin | Returns the minimum value | `{{min replicas 1}}`\nmax | Returns the maximum value | `{{max replicas 10}}`\n\nWe also support the methods from [Handlebars-Helpers](https://npmjs.com/package/handlebars-helpers).\n\nWe recommend strongly that you check out the handlebars documentation directly, but you're able to use any of the built-in helpers in your templates, such as `if`, `each`, etc.\n\nExample:\n\n```yaml\n# template.yaml\n$in: base/deployment.yaml\n$out: {{name}}/deployment.yaml\nmetadata:\n  name: {{name}}\nspec:\n{{#if replicas}}\n  replicas: {{replicas}}\n{{/if}}\n{{#if env}}\n  env:\n  {{#each env}}\n    - name: {{@key}}\n      value: {{this}}\n  {{/each}}\n{{/if}}\n```\n\n`$in` is a special key that specifies the base configuration to use. This is a relative path to the base configuration.\n`$out` is a special key that specifies the output path; often you will likely template this based on the name of the resource.\n\nThere is also a `$copy` key that can be used to copy globs from one directory to another. This is useful for copying files that are not templated.\n\nExample:\n\n```yaml\n$copy: base/info/*.txt\n$out: {{name}}/info\n```\n\n`$replace` is a special key that can be used to replace literal strings in the base configuration. For most cases, I'd recommend using patching instead as described above, but this can be useful when you need to replace a value in numerous places in the base configuration.\n\nExample:\n\n```yaml\n$in: base/deployment.yaml\n$out: {{name}}/deployment.yaml\n$replace:\n  SERVICE_NAME: {{name}}\n```\n\nThis will replace all instances of `SERVICE_NAME` in the base configuration with the name of the service.\n\n\"Is this not a form of templating in the base configuration?\" you might ask. Admittedly -- yes, yes it is. I'd encourage you to use this sparingly. \n\n### Global Variables\n\nIf you have a set of variables you want to apply across all items in your manifest, you can either import them from a file or specify them on the CLI. They are referenced in templates as `$values`.\n\nFor example, you could have an `prod.json` file that looks like so:\n\n```json\n{\n    \"environment\": \"prod\",\n    \"region\": \"us-west-2\"\n}\n```\n\nThen upon running the following command:\n```bash\ntrident -i . -f env=prod.json\n```\n\nYou could access these variables in your templates like so (from `$values`):\n\n```yaml\n# template.yaml\n$in: base/deployment.yaml\n$out: {{name}}/deployment.yaml\nmetadata:\n  name: {{name}}\nspec:\n    replicas: {{replicas}}\n    env:\n        - name: ENVIRONMENT\n        value: {{$values.env.environment}}\n        - name: REGION\n        value: {{$values.env.region}}\n```\n\nYou can also specify these variables directly on the CLI, like so:\n\n```bash\ntrident -i . -v environment=prod -v region=us-west-2\n```\n\nWhich would allow you to access them directly off of `$values` in your templates.\n\n```yaml\n# template.yaml\n$in: base/deployment.yaml\n$out: {{name}}/deployment.yaml\nmetadata:\n  name: {{name}}\nspec:\n    replicas: {{replicas}}\n    env:\n        - name: ENVIRONMENT\n        value: {{$values.environment}}\n        - name: REGION\n        value: {{$values.region}}\n```\n\n### Running Trident \n\nTo run Trident, you can use the following command:\n\n```bash\ntrident -i . \n```\n\nThis will look for a `manifest.yaml`, `template.yaml` and an optional `schema.json` in the current directory, and execute the template.\n\nYou can also specify the three files directly, separated by commas, in the following order:\n\n```bash\ntrident -i manifest.yaml,template.yaml,schema.json\n```\n\nIt might be possible that you have multiple templates \u0026 manifests, so you can use the `-i` flag multiple times to specify multiple directories.\n\n```bash\ntrident -i services -i collectors\n```\n\n### Output\n\nTrident can output either directly to the filesystem or to an archive.\n\nTo output to an archive, you can specify the `-a` flag with a path to the archive. The current formats supported are `zip`, `tar`, and `tar.gz` (and `tgz`).\n\nFor example:\n\n```bash\ntrident -i . -a output.zip\n```\n\nThe structure of the output will be determined solely by the `$out` key in the templates.\n\n### Supported Formats for Base Configurations\n\nTrident currently supports YAML, JSON and XML for base configurations.\n\n### Enabling Templating in the Base Configurations\n\n*Hey! Maybe consider using `$replace` instead of this!*\n\nWhile I like how Kustomize separates the templating from the base configurations, I understand that this can be a bit cumbersome, especially if  a `{{name}}`-like value is used in multiple places.\n\nSo while I encourage you to keep your base configurations as clean as possible, you can enable templating in the base configurations by using the flag `--enableTemplateBase`.\n\nEven if you enable this flag, I strongly recommend setting up most of your patches in the templates, and use the templating sparingly for values that are used in multiple places.\n\n### Importing Values From Template Files\n\nAs described above, you can use the CLI Flags like `-f` and `-v` to import values into `$values`.\n\nHowever, if you need something a bit more robust, you can import values from within the templates themselves.\n\nTo do this, you can use `$values` as a key within the template, and specify where to import the values to.\n\n```yaml\n$in: base/deployment.yaml\n$out: {{name}}/deployment.yaml\n$values: \n    - env: env.json\n# ...\n```\n\nWould allow you to access `$values.env` in your templates.\n\nYou may also specify an object directly,\n\n```yaml\n$in: base/deployment.yaml\n$out: {{name}}/deployment.yaml\n$values: \n    - env: \n        - key: {{somethingFromManifest}}\n        - key2: value2\n```\n\nWhich would allow you to access `$values.env.key` and `$values.env.key2` in your templates.\n\nYou may also import multiple files or values, and they will be merged together, like so:\n\n```yaml\n$in: base/deployment.yaml\n$out: {{name}}/deployment.yaml\n$values:\n    - env: env.json\n    - env: extra-{{name}}.json\n```\n\nIf you wish to allow values to be shared across future templates, you can use the `--allowValuesSharing` flag. This will allow values imported inline by one template to be available in future templates for the same manifest item.\n\n\nAdditionally, if you'd like to import values directly to the root of `$values`, you can use `'.'` as the key.\n\n```yaml\n$in: base/deployment.yaml\n$out: {{name}}/deployment.yaml\n$values: \n    - '.': env.json\n```\n\n### Changing Output Directory\n\nYou can change the output directory for the configuration by using the `$chdir` key inside of a step.\n\n```yaml\n$chdir: output/{{name}}\n```\n\nThis will automatically make the directory if it doesn't exist.\n\n**NOTE**: It's not recommended you use this with $in / $out, as you can specify a directory in the $out key; this is useful for changing the output directory in a template that invokes other templates, and setting up something like `$chdir: output` or `$chdir: output/{{name}}` at the root level.\n\n### Creating Directories\n\nYou can create directories by using the `$mkdir` key; you may not always need this, as Trident will automatically create directories for most commands if they don't exist.\n\n```yaml\n$mkdir: output/{{name}}\n```\n\nMultiple directories can be created by using an array.\n\n```yaml\n$mkdir: \n    - output/frontend/{{name}}\n    - output/backend/{{name}}\n```\n\n### Removing Files\n\nYou can remove files or directories by using the `$rm` key.\n\n```yaml\n$rm: output/{{name}}/deployment.yaml\n```\n\nMultiple files or directories can be removed by using an array.\n\n```yaml\n$rm: \n    - output/frontend/{{name}}/deployment.yaml\n    - output/backend/{{name}}/deployment.yaml\n```\n\n### Merging Files\n\nYou can merge files together by using `$merge`. This is useful for combining multiple files into a single file.\n\nThe files can be specified as a glob, and a separator can be specified to separate the files.\n\n```yaml\n$merge:\n    files: \n        - output/**/deployment.yaml\n        - output/**/service.yaml\n    separator: \"---\\n\"\n$out: output/release.yaml\n```\n\nThe files will be appended in the order they are specified, with the separator between each file.\n\n### Calling Templates From Templates\n\nIn Trident, templates are multiplicative. This means that you can call a template from within a template, and values from either the manifest or template can be passed to the called template.\n\nTo call a template from within a template, you can use the `$template` key.\n\n```yaml\n$template: services/template.yaml\n$manifest: services/manifest.yaml\n---\n$template: frontend/template.yaml\n$manifest: frontend/manifest.yaml\n```\n\nThis would call the `services/template.yaml` with the `services/manifest.yaml` and the `frontend/template.yaml` with the `frontend/manifest.yaml`, allowing you to execute multiple templates in a single run.\n\nAny $values or values from the manifest will be passed to the called template.\n\n```yaml\n$chdir: output/{{name}}\n$manifest: services/manifest.yaml\n$template: services/template.yaml\n$values:\n    - env: {{name}}.json\ntype: service\n```\n\nWould allow you to access `$values.env` in the `services/template.yaml`, as well as `{{type}}` in the `services/template.yaml` (this also works with --match).\n\nYou might run the above template with the following command:\n\n```bash\ntrident -i . --relative\n```\n\nWith the manifest being:\n```yaml\nname: Prod\n---\nname: Dev\n```\n\nAllowing you to output two different sets of configurations, one for `Prod` and one for `Dev`.\n\nYou may also specify a schema to use for the called template by using the `$schema` key.\n\n```yaml\n$template: services/template.yaml\n$schema: services/schema.json\n$manifest: services/manifest.yaml\n```\n\n### Using Multiple Manifests\n\nAs noted above, you can use `$template` to invoke other templates. \n\nIf you pass an array into `$manifest`, Trident will merge the manifests together, and merge properties with the same name.\n\nConceptually, this is similar to using multiple overlays in Kustomize.\n\n```yaml\n$template: services/template.yaml\n$manifest: \n  - services/manifest.yaml\n  - services/{{$values.env}}.yaml\n```\n\nNow if I have `services/manifest.yaml` like so:\n```yaml\nname: Users\nenv: \n  HOST: users\n  MODE: prod\nreplicas: 3\n---\nname: Orders\nenv: \n  HOST: orders\n  MODE: prod\nreplicas: 2\n```\n\nAnd a file named `services/prod.yaml` like so:\n```yaml\nname: Users\nreplicas: 5\n```\n\nI could run Trident with:\n```bash\ntrident -i . -v env=prod\n```\n\nAnd Users would be deployed with 5 replicas, and Orders would be deployed with 2 replicas.\n\n### Flags \n\nFlag | Description\n-- | --\n--relative | If set, any input files will be resolved relative to the template file.\n--enableTemplateBase | If set, templating will be enabled in the base configurations.\n--dry | If set, the output will not be written to the filesystem, and will be printed to the console instead.\n-a, --archive | If set, the output will be written to an archive. The archive format is determined by the file extension.\n--allowValuesSharing | If set, $values imported inline by one template will be available in future templates for the same manifest item.\n-i, --input | The input files to use. This can be a directory or a list of files separated by commas.\n-f | Imports values from a JSON File to be made available in $values. You can specify where to import them to by using the format `key=path.to.value`.\n-v | Imports values directly to $values. You can specify where to import them to by using the format `key=value`.\n-b, --base | A convenience flag that makes it easier to execute a template file with a default manifest (name: Base). If you're using a template file to call other template files, it might make sense to use this flag.\n-m, --match | Allows you to filter which items in the manifest(s) you wish to use. `--match name=users` would only use the item in the manifest with the name `users`, for example. Other operators are supported, `\u003e` / `\u003c` / `\u003c=` / `\u003e=` / `!=` / `~` (regex). You can use `\u0026` to combine multiple filters, like so: `--match \"name=users\u0026replicas\u003e3\"`. You can also use `--match` multiple times to specify multiple allowed filters `-m name=frontend -m name=auth` would allow both `frontend` and `auth` to be deployed.\n--enable-exec | Allows the execution of the `$exec` key in templates. This is disabled by default for security reasons. Will run a command in the shell.\n\n### All Template Instructions\n\nKey | Description | Format |  Use With\n-- | -- | -- | --\n$in | The base configuration to use. | string | $out\n$out | The output path for the configuration. | string | $in, $merge, or $copy\n$copy | Copies files from one directory to another. | string (glob) | \n$replace | Replaces literal strings in the base configuration. | object | $in, or $merge\n$values | Imports values from a JSON file to be made available in $values. | object[] | \n$chdir | Changes the working directory for the output. | string |\n$exec | Executes a command, if `--enable-exec` is run | string |\n$mkdir | Creates a directory. | string or string[] |\n$rm | Removes a file or directory. | string or string[] |\n$merge | Used to merge globs of files together | { files: string[], separator?: string } | $out\n$archive | Allows you to specify an archive to output to. | string | $merge, or $template\n$template | Allows you to call another template from within a template. | string | $manifest\n$manifest | Allows you to specify a manifest to use. If multiple manifests are passed in, it will merge them. | string or string[] | $template\n$schema | Allows you to specify a schema to use. | string |  $manifest, $template\n\n\n### Why \"Trident\"?\n\nA trident is a multi-pronged tool; this tool is designed to give your base configurations multiple prongs, or outputs. It's also a cool word.\n\n## Installation\n\n```bash\nnpm i -g trident-template\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftotaltechgeek%2Ftrident","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftotaltechgeek%2Ftrident","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftotaltechgeek%2Ftrident/lists"}