دسته‌ها
ابزارها برنامه نویسی پایتون لینوکس

آموزش انسیبل برای دوآپس – قسمت سوم از بخش اول

در این قسمت ما در خصوص فایلهای YAML که به کمک آنها در آینده Palybook های انسیبل خود را صحبت خواهیم کرد.

تاکنون اینونتوریها(Inventories) و ماژولهای مرسوم(Common Modules) انسیبل را آموختیم. اکنون باید به مباحث پیشرفته تری از «انسیبل» بپردازیم. 

در قسمت صفرم اشاره کردیم که انسیبل یک فریم‌ورک قدرتمند برای اوتوماسیون ماشینهای یونیکسی و ویندوزی است. انسیبل با بهره گیری از از مفهومی به اسم پلی‌بوک(‌Playbook) و همچنین قابلیت ماژولار خود و البته از انعطاف زبان پایتون و yaml هم بهره میبرد تا مطابق با دستور العمل خاصی سلسله وظایف مشخصی را بر روی یک تا n هاست انجام دهد. در این قسمت ما بصورت جداگانه به زبان Yaml خواهیم پرداخت.

YAML – YAML Ain’t Markup Language

از آنجایی که «انسیبل» با زبان «پایتون» نوشته شده است میتوانیم از پایتون استفاده کنیم برای اینکه با مفاهیم YAML آشنا بشویم. البته ابزارهای دیگری هم برای تایید سینتکس yaml شما موجود هستند اما ما از روش پایتونیک و ساده تری بهره میبریم. 

function yamlpy() { python -c 'import sys,yaml,pprint;pprint.pprint(yaml.load(open(sys.argv[1]).read(), Loader=yaml.FullLoader))' $1 }

وقتی که دستور بالا را کپی کنید و در ترمینال خود اجرا کنید میتوانید از دستور yamlpy استفاده کنید و مسیر فایل yaml خود را بصورت آرگومان به دستور بدهید تا در خروجی ساختار فایل را بصورت آبجکتهای پایتونی به شما نمایش دهد. با این روش میخواهیم ببینیم که انسیبل چه نوع دیتا و دیتاهایی را پردازش خواهد کرد. 

  •  ساختار YAML فایلها

مهم ترین نکته در مورد YAML فایلها ابتدایی ترین نقطه آن است. هر yaml فایل با سه خط منهی ” --- ” در خط اول شروع میشود و با سه نقطه ” ... ” در خط آخر به اتمام میرسد. کامنت کردن در YAML هم با کارکتر # امکان پذیر است.

$ cat revisions/01_03_yaml/01/test.yml
---

# Every YAML file should end with three dots
...

اما اگر این فایل را با دستور yamlpy مورد بررسی قرار دهیم خواهیم دید که از منظر انسیبل(در واقع زبان پایتون) مقدرا None بازگردانده خواهد شد.

$ yamlpy revisions/01_03_yaml/01/test.yml
None

در بازبینی دوم فایل YAML حاوی دو آیتم است:

$ cat revisions/01_03_yaml/02/test.yml
---

key_1: first value
key_2: second value

# Every YAML file should end with three dots
...

این نوع از دیتا به Key/Value مشهور است. در این مثال کلید یک key_1 و کلید دو key_2 و مقادیر آنها first value و second value هستند. اگر این فایل را با دستور yamlpy اجرا کنیم خروجی به شکل دیکشنری خواهد بود. در ادامه به تفصل در مورد دیکشنری ها و لیستها صحبت خواهیم کرد.

$ yamlpy revisions/01_03_yaml/02/test.yml
{'key_1': 'first value', 'key_2': 'second value'}

 

  • گیومه – “Double”, ‘Single’

در زبان YAML برای ایجاد یک متغیر String سه روش وجود دارد. بدون گیومه، با گیومه تگی و با گیومه دوتایی. در بازبینی سوم این سه روش قابل مشاهده است. 

$ cat revisions/01_03_yaml/03/test.yml
---

no_quotes: this is a string example
double_quotes: "this is a string example"
single_quotes: 'this is a string example'

# Every YAML file should end with three dots
...

برای مشاهده  آنها از منظر پایتون از ابزار yamlpy استفاده میکنیم:

yamlpy revisions/01_03_yaml/03/test.yml

$ yamlpy revisions/01_03_yaml/03/test.yml
{'double_quotes': 'this is a string example',
 'no_quotes': 'this is a string example',
 'single_quotes': 'this is a string example'}

همانگونه که مشاهده میکنید مقادیر هر کلید با یک Single Quote مشخص شده است.
در بازبینی چهارم تغییر کوچی ایجاد کرده‌ایم. در انتهای هر خط یک کارکتر خاص به سر خط /n اضافه کردیم. این کارکتر خاص شامل یک کارکتر اسکیپ یعنی / و یک کارکتر خط جدید (سر خط) یعنی n .

$ cat revisions/01_03_yaml/04/test.yml
---

no_quotes: this is a string examplen
double_quotes: "this is a string examplen"
single_quotes: 'this is a string examplen'

# Every YAML file should end with three dots
...

اما نکته مهم اینجاست که این کارکتر اسکیپ در مدل بدون گیومه و تک گیومه به عنوان یک کارکتر اسکیپ کد تفسیر نخواهد شد. به خروجی زیر توجه کنید:

$ yamlpy revisions/01_03_yaml/04/test.yml
{'double_quotes': 'this is a string examplen',
 'no_quotes': 'this is a string examplen',
 'single_quotes': 'this is a string examplen'}

به همین دلیل توصیه میشود زمانی که نیاز به استفاده از کارکتر اسکیپ دارید از “Double Quote” استفاده کنید.

  • متغیرهای چند خطی – Multiline variable

اما هم اکنون که در مورد Strings صحبت میکنم شاید بد نباشد اگر به Multilines Strings هم اشاره کنیم. در بازبینی پنجم از کارکتر پایپ | استفاده شده است اما رشته در چنید خط در پی هم نوشته شده است:

$ cat revisions/01_03_yaml/05/test.yml
---

key_1: |
  this is a string
  that goes over
  multiple lines

# Every YAML file should end with three dots
...

اما اگر از ابزار yamlpy برای بررسی فایل استفاده کنیم تمام رشته را در یک خط خواهیم داشت در حالی که هر خط با کارکتر خاص n از هم جدا شده است.

$ yamlpy  revisions/01_03_yaml/05/test.yml
{'key_1': 'this is a stringnthat goes overnmultiple linesn'}

در بازبینی ششم اما بجای کارکتر پایپ از کارکتر بزرگتر > استفاده کرده ایم:

$ cat revisions/01_03_yaml/06/test.yml
---

example_key_1: >
  this is a string
  that goes over
  multiple lines

# Every YAML file should end with three dots
...

همانگونه که در پایین ملاحظه میکنید تفاوت بزرگ کارکتر پایپ با کارکتر بزرگتر در اضافه کردن کارکتر خط جدید /n به مقدار متغیر است:

yamlpy  revisions/01_03_yaml/06/test.yml
{'example_key_1': 'this is a string that goes over multiple linesn'}

در زمانهایی که مقدار متغیر ما از نوع رشته طولانی و دارای کلمات زیادی است، میتوانیم از این روش بهره ببریم تا کدهای yaml ما شکیل‌تر بشوند.
اما اگر دقت کنید در مثال بالا هم در انتهای رشته یک کارکتر /n قابل رویت است. گاهی ما نیاز داریم که این کارکتر در انسیبل تفسیر نشود. به بازبینی هفتم بریم:

$ cat revisions/01_03_yaml/07/test.yml
---

example_key_1: >-
  this is a string
  that goes over
  multiple lines

# Every YAML file should end with three dots
...

در اینجا برای حذف /n در انتها بعد از کارکتر بزرگتر از یک - استفاده میکنیم. خروجی زیر را مشاهده کنید:

$ yamlpy  revisions/01_03_yaml/07/test.yml
{'example_key_1': 'this is a string that goes over multiple lines'}

اما برای تعریف کردن یک متغیر از نوع اینتجر به صورت خودکار تفسیر میشود. برای مثال در پوشه بازبینی هشتم فایل test.yml را مشاهده کنید:

cat revisions/01_03_yaml/08/test.yml
---

example_integer: 1

# Every YAML file should end with three dots
...

و خروجی آن در دستور yamlpy که قبلا برای تایید فایلهای yaml خود تعریف کرده‌ایم:

yamlpy  revisions/01_03_yaml/08/test.yml
{'example_integer': 1}

قبل از این هم اشاره کردیم که در تفسیر متغیرها در انسیبل همانند پایتون است(در واقع پایتون است که با استفاده از ماژول yaml فایلهای yaml و متغیرهای تعریف شده در آن را تفسیر میکند). بنابراین اگر نیاز باشد که عددی از نوع رشته به یک متغیر منسوب کنیم از گیومه استفاده خواهیم کرد:

cat revisions/01_03_yaml/09/test.yml
---

example_integer: "1"

# Every YAML file should end with three dots
...

و طبیعتا در خروجی دستور yamlpy این مقدار با گیومه مشخص شده است:

yamlpy  revisions/01_03_yaml/09/test.yml
{'example_integer': '1'}
  • بولین در انسیبل – True/False

در بازبینی دهم ما تقریبا همه روشهایی که میشود مقدار True و یا False را به یک متغیر منسوب کنیم را پوشش داده‌ایم:

cat revisions/01_03_yaml/10/test.yml
---

# false, False, FALSE, no, No, NO, off, Off, OFF
# true, True, TRUE, yes, Yes, YES, on, On, ON

# n.b. n does not equal false, y does not equal true

is_false_01: false
is_false_02: False
is_false_03: FALSE
is_false_04: no
is_false_05: No
is_false_06: NO
is_false_07: off
is_false_08: Off
is_false_09: OFF
is_false_10: n
is_true_01: true
is_true_02: True
is_true_03: TRUE
is_true_04: yes
is_true_05: Yes
is_true_06: YES
is_true_07: on
is_true_08: On
is_true_09: ON
is_true_10: y

# Every YAML file should end with three dots
...

نکته بسیار مهمی در خط هفتم این فایل بصورت کامنت مشخص شده است. در yaml برای تعریف کردن مقدار Ture نمیشود از y و همچنین برای تعریف کردن مقدار False نمیشود از n استفاده کرد. در این صورت پایتون آنها را به عنوان یک رشته که حاوی که یک کارکتر است تفسیر میکند. خروجی زیر بیانگر این ادعا است:

$ yamlpy  revisions/01_03_yaml/10/test.yml
{'is_false_01': False,
 'is_false_02': False,
 'is_false_03': False,
 'is_false_04': False,
 'is_false_05': False,
 'is_false_06': False,
 'is_false_07': False,
 'is_false_08': False,
 'is_false_09': False,
 'is_false_10': 'n',
 'is_true_01': True,
 'is_true_02': True,
 'is_true_03': True,
 'is_true_04': True,
 'is_true_05': True,
 'is_true_06': True,
 'is_true_07': True,
 'is_true_08': True,
 'is_true_09': True,
 'is_true_10': 'y'}

همانگونه که میبنید کلید های is_false_10 و is_true_10 یک رشته را به عنوان مقدار خود در نظر گرفته. توصیه میشود برای عدم ابهام در کدهای انسیبل از مقدار True و یا False استفاده کنید.

  • لیستها و دیکشنریهاLists and Dictionaries

تا کنون ما در همه فایلهای yaml خود از دیتا نوع دیشکنری استفاده کردیم. طبیعتا برای تعریف یک دیشنری به یک کلید و مقدار آن نیاز بود در مثالها به کرار مورد استفاده قرار گرفته. اما در بازبینی یازدهم میبینم که تعیریف کردن متغیر از نوع لیسن به چه صورت است.

$ cat revisions/01_03_yaml/11/test.yml
---
# Every YAML file should start with three dashes

- item 1
- item 2
- item 3
- item 4
- item 5

# Every YAML file should end with three dots
...

در واقع برای تعریف کرد لیسن میتوان از کارکتر - استفاده کرد و مقدار بعد از آن عنصر عضو آن لیست خواهد بود:

$ yamlpy revisions/01_03_yaml/11/test.yml
['item 1', 'item 2', 'item 3', 'item 4', 'item 5']

اما برای تعریف کردن دیکشنری نکته مهم استفاده از کارکتر : بعد از کلید بود. به بازبینی دوازدهم دقت کنید:

$ cat revisions/01_03_yaml/12/test.yml
---

example_key_1: example_value_1
example_key_2: example_value_2

# Every YAML file should end with three dots
...

و خروجی:

$ yamlpy revisions/01_03_yaml/12/test.yml
{'example_key_1': 'example_value_1', 'example_key_2': 'example_value_2'}

اما نکته قابل تامل در انسیبل و استفاده از سینتکس yaml در بازبینی سیزدهم پوشش داده شده:

$ cat revisions/01_03_yaml/13/test.yml
---

{example_key_1: example_value_1, example_key_2: example_value_2}

# Every YAML file should end with three dots
...

همانگونه که مشاهده میکنید این امکان وجود دارد که از سینتکس زبان پایتون برای تعریف کردن متغیرهای از انواع مختلف استفاده کرد. در پایتون برای تعیرف کردن یک دیکشنری از کارترهای {} استفاده میشود. خروجی بیانگر این ادعا است:

$ yamlpy revisions/01_03_yaml/13/test.yml
{'example_key_1': 'example_value_1', 'example_key_2': 'example_value_2'}

دقیقا متغیرهای لیست هم از این قائده مستثنی نیستند. به بازبینی چهاردهم برویم:

$ cat revisions/01_03_yaml/14/test.yml
---

[example_list_entry_1, example_list_entry_2]

# Every YAML file should end with three dots
...

و خروجی:

$ yamlpy revisions/01_03_yaml/14/test.yml
['example_list_entry_1', 'example_list_entry_2']

  • فاصله گذاری – Indentation

اما زبان yaml هم مانند زبانهای مرسوم از قانون و قوانین خاص خود در خصوص فاصله گذاری تبعیت میکند. متغیرهای دیکشنری و لیست مثال خوبی برای توضیح این موضوع است. به بازبینی پانزدهم بریم:

$ cat revisions/01_03_yaml/15/test.yml
---

example_key_1: example_value_1
- example_list_entry_1

# Every YAML file should end with three dots
...

در مثال بالا یک دیکشنری و یک لیست در یک سطح تعریف کرده‌ایم. مسئله دقیقا اینجاست که از نظر yaml این نا معتبر است.
حتی اگر بصورت پایتونیک هم دو نوع متفاوت از دیتا را در یک سطح تعیرف کیند باز هم نا معتبر خواهد بود. بازبینی شانزدهم مثالی از این نمونه است:

$ cat revisions/01_03_yaml/16/test.yml
---

{example_key_1: example_value_1}
[example_list_entry_1]

# Every YAML file should end with three dots
...

از آنجایی که زبان yaml برای نگه داری انوع دیتا طراحی شده است، در نظر میگرد که در هر سطح از میبایست یک نوع دیتا در نظر گرفته شود. برای سطح بندی میشود همانند پایتون از فاصله گذاری استفاده کرد. و این فاصله گذاری ( یا تورفتگی ) باید از یک الگوی مشترک در کل فایل تبعیت کنید. مرسوم است از دو کارکتر space برای سطح بندی استفاده شود. شما میتوانید الگوی خود را داشته باشید، اما اگر قصد دارید کدهای خود را بصورت عمومی منتشر کنید توصیه میشود از همان دو کارکتر space به ازای هر سطح استفاده کنید.

اما همانند پایتون این امکان وجود دارد یک دیتا از نوع لیست مقدار یک کلید دیکشنری باشد. برای نمونه به بازبینی هفدهم برویم:

$ cat revisions/01_03_yaml/17/test.yml
---

example_key_1:
  - list item 1
  - list item 2

example_key_2:
  - list item 3
  - list item 4

# Every YAML file should end with three dots
...

در این مثال یک دیکشنری داریم که داری دو کلید است و هر کلید یک لیست به عنوان مقدار در خود دارد که هر کدام از این لیست‌ها شامل دو عنصر است:

yamlpy revisions/01_03_yaml/17/test.yml
{'example_key_1': ['list item 1', 'list item 2'],
 'example_key_2': ['list item 3', 'list item 4']}

در بازبینی هجدهم مدل کمی پیچیده تر مثال زده شده است.

cat revisions/01_03_yaml/18/test.yml
---

- example_1:
  - item_1
  - item_2
  - item_3

- example_2:
  - item_4
  - item_5
  - item_6

# Every YAML file should end with three dots
...

در این مثال یک لیست شامل دو عنصر که هر عنصر یک دیکشنری است و هر دیکشنری یک کلید دارد که مقدار آن برابر با یک لیست است. لیست مولود شامال سه عنصر از نوع رشته است:

$ yamlpy revisions/01_03_yaml/18/test.yml
[{'example_1': ['item_1', 'item_2', 'item_3']},
 {'example_2': ['item_4', 'item_5', 'item_6']}]

در بازبینی نوزدهم باز هم سعی شده تا یک مثال نسبتا پیچیده تر آورده شود:

$ cat revisions/01_03_yaml/19/test.yml
---

example_dictionary_1:
  - example_dictionary_2:
    - 1
    - 2
    - 3
  - example_dictionary_2:
    - 4
    - 5
    - 6
  - example_dictionary_4:
    - 7
    - 8
    - 9

# Every YAML file should end with three dots
...

در این مدل در بالاترین سطح یک دیکشنری داریم که شامل یک کلید است. مقدار این کلید یک لیست که سه عنصر دارد و هر عنصر یک دیکشنری است. این دیکشنری خود شامل یک کلید است که مقدار آن یک لیست با سه عنصر اینتجر است.

$ yamlpy revisions/01_03_yaml/19/test.yml
{'example_dictionary_1': [{'example_dictionary_2': [1, 2, 3]},
                          {'example_dictionary_2': [4, 5, 6]},
                          {'example_dictionary_4': [7, 8, 9]}]}

در این مثال ما تا پنج سطح به عمق رفته ایم. ۱- دیشکنری، ۲- لیست ، ۳- دیکشنری و ۴- لیست و در آخرین سطح عناصر لیست که از نوع اینتیجر هستند.

در بازبینی بیستم برای درک بهتر ساختار یک فایل yaml من لیستی از چهار کارگردان محبوبم را تهیه کرده ام:

cat revisions/01_03_yaml/20/test.yml
---

- Clint Eastwood
- Quentin Tarantino
- Martin Scorsese
- Mohsen Makhmalbaf

# Every YAML file should end with three dots
...

که خروجی آن در دستور yamlpy یقینا به صورت زیر خواهد بود:

$ yamlpy revisions/01_03_yaml/20/test.yml
['Clint Eastwood', 'Quentin Tarantino', 'Martin Scorsese', 'Mohsen Makhmalbaf']

در بازبینی بیست و یک همین لیست کارگردان‌ها را کمی تغییر داده‌ایم:

cat revisions/01_03_yaml/21/test.yml
---

- Clint Eastwood:
    Born: 1930
    Best Movie: Million Dollar Baby
- Quentin Tarantino:
    Born: 1963
    Best Movie: Pulp Fiction
- Martin Scorsese:
    Born: 1942
    Best Movie: Casino
- Mohsen Makhmalbaf:
    Born: 1957
    Best Movie: Sex & Philosophy

# Every YAML file should end with three dots
...

عناصر لیست (کارگردانها) اکنون خود کلید یک دیکشنری هستند که مقدار آنها یک دیکشنری دیگر شامل دو کلید یکی سال تولد و دیگری بهتری اثرشان از نظر نگارنده است:

$ yamlpy revisions/01_03_yaml/21/test.yml
[{'Clint Eastwood': {'Best Movie': 'Million Dollar Baby', 'Born': 1930}},
 {'Quentin Tarantino': {'Best Movie': 'Pulp Fiction', 'Born': 1963}},
 {'Martin Scorsese': {'Best Movie': 'Casino', 'Born': 1942}},
 {'Mohsen Makhmalbaf': {'Best Movie': 'Sex & Philosophy', 'Born': 1957}}]

در بازبینی بیست و دوم یک مثال پیچیده تر آورده شده:

cat revisions/01_03_yaml/22/test.yml
---

- Aston Martin:
    year_founded: 1913
    website: astonmartin.com
    founded_by:
      - Lionel Martin
      - Robert Bamford
- Fiat:
    year_founded: 1899
    website: fiat.com
    founded_by:
      - Giovanni Agnelli
- Ford:
    year_founded: 1903
    website: ford.com
    founded_by:
      - Henry Ford
- Vauxhall:
    year_founded: 1857
    website: vauxhall.co.uk
    founded_by:
      - Alexander Wilson

# Every YAML file should end with three dots
...

لطفا با دستور yamlpy این فایل را از بازبینی ۲۲ بررسی و آنالیز کنید و در صورت تمایل به عنوان تمرین در کامنت توضیح خود را بنویسید و یا به ایمیل من ارسال کنید.

لینک قسمتهای قبلی این سری آموزش به شرح ذیل است:

  1. صفرم – مقدمه و فرآهم آوردن محیط آزمایشگاه
  2. بخش اول قسمت اول – همه چیز در رابطه با اینونتوری‌ها (Ansible Inventories)
  3. بخش اول قسمت دوم – انسیبل هوشمند و ماژولار است (Ansible Madules)

7 دیدگاه دربارهٔ «آموزش انسیبل برای دوآپس – قسمت سوم از بخش اول»

سلام. ممنون از پیامتون
تو تمیرن ازتون خواستم با برنامه yamlpy فایل test.yml را بررسی کنید و به من بگید در چند سطح دیتاها تو رفتند و جنسشون چیه؟ اینجوری میتونم تک بدونم چقدر از مطالب براتون واضح بود و اگه نیاز به توضیحات تکمیلی باشه توضیح میدم.
لطفا بعد از اینکه تمرین را حل کردین برام پیام یا ایمیل بفرستید.

پاسخ

سلام دوست عزیز.
در حال تهیه هستم! بزودی منتشر میکنم. ممنون از پیگیریتون که بهم انگیزه میده.

پاسخ

پاسخی بگذارید