【问题标题】:How can I use a Chef resource within a library module? (Or should I...)?如何在库模块中使用 Chef 资源? (或者我应该……)?
【发布时间】:2014-05-26 02:45:19
【问题描述】:

我正在尝试通过在帮助程序库中收集常见的 Ruby 逻辑来更好地组织一些 Chef 食谱。我已经看到在库中声明一个类(即类 Chef::Recipe::MyHelper)的示例,其中包含一些可重用的方法。我还看到了以类似方式使用模块的示例。就我而言,我想在其中一些方法中使用资源。

例如,假设我想提供一个辅助方法,该方法采用一组服务名称并循环使用服务资源停止每个服务名称。我想尽可能多地清理配方文件,并通过调用“stopServices(serviceList)”方法来保留一些逻辑。

如果我像这样定义帮助程序库:

class Chef::Recipe::MyHelper
  def self.stopServices(serviceList)
    serviceList.each do |svc|
      service "#{svc}" do
        action :stop
      end
    end
  end
end

然后在我的食谱中我使用:

MyHelper.stopServices(serviceList)

我收到错误消息:“Chef::Recipe::MyHelper:Class 的未定义方法‘服务’”。

有没有一种简单的方法可以像这样使用库中的资源? (库是否包含 MyHelper 作为类或模块)?这只是我违反的一种不良做法吗?我做了很多搜索,找不到任何人问类似的问题,这让我相信我可能正在做一些我不应该做的事情,所以任何替代建议也将不胜感激。

【问题讨论】:

    标签: chef-infra chef-recipe


    【解决方案1】:

    Libraries 是一种从食谱食谱中抽象出复杂 Ruby 代码的方法。

    要对资源(Chef DSL 代码)进行分组,您应该使用任一

    • Definitions(最简单的选项)您可以像在食谱中使用常规厨师资源一样使用它;或
    • LWRPs 更复杂但支持不同的操作(想想service 可以使用:start:stop:restart 等的资源;或者package 可以使用:install:upgrade 的资源, :remove 等)。

    更新

    可以解决您的示例问题的定义:

    # cookbooks/common/definitions/common_stop_services.rb
    define :common_stop_services, :services => [] do
      params[:services].each do |svc|
        service svc do
          action :stop
        end
      end
    end
    

    然后像这样使用它:

    # my_cookbook/recipes/my_recipe.rb
    common_stop_services "my_recipe_services" do
      services [ 'svc1', 'svc2' ]
    end
    

    Obs:如果你真的想用一个通用的方法来包装多个服务停止,可能值得问问自己。通常服务操作由其他资源通知(经典示例是配置文件更改通知重新配置的服务重新启动,但其他模式也适用)。

    Obs2:CamelCase 仅用于 Ruby 代码中的 ClassesModules。我推荐阅读style guide

    Obs3:即使您要在库中实现该代码,您也可能不想使用Class。你永远不会实例化MyHelper,所以你想要的是Module

    【讨论】:

    • 感谢您的回复,我认为 LWRP 是我长期发展的方式。在短期内,我仍然想知道我正在尝试做的事情是否可行。为了清理食谱,我将许多这些方法移到“通用”食谱中的库文件中,并使其他需要它们的食谱依赖于该食谱。我没有费心将方法包装在一个类或模块中,它工作得很好,就像上面写的一样,只是没有类行(和“自我”),但仍然从库中的方法调用资源。
    • 我想将它包装在一个类中作为最佳实践,以避免污染默认命名空间,并通过“MyHelper.stopServices”使其他配方中方法的来源更加明显而不仅仅是“stopServices”。似乎唯一的问题是,当我将它包装在一个类中时,它假定服务资源是该类的一部分。所以这似乎是一个简单的命名空间问题,但我没有尝试修复它。有什么方法可以完全限定资源名称或以其他方式指定它是什么以便以这种方式使用它?
    • 再次,您正在颠覆使用库来执行 Chef DSL 调用。通过声明一个名称不会让您知道它来自何处的类(也许Common 会是一个更好的名称,因为它会匹配它的食谱?),您也不会让它更清楚。我已经编辑了我的答案,以演示如何为您的问题实施定义。我还添加了一些观察结果,从长远来看可能会对您有所帮助。
    • 谢谢,我很欣赏这个例子。我显然有很多东西要学,但这个定义很有帮助。我将研究如何更好地利用 LWRP 并通知需要停止/启动的服务资源。
    猜你喜欢
    • 1970-01-01
    • 2022-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-30
    • 2015-12-11
    相关资源
    最近更新 更多