项目作者: scravy

项目描述 :
JSON/YAML homoiconic templating language
高级语言: Python
项目地址: git://github.com/scravy/jinsi.git
创建时间: 2020-11-27T00:24:37Z
项目社区:https://github.com/scravy/jinsi

开源协议:MIT License

下载


JSON/YAML homoiconic templating language

Github Actions
Downloads
PyPI version

```shell script
python3 -m pip install jinsi

  1. Jinsi is a templating engine that uses YAML/JSON syntax, i.e. it is homoiconic. Never mess with indentation again.
  2. Most template engines are a poor choice for templating YAML/JSON, which is why Jinsi is embedded in the document as
  3. native YAML/JSON syntax.
  4. Example:
  5. ```yaml
  6. ::let:
  7. foo: Hello
  8. bar: World
  9. value: <<foo>> <<bar>>

Yields:

  1. value: Hello World

Since Jinsi is basically independent from the syntax it works natively in JSON (or any other dialect which uses the
same data model) too:

  1. {
  2. "::let": {
  3. "foo": "Hello",
  4. "bar": "World"
  5. },
  6. "value": "<<foo>> <<bar>>"
  7. }

Jinsi was inspired by AWS Cloudformation templates, which are also homoiconic and feature builtin functions
(with more limited scope though). As I am using it to ease my DevOps woes it supports Cloudformation’s
Bang-Syntax (!Sub) natively.

Jinsi comes as a command line tool, but you can use it as a library for reading/writing YAML/JSON files too.

Usage:

  1. jinsi template.yaml foo=bar qux=quuz

The above invocation will set $foo to Jane and $qux to Jim:

  1. value: Hello <<$foo>>

…would result in value: Hello Jane.

I am also using it to template Kubernetes YAML files. Both kustomize as well as helm (which uses Go
Templates 😖) do not cut it for me. My developer life has been happier ever since. I could imagine using it with salt, too
(Jinja templates + YAML is just a PITA). Here’s an example which configures
an ingress resource using aws load balancer controller

  1. ::let:
  2. $name: web-application
  3. $subdomain: dashboard
  4. $domain: example.com
  5. $services:
  6. - users
  7. - messages
  8. - backoffice
  9. apiVersion: extensions/v1beta1
  10. kind: Ingress
  11. metadata:
  12. name: <<$subdomain>>
  13. annotations:
  14. kubernetes.io/ingress.class: alb
  15. alb.ingress.kubernetes.io/group.name: <<$domain>>
  16. alb.ingress.kubernetes.io/scheme: internet-facing
  17. alb.ingress.kubernetes.io/listen-ports:
  18. ::json_serialize:
  19. - HTTPS: 443
  20. - HTTP: 80
  21. alb.ingress.kubernetes.io/actions.ssl-redirect:
  22. ::json_serialize:
  23. Type: redirect
  24. RedirectConfig:
  25. Protocol: HTTPS
  26. Port: '443'
  27. StatusCode: HTTP_301
  28. spec:
  29. rules:
  30. - host: <<$subdomain>>.<<$domain>>
  31. http:
  32. paths:
  33. ::concat:
  34. - - path: /*
  35. backend:
  36. serviceName: ssl-redirect
  37. servicePort: use-annotation
  38. - ::each $services as $service:
  39. path: '/<<$service>>/*'
  40. backend:
  41. serviceName: <<$service>>-service
  42. servicePort: 80
  43. - - path: '/*'
  44. backend:
  45. serviceName: <<$name>>
  46. servicePort: 80

Usage via CLI

```shell script
python3 -m jinsi - # read from stdin

  1. ```shell script
  2. python3 -m jinsi -j - # read from stdin, render as json

```shell script
python3 -m jinsi file1.yaml file2.yaml

  1. ## Examples
  2. ### Cloudformation Template
  3. YAML input:
  4. ```yaml
  5. ::let:
  6. user:
  7. ::object:
  8. - ::titlecase:
  9. ::get: $user.username
  10. - Type: AWS::IAM::User
  11. Properties:
  12. UserName:
  13. ::get: $user.username
  14. Groups:
  15. - Administrators
  16. LoginProfile:
  17. Password:
  18. ::get: $user.password
  19. ::else: default
  20. PasswordResetRequired: Yes
  21. users:
  22. ::merge:
  23. ::each $ as $user:
  24. ::call user:
  25. Resources:
  26. ::call users:
  27. - username: jim
  28. password: one
  29. - username: jack
  30. password: two
  31. - username: johnny

Rendered output:

  1. Resources:
  2. Jack:
  3. Properties:
  4. Groups:
  5. - Administrators
  6. LoginProfile:
  7. Password: two
  8. PasswordResetRequired: true
  9. UserName: jack
  10. Type: AWS::IAM::User
  11. Jim:
  12. Properties:
  13. Groups:
  14. - Administrators
  15. LoginProfile:
  16. Password: one
  17. PasswordResetRequired: true
  18. UserName: jim
  19. Type: AWS::IAM::User
  20. Johnny:
  21. Properties:
  22. Groups:
  23. - Administrators
  24. LoginProfile:
  25. Password: default
  26. PasswordResetRequired: true
  27. UserName: johnny
  28. Type: AWS::IAM::User

Some fancy shit, too 🥸

This is just an example to show how complex a template can be.
Also note: The fibonacci function is defined recursively. This
would blow up and values upto 50 could not be computed. Since
Jinsi is purely functional, functions are mappings and can be
cached. This is why the computation returns quickly (at all).

```shell script
python3 -m jinsi max=50 -

  1. YAML input:
  2. ```yaml
  3. ::let:
  4. fib:
  5. ::when:
  6. ::get: $n == 0 or $n == 1
  7. ::then:
  8. ::get: $n
  9. ::else:
  10. ::add:
  11. - ::call fib:
  12. $n:
  13. ::get: $n - 1
  14. - ::call fib:
  15. $n:
  16. ::get: $n - 2
  17. fibs:
  18. ::range_exclusive:
  19. - 0
  20. - ::get: $max
  21. ::else: 10
  22. result:
  23. ::each fibs as $n:
  24. ::call: fib

Rendered output:

  1. result:
  2. - 0
  3. - 1
  4. - 1
  5. - 2
  6. - 3
  7. - 5
  8. - 8
  9. - 13
  10. - 21
  11. - 34
  12. - 55
  13. - 89
  14. - 144
  15. - 233
  16. - 377
  17. - 610
  18. - 987
  19. - 1597
  20. - 2584
  21. - 4181
  22. - 6765
  23. - 10946
  24. - 17711
  25. - 28657
  26. - 46368
  27. - 75025
  28. - 121393
  29. - 196418
  30. - 317811
  31. - 514229
  32. - 832040
  33. - 1346269
  34. - 2178309
  35. - 3524578
  36. - 5702887
  37. - 9227465
  38. - 14930352
  39. - 24157817
  40. - 39088169
  41. - 63245986
  42. - 102334155
  43. - 165580141
  44. - 267914296
  45. - 433494437
  46. - 701408733
  47. - 1134903170
  48. - 1836311903
  49. - 2971215073
  50. - 4807526976
  51. - 7778742049