Giới thiệu về Ngôn ngữ Mẫu
Jinja là ngôn ngữ mẫu linh hoạt cho Python có thể được sử dụng để tạo bất kỳ định dạng dựa trên văn bản nào như HTML, XML và YAML. Các ngôn ngữ mẫu như Jinja cho phép bạn chèn dữ liệu vào định dạng có cấu trúc. Bạn cũng có thể nhúng các câu lệnh logic hoặc luồng điều khiển vào các mẫu để có khả năng tái sử dụng và tính mô-đun cao hơn. Công cụ mẫu của Jinja chịu trách nhiệm xử lý mã trong các mẫu và tạo đầu ra cho tài liệu dựa trên văn bản cuối cùng.
Ngôn ngữ mẫu được biết đến rộng rãi trong bối cảnh tạo trang web trong kiến trúc Model View Controller . Trong trường hợp này, công cụ mẫu xử lý dữ liệu nguồn, như dữ liệu tìm thấy trong cơ sở dữ liệu và mẫu web bao gồm hỗn hợp HTML và ngôn ngữ mẫu. Hai phần này sau đó được sử dụng để tạo trang web cuối cùng để người dùng sử dụng. Tuy nhiên, ngôn ngữ mẫu không giới hạn ở các trang web. Salt, một phần mềm quản lý cấu hình phổ biến dựa trên Python, hỗ trợ Jinja để cho phép trừu tượng hóa và tái sử dụng trong các tệp trạng thái Salt và các tệp thông thường.
Hướng dẫn này sẽ cung cấp tổng quan về ngôn ngữ mẫu Jinja được sử dụng chủ yếu trong Salt. Nếu bạn chưa quen với các khái niệm Salt, hãy xem lại Hướng dẫn dành cho người mới bắt đầu về Salt trước khi tiếp tục. Mặc dù bạn sẽ không tạo trạng thái Salt của riêng mình trong hướng dẫn này, nhưng cũng hữu ích khi xem lại hướng dẫn Bắt đầu với Salt – Cài đặt và Thiết lập cơ bản .
Kiến thức cơ bản về Jinja
Phần này cung cấp mô tả giới thiệu về cú pháp và khái niệm Jinja cùng với các ví dụ về trạng thái Jinja và Salt. Để tìm hiểu sâu hơn về Jinja, hãy tham khảo Tài liệu chính thức của Jinja Template Designer .
Các ứng dụng như Salt có thể xác định hành vi mặc định cho công cụ tạo mẫu Jinja. Tất cả các ví dụ trong hướng dẫn này đều sử dụng các tùy chọn môi trường Jinja mặc định của Salt. Các thiết lập này có thể được thay đổi trong tệp cấu hình chính Salt:
# Default Jinja environment options for all templates except sls templates
#jinja_env:
# block_start_string: '{%'
# block_end_string: '%}'
# variable_start_string: '{{'
# variable_end_string: '}}'
# comment_start_string: '{#'
# comment_end_string: '#}'
# line_statement_prefix:
# line_comment_prefix:
# trim_blocks: False
# lstrip_blocks: False
# newline_sequence: '\n'
# keep_trailing_newline: False
# Jinja environment options for sls templates
#jinja_sls_env:
# block_start_string: '{%'
# block_end_string: '%}'
# variable_start_string: '{{'
# variable_end_string: '}}'
# comment_start_string: '{#'
# comment_end_string: '#}'
# line_statement_prefix:
# line_comment_prefix:
# trim_blocks: False
# lstrip_blocks: False
Ghi chú: Trước khi đưa Jinja vào trạng thái Salt của bạn, hãy đảm bảo xem lại phần Thực hành tốt nhất về Salt và Jinja của hướng dẫn này để đảm bảo rằng bạn đang tạo ra các trạng thái Salt có thể bảo trì và đọc được. Có thể sử dụng các công cụ và khái niệm Salt nâng cao hơn để cải thiện tính mô-đun và khả năng tái sử dụng của một số ví dụ về trạng thái Jinja và Salt được sử dụng trong hướng dẫn này.
Dấu phân cách
Các dấu phân cách ngôn ngữ mẫu được sử dụng để biểu thị ranh giới giữa ngôn ngữ mẫu và một loại định dạng dữ liệu khác như HTML hoặc YAML. Jinja sử dụng các dấu phân cách sau:
Cú pháp phân cách | Cách sử dụng |
---|---|
{% ... %} | Cấu trúc điều khiển |
{{ ... }} | Các biểu thức được đánh giá sẽ in ra đầu ra mẫu |
{# ... #} | Các bình luận sẽ bị bỏ qua bởi công cụ tạo mẫu |
# ... ## | Các câu lệnh dòng |
Trong ví dụ về tệp trạng thái Salt này, bạn có thể phân biệt cú pháp Jinja với YAML nhờ các {% ... %}
dấu phân cách bao quanh các điều kiện if/else:
{% if grains['group'] == 'admin' %}
America/Denver:
timezone.system:
{% else %}
Europe/Minsk:
timezone.system:
{% endif %}
Xem phần cấu trúc điều khiển để biết thêm thông tin về điều kiện.
Biến mẫu
Biến mẫu có sẵn thông qua từ điển ngữ cảnh của mẫu. Từ điển ngữ cảnh của mẫu được tạo tự động trong các giai đoạn khác nhau của quá trình đánh giá mẫu. Các biến này có thể được truy cập bằng ký hiệu dấu chấm:
{{ foo.bar }}
Hoặc chúng có thể được truy cập bằng cú pháp chỉ số dưới:
{{ foo['bar'] }}
Salt cung cấp một số biến ngữ cảnh có sẵn theo mặc định cho bất kỳ tệp trạng thái Salt hoặc mẫu tệp nào:
Salt : salt
Biến này cung cấp một tập hợp các hàm thư viện Salt mạnh mẽ .
{{ salt['pw_user.list_groups']('jdoe') }}
Bạn có thể chạy salt '*' sys.doc
từ Salt master để xem danh sách tất cả các chức năng có sẵn.
Opts : Biến là một từ điển cung cấp quyền truy cập vào nội dung của tệp cấu hìnhopts
minion Salt :
{{ opts['log_file'] }}
Vị trí lưu trữ tệp cấu hình của minion là /etc/salt/minion
.
Trụ cột : Biến là một từ điển được sử dụng để truy cập dữ liệu trụ cộtpillar
của Salt :
{{ pillar['my_key'] }}
Mặc dù bạn có thể truy cập trực tiếp các khóa và giá trị của cột, nhưng bạn nên sử dụng pillar.get
hàm thư viện biến của Salt, vì nó cho phép bạn xác định giá trị mặc định. Điều này hữu ích khi giá trị không tồn tại trong cột:
{{ salt['pillar.get']('my_key', 'default_value') }}
Grains : grains
Biến này là một từ điển và cung cấp quyền truy cập vào dữ liệu hạt của minion :
{{ grains['shell'] }}
grains.get
Bạn cũng có thể sử dụng hàm thư viện biến của Salt để truy cập dữ liệu hạt:
{{ salt['grains.get']('shell') }}
Saltenv : Bạn có thể định nghĩa nhiều môi trường salt cho minion trong tệp top của Salt master, chẳng hạn như base
, prod
, dev
và test
. saltenv
Biến này cung cấp một cách để truy cập môi trường Salt hiện tại trong tệp trạng thái Salt. Biến này chỉ khả dụng trong các tệp trạng thái Salt.
{{ saltenv }}
SLS : Với sls
biến này, bạn có thể lấy được giá trị tham chiếu cho tệp trạng thái hiện tại (ví dụ: apache
, webserver
, v.v.). Đây là giá trị tương tự được sử dụng trong tệp top để ánh xạ minion vào tệp trạng thái hoặc thông qua include
tùy chọn trong tệp trạng thái:
{{ sls }}
Slspath : Biến này cung cấp đường dẫn đến tệp trạng thái hiện tại:
{{ slspath }}
Gán biến
Bạn có thể gán giá trị cho một biến bằng cách sử dụng thẻ set
cùng với dấu phân cách và cú pháp sau:
{% set var_name = myvalue %}
Thực hiện theo quy ước đặt tên Python khi tạo tên biến. Nếu biến được gán ở cấp cao nhất của mẫu, phép gán sẽ được xuất và có thể được nhập bởi các mẫu khác.
Bất kỳ giá trị nào được tạo ra bởi hàm thư viện biến mẫu Salt đều có thể được gán cho một biến mới.
{% set username = salt['user.info']('username') %}
Bộ lọc
Bộ lọc có thể được áp dụng cho bất kỳ biến mẫu nào thông qua một |
ký tự. Bộ lọc có thể nối chuỗi và chấp nhận các đối số tùy chọn trong dấu ngoặc đơn. Khi nối chuỗi bộ lọc, đầu ra của một bộ lọc sẽ trở thành đầu vào của bộ lọc tiếp theo.
{{ '/etc/salt/' | list_files | join('\n') }}
Các bộ lọc được nối này sẽ trả về danh sách đệ quy của tất cả các tệp trong thư /etc/salt/
mục. Mỗi mục danh sách sẽ được nối bằng một dòng mới.
/etc/salt/master
/etc/salt/proxy
/etc/salt/minion
/etc/salt/pillar/top.sls
/etc/salt/pillar/device1.sls
Để biết danh sách đầy đủ tất cả các bộ lọc Jinja tích hợp, hãy tham khảo tài liệu Thiết kế mẫu Jinja . Tài liệu chính thức của Salt bao gồm danh sách các bộ lọc Jinja tùy chỉnh .
Macro
Macro là các mẫu nhỏ, có thể tái sử dụng giúp bạn giảm thiểu sự lặp lại khi tạo trạng thái. Xác định macro trong các mẫu Jinja để biểu diễn các cấu trúc thường dùng và sau đó tái sử dụng các macro trong các tệp trạng thái.
{% macro mysql_privs(user, grant=select, database, host=localhost) %}
{{ user }}_exampledb:
mysql_grants.present:
- grant: {{ grant }}
- database: {{ database }}
- user: {{user}}
- host: {{ host }}
{% endmacro %}
{% import "/srv/salt/mysql/db_macro.sls" as db -%}
db.mysql_privs('jane','exampledb.*','select,insert,update')
Macro mysql_privs()
được định nghĩa trong db_macro.sls
tệp. Sau đó, mẫu được nhập vào db
biến trong db_privs.sls
tệp trạng thái và được sử dụng để tạo trạng thái MySQL grants
cho một người dùng cụ thể.
Tham khảo phần Nhập và Bao gồm để biết thêm thông tin về việc nhập mẫu và biến.
Nhập khẩu và Bao gồm
Nhập khẩu
Nhập trong Jinja tương tự như nhập trong Python. Bạn có thể nhập toàn bộ mẫu, trạng thái cụ thể hoặc macro được xác định trong tệp.
{% import '/srv/salt/users.sls' as users %}
Ví dụ này sẽ nhập tệp trạng thái users.sls
vào biến users
. Tất cả các trạng thái và macro được xác định trong mẫu sẽ có sẵn bằng cách sử dụng ký hiệu dấu chấm.
Bạn cũng có thể nhập trạng thái hoặc macro cụ thể từ một tệp.
{% from '/srv/salt/user.sls' import mysql_privs as grants %}
Lệnh nhập này nhắm vào macro mysql_privs
được xác định trong user.sls
tệp trạng thái và được cung cấp cho mẫu hiện tại với grants
biến đó.
Bao gồm
Thẻ này {% include %}
hiển thị đầu ra của một mẫu khác vào vị trí mà thẻ include được khai báo. Khi sử dụng thẻ, {% include %}
ngữ cảnh của mẫu include được chuyển đến mẫu đang gọi.
include:
- groups
{% include 'users.sls' %}
Ghi chú: Một tệp được tham chiếu bởi thẻ Jinja include
cần được chỉ định theo đường dẫn tuyệt đối của nó từ thiết lập của Saltfile_roots
; sử dụng đường dẫn tương đối từ tệp trạng thái hiện tại sẽ tạo ra lỗi. Để bao gồm một tệp trong cùng thư mục với tệp trạng thái hiện tại:
{% include slspath + "/users.sls" %}
Ngoài ra, lưu ý rằng Salt có khai báo gốc riênginclude
, độc lập với . của Jinja include
.
Nhập khẩu hành vi bối cảnh
Theo mặc định, một lần nhập sẽ không bao gồm ngữ cảnh của mẫu đã nhập, vì các lần nhập được lưu trong bộ nhớ đệm. Điều này có thể được ghi đè bằng cách thêm with context
vào các câu lệnh nhập của bạn.
{% from '/srv/salt/user.sls' import mysql_privs with context %}
Tương tự như vậy, nếu bạn muốn xóa ngữ cảnh khỏi {% include %}
, hãy thêm without context
:
{% include 'users.sls' without context %}
Kiểm soát khoảng trắng
Jinja cung cấp một số cơ chế để kiểm soát khoảng trắng của đầu ra được kết xuất. Theo mặc định, Jinja xóa các dòng mới theo sau và giữ nguyên mọi thứ khác, ví dụ như tab, khoảng trắng và nhiều dòng mới. Bạn có thể tùy chỉnh cách công cụ mẫu Jinja của Salt xử lý khoảng trắng trong tệp cấu hình chính của Salt . Một số tùy chọn môi trường có sẵn để kiểm soát khoảng trắng là:
trim_blocks
: Khi được đặt thànhTrue
, dòng mới đầu tiên sau thẻ mẫu sẽ tự động bị xóa.False
Theo mặc định, tùy chọn này được đặt thành trong Salt.lstrip_blocks
: Khi được đặt thànhTrue
, Jinja sẽ xóa các tab và khoảng trắng từ đầu dòng đến đầu khối. Nếu có các ký tự khác trước khi bắt đầu khối, sẽ không có ký tự nào bị xóa.False
Theo mặc định, tùy chọn này được đặt thành trong Salt.keep_trailing_newline
: Khi được đặt thànhTrue
, Jinja sẽ giữ nguyên các dòng mới theo sau.False
Theo mặc định, tùy chọn này được đặt thành trong Salt.
Để tránh gặp phải lỗi cú pháp YAML, hãy đảm bảo rằng bạn cân nhắc đến hành vi hiển thị khoảng trắng của Jinja khi chèn đánh dấu mẫu vào trạng thái Salt. Hãy nhớ rằng, Jinja phải tạo ra YAML hợp lệ. Khi sử dụng cấu trúc điều khiển hoặc macro, có thể cần phải xóa khoảng trắng khỏi khối mẫu để hiển thị YAML hợp lệ một cách phù hợp.
Để giữ nguyên khoảng trắng của nội dung trong các khối mẫu, bạn có thể đặt cả tùy chọn trim_blocks
và trong tệp cấu hình chính. Bạn cũng có thể bật và tắt thủ công các tùy chọn môi trường khoảng trắng trong mỗi khối mẫu. Một ký tự sẽ đặt hành vi của và thành và một ký tự sẽ đặt các tùy chọn này cho khối:lstrip_block
True
-
trim_blocks
lstrip_blocks
False
+
True
Ví dụ, để xóa khoảng trắng sau phần đầu của cấu trúc điều khiển, hãy thêm một -
ký tự trước phần đóng %}
:
{% for item in [1,2,3,4,5] -%}
{{ item }}
{% endfor %}
Điều này sẽ xuất ra các số 12345
mà không có khoảng trắng ở đầu. Nếu không có -
ký tự, đầu ra sẽ giữ nguyên khoảng cách được xác định trong khối.
Cấu trúc điều khiển
Jinja cung cấp các cấu trúc điều khiển phổ biến cho nhiều ngôn ngữ lập trình như vòng lặp, điều kiện, macro và khối. Việc sử dụng các cấu trúc điều khiển trong trạng thái Salt cho phép kiểm soát chi tiết luồng thực thi trạng thái.
Vòng lặp For
Vòng lặp For cho phép bạn lặp qua danh sách các mục và thực thi cùng một mã hoặc cấu hình cho từng mục trong danh sách. Vòng lặp cung cấp một cách để giảm sự lặp lại trong các trạng thái Salt.
{% set groups = ['sudo','wheel', 'admins'] %}
include:
- groups
jane:
user.present:
- fullname: Jane Doe
- shell: /bin/zsh
- createhome: True
- home: /home/jane
- uid: 4001
- groups:
{%- for group in groups %}
- {{ group }}
{%- endfor -%}
Vòng lặp for trước đó sẽ gán người dùng jane
vào tất cả các nhóm trong groups
danh sách được đặt ở đầu users.sls
tệp.
Điều kiện
Biểu thức điều kiện đánh giá thành hoặc True
hoặc False
và điều khiển luồng của chương trình dựa trên kết quả của biểu thức boolean được đánh giá. Biểu thức điều kiện của Jinja được thêm tiền tố là if
/ elif
/ else
và được đặt trong {% ... %}
dấu phân cách.
{% set users = ['anna','juan','genaro','mirza'] %}
{% set admin_users = ['genaro','mirza'] %}
{% set admin_groups = ['sudo','wheel', 'admins'] %}
{% set org_groups = ['games', 'webserver'] %}
include:
- groups
{% for user in users %}
{{ user }}:
user.present:
- shell: /bin/zsh
- createhome: True
- home: /home/{{ user }}
- groups:
{% if user in admin_users %}
{%- for admin_group in admin_groups %}
- {{ admin_group }}
{%- endfor -%}
{% else %}
{%- for org_group in org_groups %}
- {{ org_group }}
{% endfor %}
{%- endif -%}
{% endfor %}
Trong ví dụ này, sự hiện diện của người dùng trong admin_users
danh sách sẽ xác định nhóm nào được đặt cho người dùng đó trong trạng thái. Tham khảo phần Thực hành tốt nhất của Salt để biết thêm thông tin về việc sử dụng các điều kiện và câu lệnh điều khiển luồng trong tệp trạng thái.
Kế thừa mẫu
Với kế thừa mẫu, bạn có thể định nghĩa một mẫu cơ sở có thể được sử dụng lại bởi các mẫu con. Mẫu con có thể ghi đè các khối được chỉ định bởi mẫu cơ sở.
Sử dụng {% block block_name %}
thẻ có tên khối để xác định vùng của mẫu cơ sở có thể ghi đè.
{% block user %}jane{% endblock %}:
user.present:
- fullname: {% block fullname %}{% endblock %}
- shell: /bin/zsh
- createhome: True
- home: /home/{% block home_dir %}
- uid: 4000
- groups:
- sudo
Ví dụ này tạo ra một mẫu trạng thái người dùng cơ sở. Bất kỳ giá trị nào chứa thẻ đều {% block %}
có thể được ghi đè bởi một mẫu con với giá trị riêng của nó.
Để sử dụng mẫu cơ sở trong mẫu con, hãy sử dụng thẻ {% extends "base.sls"%}
có vị trí của tệp mẫu cơ sở.
{% extends "/srv/salt/users.jinja" %}
{% block fullname %}{{ salt['pillar.get']('jane:fullname', '') }}{% endblock %}
{% block home_dir %}{{ salt['pillar.get']('jane:home_dir', 'jane') }}{% endblock %}
Tệp webserver_users.sls
trạng thái mở rộng users.jinja
mẫu và xác định giá trị cho các khối fullname
và home_dir
. Các giá trị được tạo bằng cách sử dụng salt
biến ngữ cảnh và dữ liệu trụ cột. Phần còn lại của trạng thái sẽ được hiển thị theo user.jinja
cách mẫu cha đã xác định.
Thực hành tốt nhất của muối và Jinja
Nếu Jinja bị sử dụng quá mức, sức mạnh và tính linh hoạt của nó có thể tạo ra các tệp trạng thái Salt không thể bảo trì và khó đọc. Sau đây là một số biện pháp tốt nhất để đảm bảo rằng bạn đang sử dụng Jinja hiệu quả:
- Giới hạn số lượng Jinja bạn sử dụng trong các tệp trạng thái. Tốt nhất là tách dữ liệu khỏi trạng thái sẽ sử dụng dữ liệu. Điều này cho phép bạn cập nhật dữ liệu mà không cần phải thay đổi trạng thái của mình.
- Không lạm dụng điều kiện và vòng lặp trong các tệp trạng thái. Lạm dụng sẽ khiến việc đọc, hiểu và duy trì trạng thái của bạn trở nên khó khăn.
- Sử dụng từ điển biến và tuần tự hóa trực tiếp chúng thành YAML, thay vì cố gắng tạo YAML hợp lệ trong một mẫu. Bạn có thể đưa logic của mình vào từ điển và truy xuất biến cần thiết trong các trạng thái của mình.Thẻ
{% load_yaml %}
sẽ hủy tuần tự hóa các chuỗi và biến được truyền vào nó.
{% load_yaml as example_yaml %}
user: jane
firstname: Jane
lastname: Doe
{% endload %}
{{ example_yaml.user }}:
user.present:
- fullname: {{ example_yaml.firstname }} {{ example_yaml.lastname }}
- shell: /bin/zsh
- createhome: True
- home: /home/{{ example_yaml.user }}
- uid: 4001
- groups:
- games
Sử dụng {% import_yaml %}
để nhập các tệp dữ liệu bên ngoài và làm cho dữ liệu có sẵn dưới dạng biến Jinja.
{% import_yaml "users.yml" as users %}
Sử dụng Salt Pillars để lưu trữ dữ liệu chung hoặc nhạy cảm dưới dạng biến. Truy cập các biến này bên trong tệp trạng thái và tệp mẫu.
Thông tin thêm
Bạn có thể muốn tham khảo các nguồn sau để biết thêm thông tin về chủ đề này. Mặc dù chúng tôi cung cấp với hy vọng rằng chúng sẽ hữu ích, nhưng xin lưu ý rằng chúng tôi không thể đảm bảo tính chính xác hoặc tính kịp thời của các tài liệu được lưu trữ bên ngoài.
Nguồn: https://www.linode.com/docs/guides/introduction-to-jinja-templates-for-salt/