### 使用純 Ruby 代碼書寫配置清單
你會說西班牙語嗎?學習一門語言可能會很有趣,但并非所有人都想這么做。 Puppet 有時會因為它使用自己專用的配置語言而不是現存的通用語言(如 Ruby)書寫配置清單而遭到批評。
不是每個人都認為這是個缺點。計算機科學家 Dennis Ritchie 說:
> A language that doesn’t have everything is actually easier to program in than some that do.
>
> — Dennis Ritchie
無論你是什么觀點,這種批評已不再適用。因為 Puppet 已經擁有了使用 Ruby 語言書寫配置清單的實驗性支持,這在生產環境上是相當有用的,即使還處于早期開發階段。 在你的配置清單中可以混合使用兩種語言,Puppet 以文件擴展名進行區別,擴展名 .rb 表示用 Ruby 語言書寫的配置清單文件,而擴展名 .pp 表示 Puppet 專用的配置語言文件。
為了書寫配置清單使用的 Ruby 的 **特定領域語言**(**domain-specific language,DSL**) 看上去與標準的 Puppet 語言非常相似。 在下面的例子中,我將向你展示如何將典型的 Puppet 配置清單轉換成 Ruby 的。 Puppet 語法的原始配置清單如下:
```
class admin::exim {
package { "exim4": ensure => installed }
service { "exim4":
ensure => running,
require => Package["exim4"],
}
file { "/etc/exim4/exim4.conf":
content => template("admin/exim4.conf"),
notify => Service["exim4"],
require => Package["exim4"],
}
}
```
#### 操作步驟
1. 使用如下內容創建 /etc/puppet/modules/admin/manifests/exim.rb 文件:
```
hostclass "admin::exim" do
package "exim4", :ensure => :installed
service "exim4",
:ensure => :running,
:require => "Package[exim4]"
file "/etc/exim4/exim4.conf",
:content => template(["admin/exim4.conf"]),
:notify => "Service[exim4]",
:require => "Package[exim4]"
end
```
2. 在一個節點中包含這個類并運行 Puppet。
#### 工作原理
1. 關鍵字 hostclass 聲明一個類,就像 Puppet 中的 class:hostclass admin::exim do
2. 然后跟一個 do … end 語句塊,這相當于 Puppet 的一對大括號。
3. 通過在資源類型后調用函數來聲明資源: 例如 package 或 service:package "exim4", :ensure => :installed
4. 傳遞給函數的參數是一個用逗號分割的列表,參數必須要用雙引號括起來, 或者在參數前使用前導的冒號使其成為 Ruby symbol 對象: :ensure => :running,
又如,像 :installed 或 :running 這樣的 Puppet 內置名字都是 Ruby 的 symbol 對象。
|  | 譯者注
有關 Ruby Symbol 的詳細介紹請參考: [http://www.ibm.com/developerworks/cn/opensource/os-cn-rubysbl/](http://www.ibm.com/developerworks/cn/opensource/os-cn-rubysbl/)
|
5. 當我們需要引用資源來表示相互關系時,就要使用 :require, 資源標識符通過首字母大寫的資源類型跟上寫在一對方括號中的資源名給出,例如: require => "Package[exim4]"
在調用像模板這樣的函數時可以使用函數名跟一對圓括號,在圓括號中傳遞的參數是 一對用方括號聲明的數組,例如::content => template(["admin/exim4.conf"]),。
#### 更多用法
Ruby DSL 尚處于早期開發階段。試驗雖然有趣,除非你有使用 Ruby 的令人信服的理由否則先別用它, 至今我仍舊使用標準的 Puppet 語言。或許將來 Ruby DSL 會被廣泛應用,但在此期間, 你會發現沒有它的生活會更輕松。然而,若你堅持要使用它,下面介紹幾個非常有用的提示。
##### 變量
當你像常規的 Ruby 程序一樣使用 Ruby 變量時,可以使用 scope.lookupvar 訪問你的 Puppet 變量,例如:
```
notice( "I am running on node %s" % scope.lookupvar("fqdn") )
```
將得到:
```
notice: I am running on node cookbook.bitfieldconsulting.com
```
要在你的 Puppet 配置清單范圍內設置變量,使用 scope.setvar,例如:
```
require 'time'
scope.setvar("now", Time.now)
notice( "At the third stroke, the time sponsored by Bitfield
Consulting will be: %s" % scope.lookupvar("now") )
```
上面的代碼將獲得如下結果:
```
notice: At the third stroke, the time sponsored by Bitfield Consulting
will be: Wed Mar 23 05:58:16 -0600 2011
```
##### 文檔
你可以在 Puppet Labs 網站找到更多如何使用 Ruby DSL 的詳細資料,包括諸如 **virtual resources** 和 **collections** 這樣的高級主題: [http://projects.puppetlabs.com/projects/1/wiki/Ruby_Dsl](http://projects.puppetlabs.com/projects/1/wiki/Ruby_Dsl) 。
Ken Barber 提供了一些語法例子,并對 Puppet 語法和 Ruby DSL 結構做了比較,網址在 [https://github.com/bobsh/puppet-rubydsl-examples](https://github.com/bobsh/puppet-rubydsl-examples) 。
最后,James Turnbull 發布過一篇 blog, 展示了使用 Ruby 連接 MySQL 服務器的高級方法: [http://www.puppetlabs.com/blog/using-ruby-inthe-puppet-ruby-dsl/](http://www.puppetlabs.com/blog/using-ruby-inthe-puppet-ruby-dsl/) 。
- Puppet 2.7 Cookbook 中文版
- 中文翻譯版
- 譯者序
- 項目緣起
- 翻譯方法
- 社區鏈接
- 社區建議
- 貢獻者
- 原書版權頁
- 關于作者
- 前言
- 本書內容
- 閱讀前提
- 適用讀者
- 格式約定
- 讀者反饋
- 客戶支持
- 下載案例代碼
- 勘誤表
- Puppet 基礎設施
- 使用版本控制
- 使用提交鉤子
- 使用 Rake 部署變更
- 配置 Puppet 的文件服務器
- 從 cron 運行 Puppet
- 使用自動簽名
- 預簽名證書
- 從 Puppet 的 filebucket 檢索文件
- 使用 Passenger 擴展 Puppet 的部署規模
- 創建去中心化的分布式 Puppet 架構
- 監控、報告和排錯
- 生成報告
- 通過 Email 發送包含特定標簽的日志信息
- 創建圖形化報告
- 自動生成 HTML 文檔
- 繪制依賴關系圖
- 測試你的 Puppet 配置清單
- 執行模擬運行
- 檢測編譯錯誤
- 理解 Puppet 的錯誤信息
- 顯示命令的輸出結果
- 輸出調試信息
- 檢查配置設置
- 使用標簽
- 使用運行階段
- 使用不同的環境
- Puppet 語言及其寫作風格
- 使用 Puppet 社區規范
- 使用模塊
- 使用標準的命名規范
- 使用嵌入式 Ruby 代碼
- 使用純 Ruby 代碼書寫配置清單
- 遍歷多個項目
- 書寫強大的條件語句
- 在 if 語句中使用正則表達式
- 使用選擇器和 case 語句
- 檢測字符串中是否包含指定的值
- 使用正則表達式替換
- 書寫更優質的配置清單
- 使用資源的數組
- 使用 define 資源
- 指定資源的依賴關系
- 使用節點繼承
- 使用類的繼承和重載
- 給類傳遞參數
- 書寫可重用的跨平臺配置清單
- 獲得系統的環境信息
- 導入動態信息
- 從 CSV 文件導入數據
- 給 Shell 命令傳遞參數
- 使用文件和軟件包
- 為配置文件添加配置行
- 使用 Augeas 自動修改配置文件
- 使用配置片段構建配置文件
- 使用 ERB 模板
- 在模板中遍歷數組
- 從第三方倉庫安裝軟件包
- 配置 APT 軟件倉庫
- 配置 GEM 倉庫
- 從源碼包自動構建軟件
- 比較軟件包的版本
- 用戶和虛擬資源
- 使用虛擬資源
- 使用虛擬資源管理用戶
- 管理用戶基于密鑰的 SSH 訪問
- 管理用戶的自定義文件
- 有效地分發 cron 任務
- 當文件更新時運行命令
- 使用主機資源
- 為文件資源指定多個源
- 使用文件資源遞歸地分發整個目錄樹
- 清理過期的舊文件
- 使用日程表資源
- 資源的審計
- 臨時禁用資源
- 管理時區
- 應用程序
- 管理 Apache 服務
- 創建 Apache 虛擬主機
- 創建 Nginx 虛擬主機
- 創建 MySQL 數據庫及用戶
- 管理 Drupal 站點
- 管理 Rails 應用程序
- 服務器和云基礎設施
- 部署 Nagios 監控服務器
- 使用 Heartbeat 構建高可用服務
- 管理 NFS 服務和文件共享
- 使用 HAProxy 為多個 web 服務器實現負載均衡
- 使用 iptables 管理防火墻
- 管理 Amazon 的 EC2 實例
- 使用 Vagrant 管理虛擬機
- 外部工具和 Puppet 生態環境
- 創建 Facter 的自定義 fact
- 在運行 Puppet 之前和之后執行命令
- 從 Shell 會話生成 Puppet 配置清單
- 從運行的系統上生成 Puppet 配置清單
- 使用 Puppet Dashboard
- 使用 Foreman
- 使用 MCollective
- 使用公共模塊
- 使用外部節點分類器
- 創建自定義的資源類型
- 創建自定義的提供者