

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 範例 5：使用屬性
<a name="cookbooks-101-basics-attributes"></a>

**重要**  
 AWS OpsWorks Stacks 此服務已於 2024 年 5 月 26 日終止，並已針對新客戶和現有客戶停用。我們強烈建議客戶盡快將其工作負載遷移至其他解決方案。如果您對遷移有任何疑問，請透過 [AWS re：Post](https://repost.aws/) 或透過 [AWS Premium Support](https://aws.amazon.com/support) 聯絡 AWS 支援 團隊。

除平台之外，前面各節中的配方針對所有項目都使用硬式編碼值。這種方法很麻煩，例如，當您想要在多個配方中使用相同的值時。您可以在技術指南中包含屬性檔案，從配方分別定義值。

屬性檔案是將值指派給一或多個屬性的 Ruby 應用程式。它必須位在技術指南的 `attributes` 資料夾。Chef 將屬性併入到節點物件，而所有配方可以透過參考屬性使用這些屬性值。本主題示範如何修改[重複](cookbooks-101-basics-ruby.md#cookbooks-101-basics-ruby-iteration)中的配方來使用這些屬性。下列是供參考的原始配方。

```
[ "/srv/www/config", "/srv/www/shared" ].each do |path|
  directory path do
    mode 0755
    owner 'root'
    group 'root'
    recursive true
    action :create
  end
end
```

下列定義子目錄名稱、模式、擁有者和群組值的屬性。

```
default['createdir']['shared_dir'] = 'shared'
default['createdir']['config_dir'] = 'config'
default['createdir']['mode'] = 0755
default['createdir']['owner'] = 'root'
default['createdir']['group'] = 'root'
```

注意下列事項：
+ 每個定義都是以「屬性類型」**開始。

  如果屬性定義超過一次，可能是在不同屬性檔案中，屬性類型會指定屬性的優先順序，這會決定哪個定義會併入節點物件。如需詳細資訊，請參閱[屬性優先順序](workingcookbook-attributes-precedence.md)。本範例中的所有定義均有 `default` 屬性類型，這是此用途的一般類型。
+ 屬性有巢狀名稱。

  節點物件基本上是可任意深度嵌套的雜湊表，所以屬性名稱可以是、也普遍是巢狀的。此屬性檔案遵循使用巢狀名稱的標準實務，以技術指南名稱 `createdir` 為第一個元素。

使用 createdir 為屬性第一個元素的原因是，當您執行 Chef 執行時，Chef 會將每個技術指南的屬性納入節點物件。使用 OpsWorks Stacks，除了您定義的任何屬性之外，節點物件還包含[來自內建技術指南](https://github.com/aws/opsworks-cookbooks)的大量屬性。在屬性名稱中包含技術指南名稱，可降低與其他技術指南屬性名稱發生衝突的風險，特別是當您的屬性名稱類似 `port` 或 `user` 時。除非您想要覆寫該屬性的值，否則請不要將屬性命名為類似 [`[:apache2][:user]`](attributes-recipes-apache.md#attributes-recipes-apache-user)。如需詳細資訊，請參閱[使用自訂技術指南屬性](workingcookbook-cookbook-attributes.md)。

下列範例顯示使用屬性的原始配方，不是使用硬式編碼值。

```
[ "/srv/www/#{node['createdir']['shared_dir']}", "/srv/www/#{node['createdir']['config_dir']}" ].each do |path|
  directory path do
    mode node['createdir']['mode']
    owner node['createdir']['owner']
    group node['createdir']['group']
    recursive true
    action :create
  end
end
```

**注意**  
如果您想要將屬性值納入字串中，請用 `#{}` 括住它。在上述範例中，`#{node['createdir']['shared_dir']}` 會將 "shared" 附加到 "/srv/www/" 的後面。

**執行配方**

1. 執行 `kitchen destroy` 以從乾淨的執行個體開始。

1. 以前述的配方範例取代 `recipes/default.rb` 中的程式碼。

1. 建立名為 `createdir` 的 `attributes` 子目錄，並新增包含屬性定義之名為 `default.rb` 的檔案。

1. 編輯 `.kitchen.yml` 將 CentOS 從平台清單中移除。

1. 執行 `kitchen converge`，然後登入執行個體，驗證 `/srv/www/shared` 和 `/srv/www/config` 是否在此。

**注意**  
透過 OpsWorks Stacks，將值定義為屬性可提供額外的優點；您可以使用[自訂 JSON](workingstacks-json.md) 來覆寫每個堆疊或甚至每個部署的這些值。這是適用於各種用途，包括：  
您可以自訂您的配方行為，例如組態設定或使用者名稱，不必修改技術指南。  
例如，您可以在不同的堆疊使用相同的技術指南，使用自訂 JSON 指定特定堆疊的關鍵組態設定。這可節省您修改技術指南或為每個堆疊使用不同技術指南所需的時間和心力。
您不必將資料庫密碼等可能的敏感資訊放在技術指南儲存庫。  
您可以改用屬性定義預設值，然後使用自訂的 JSON 以真實的值覆寫該值。
如需如何使用自訂 JSON 覆寫屬性的詳細資訊，請參閱[覆寫屬性](workingcookbook-attributes.md)。

如果是相當簡單的名稱，此屬性檔案名為 `default.rb`，因為它是 Ruby 應用程式。例如，這表示您可以根據作業系統，使用條件式邏輯指定屬性值。在[條件式邏輯](cookbooks-101-basics-ruby.md#cookbooks-101-basics-ruby-conditional)中，您已在配方中為不同的 Linux 系列指定不同的子目錄名稱。使用屬性檔案，您可以改將條件式邏輯放在屬性檔案中。

下列屬性檔案使用 `value_for_platform` 指定不同的 `['shared_dir']` 屬性值，視作業系統而定。其他條件可以使用 Ruby `if-elsif-else` 邏輯或 `case` 陳述式。

```
data_dir = value_for_platform(
  "centos" => { "default" => "shared" },
  "ubuntu" => { "default" => "data" },
  "default" => "user_data"
)
default['createdir']['shared_dir'] = data_dir
default['createdir']['config_dir'] = "config"
default['createdir']['mode'] = 0755
default['createdir']['owner'] = 'root'
default['createdir']['group'] = 'root'
```

**執行配方**

1. 執行 `kitchen destroy` 從全新的執行個體開始。

1. 以前述範例取代 `attributes/default.rb` 中的程式碼。

1. 編輯 `.kitchen.yml` 將 CentOS 平台新增到平台部分，如[條件式邏輯](cookbooks-101-basics-ruby.md#cookbooks-101-basics-ruby-conditional)中所述。

1. 執行 `kitchen converge`，然後登入執行個體，驗證目錄是否在此。

完成後，請執行 `kitchen destroy` 終止執行個體。下一個範例會使用新的技術指南。