Chef Sugar旨在提高Chef食谱的编写体验

Chef Sugar是Chef的一个扩展,它提供了DSL方法能够让你编写更加可读的食谱(recipe)。Seth Vargo是Chef Sugar的作者,他写出了自己创建Chef Sugar的动机并通过示例做了强调。InfoQ采访了Seth以期了解他对语法糖以及Chef上下文中插件架构优点的看法。

Chef Sugar在一些区域提供了DSL方法,例如云(例如Cloud?ec2?)或者平台(例如ubuntu?centos?)。额外帮助方法的添加正在讨论中。Seth在自己的文章中展示了一个示例,该示例对使用和没有使用Chef Sugar的食谱做了对比。下面这段程序:

include_recipe 'cookbook::_windows_setup' if platform_family?('windows')  
include_recipe 'cookbook::_ec2_setup' if node['ec2'] || node['eucalyptus']

package 'foo' do  
  action :nothing
end.run_action(:install)

execute 'untar package' do  
  if node['kernel']['machine'] == 'x86_64'
    command 'ARCH_FLAGS=x64 make'
  else
    command 'ARCH_FLAGS=i386 make'
  end
  not_if do
    ::File.exists?('/bin/tool') &&
    ::File.executable?('/bin/tool') &&
    shell_out!('/bin/tool --version').stdout.strip == node['tool']['version']
  end
end

credentials = Chef::EncryptedDataBagItem.load('accounts', 'passwords') 

可以被转换成如下的这段:

include_recipe 'cookbook::_windows_setup' if windows?  
include_recipe 'cookbook::_ec2_setup' if ec2? || eucalyptus?

compile_time do  
  package 'apache2'
end

execute 'untar package' do  
  if _64_bit?
    command 'ARCH_FLAGS=x64 make'
  else
    command 'ARCH_FLAGS=i386 make'
  end
  not_if { installed_at_version?('/bin/tool', node['tool']['version']) }
end

credentials = encrypted_data_bag_item('accounts', 'passwords')	

Chef Sugar是为了在一个食谱中访问而特意编写的,同时它还是一个Chef类库,你可以将任意的Ruby代码包含在食谱中。唯一重要的区别是当它作为一个类库被使用的时候,Chef Sugar的方法需要一个节点对象(node object)参数。

# cookbook/libraries/default.rb
def only_on_windows(&block)  
  yield if Chef::Sugar::PlatformFamily.windows?(@node)
end 

InfoQ:有些时候语法糖会被看作是一些没有用处、不重要的东西。但是既然你创建了一个名为Chef Sugar的项目,那么很显然你并不认为事情总是如此。你认为哪些时候有一点语法糖是好的,哪些时候语法糖有点多?

我认为Ruby(和Rails)之所以会在开发人员之间如此成功的首要原因之一就是语法糖。例如,ActiveSupport向Ruby的整数类型添加了语法糖,让它能够执行像5.days.ago这样的调用。在降低复杂性和重复性方面语法糖有让人难以置信的用处。许多菜谱(cookbooks)会分享共同的习语或者模式——例如检查是否安装了特定版本的软件。当我看到这种类型的模式出现的时候,我知道是时候去涂上一些糖了。

但是,我并不会积极地寻找领域去“加糖”。我认为这是人们常犯的一个错误。按照我的观点,当逻辑分支或者组件多于两个的时候语法糖就做了过多的事情。例如,开发人员能够很容易地编写一个包装了一个逻辑和资源分支的语法糖,但是最好的方式是将它作为一个类库或者LWRP提供。语法糖应该可以很容易地测试和维护,同时新手开发者应该可以仔细分析定义语法糖的方法。

InfoQ:一般来说,这种类型的特性应该存在于一个应用程序的核心中或者最好是将它们作为“插件”,你认为是这样吗?为什么?

我是插件架构模式的忠实拥护者。我能够很容易地将Chef Sugar添加到Chef核心中,但是我还是有意识地保持它的独立性。就像我们不应该强制一个Ruby开发人员使用ActiveSupport一样,我们也不能强制一个Chef开发者使用Chef Sugar。

从可维护性的角度来看,将Chef Sugar作为一个独立的gem能够让我的工作和迭代独立于Chef的发布周期。Ruby本身就采用了这种插件模式,它将核心的Ruby类迁移到了gems。Rubinius 2.0完全由gems组成。就像一个分布式系统相对于一个完全统一的应用程序所具有的优势那样,使用基于插件的模式比将组件绑定到核心框架中具有同样的优势。这种模式也存在于Vagrant Knife(Chef的CLI)及Rubygems这样的工具中。

但是,还有一种中庸之道,那就是将插件锁定并捆绑到一个特定版本的核心中(作为一个依赖),即便如此这些插件也是存在于框架的外部作为一个独立的资源。用户可能会在任意时间选择更新到最新版本的插件,也可能会等着升级完整的软件包。Ruby 2.0就遵循这种模式。如果试图卸载bigdecimal,那么你将会得到下面的错误:

ERROR:  While executing gem ... (Gem::InstallError)
    gem "bigdecimal" cannot be uninstalled because it is a default gem

但是Ruby开发者能够在任意时间选择升级到一个新版本的bigdecimal。

最后一件要考虑的事情(经常会被我们忽视)是许可的影响。对于Chef Sugar而言,Chef和Chef Sugar两者都是基于Apache 2.0许可发布的,所以这并不是问题。有些时候我们不能将一个插件捆绑到核心应用程序中,因为它可能并不允许转售,或者涉及到专利等问题。

InfoQ:Chef中是否还有一些其他的领域可以从附加的Chef Sugar方法中受益?

正如我前面所说的,我并不会积极寻找领域去“加糖”。在我第一次发布Chef Sugar的时候,它非常受大家欢迎。在短短的20分钟之内就有一个社区成员添加了FreeBSD平台的支持。然后这个项目度过了两个月没有任何维护的日子(它能“工作”)。大约在一个月之前,有一些人添加了Cloudstack支持。

我非常骄傲自己能够快速承认并合并拉请求,所以我一直都鼓励大家提交自己的想法。当我认为某个补丁超出了项目目标的时候,我也不怕对它说不。如果一个社区成员发现了一个应该“加糖”的领域,那么我会非常高兴地去看看在哪!

InfoQ: Chef中的哪些最重要的部分能够从更多的社区参与中受益?

Chef的所有问题都能从Chef软件的报修系统上追踪到。大部分问题都是被分类并按优先级排序的。对于新社区成员而言,被标记为“不重要”或者“微调”的问题可能涉及到最小的变化,同时也是深入Chef核心的一个非常好的方式。最后,永远都不要低估印刷或者语法规则修复的能量。因为随着Chef变得越来越流行,非英语背景的用户也可能会查阅这些文档。

此外,有一个针对Chef RFC的开源GitHub项目。社区也反馈了一些针对Chef路线图中的高层特性或者变化的建议。该仓库中的拉请求就极大地受益于社区参与(即使它仅仅是一个简单的:+1:)。

除了Chef核心软件项目之外,Chef社区在去年11月份还向COOK项目(Chef维护的社区食谱)提交了一些重要的改变。Chef担负着社区食谱和Chef社区成员之间共享的责任。

查看英文原文:Chef Sugar Aims to Enhance Chef's Recipes Authoring Experience

你可能感兴趣的:(Chef Sugar旨在提高Chef食谱的编写体验)