从清单脚本安装Puppet模块。

38
我正在使用Puppet来配置一个Vagrant(基于Ubuntu)虚拟机。 在我的脚本中,我需要:
sudo apt-get build-dep python-lxml

我知道我可以安装 apt puppet模块 以便使用:

apt::builddep { 'python-lxml': }

但是我找不到有关如何从脚本中安装模块以及如何包含/引用它的任何参考资料。对我来说,Puppet文档似乎只涉及从命令行puppet工具安装
我还尝试了类似以下的操作:
define build_dep($pkgname){
    exec {
    "builddepend_$pkgname":
    commmand => "sudo apt-get build-dep $pkgname";
    }
}
build_dep{
    "python-imaging":
    pkgname => "python-imaging";

    "python-lxml":
    pkgname => "python-lxml";
}

但是 Puppet 在此处出现了错误。还有:
exec{"install apt module":

    command => "puppet module install puppetlabs/apt"
}

class { 'apt':
        require => Exec["install apt module"]}
include apt

apt::builddep { 'python-imaging':
 }

但是收到了 无法找到声明的类apt.. 的错误信息。

有什么想法?方向?我知道我错过了一些显而易见的东西,但是想不出来。

编辑:如果我使用命令行预先安装 (puppet module install) apt:builddep 就可以正常工作。 但我需要puppet处理模块下载和安装。其他解决方法对于基本用例也有效,但无法回答我的主要问题。

8个回答

66

我也遇到了这个问题。诀窍是在puppet provisioner运行之前使用vagrant shell命令下载模块。

config.vm.provision :shell do |shell|
  shell.inline = "mkdir -p /etc/puppet/modules;
                  puppet module install puppetlabs/nodejs;
                  puppet module install puppetlabs/apache"
end

config.vm.provision :puppet do |puppet|
  puppet.manifests_path = "puppet/manifests"
  puppet.manifest_file = "site.pp"
end

顺序很重要,由于Puppet配置未运行,因此文件夹/etc/puppet/modules尚不存在。

我像alonisser一样决定使用puppet模块工具安装模块,而不是使用vagrant puppet provisioner的模块文件夹,原因是我不想下载我要使用的所有模块的依赖项并将这些模块存储在我的源代码控制中。运行这两个命令会产生5个依赖项,否则这些依赖项将占用我的git存储库的空间。


13
只要在同一台虚拟机上再次运行配置步骤,它就能正常工作...但是当这样做时,它会出现“模块已安装”的错误。 - Igor Popov
也许如果您像这样使用--force选项puppet module install --force puppetlabs/apache...就不会失败,但它会重新安装模块。如文档所述:“使用--force选项强制重新安装现有模块。”。请参见:http://docs.puppetlabs.com/puppet/2.7/reference/modules_installing.html - Tony
1
--force选项不会安装依赖模块。 - techarch
3
我曾通过在Shell命令外层加上true来绕过多次设置的限制,例如(puppet module install puppetlabs/apache; true),但如果模块因其他原因安装失败,这可能会产生意想不到的后果。 - brain_bacon
7
为了避免第二次执行时出现错误或需要使用--force选项,您可以执行类似于(puppet module list |grep puppetlabs-nodejs ) || (mkdir -p /etc/puppet/modules; puppet module install puppetlabs/nodejs)的命令。(注释中不能有回车符,抱歉) - Iacopo
显示剩余5条评论

14

以下是我采取的方法,以使 puppet module install 命令最多只运行一次:

$script = <<EOF
mkdir -p /etc/puppet/modules
(puppet module list | grep puppetlabs-mysql) ||
   puppet module install -v 2.1.0 puppetlabs/mysql
EOF

Vagrant::Config.run do |config|
   config.vm.provision :shell, :inline => $script

8
我采用了类似于@brain_bacon的方法,但我遇到的额外复杂性是除了像puppetlabs/nodejs这样的预打包模块之外,我还需要相对于我的Vagrantfile使用本地模块。我不想将预打包模块作为我的存储库的一部分进行检查,也不想使用git子模块,因为@Igor Popov指出了其中的问题。
最终我选择了使用Shell脚本来下载这些模块,并将它们的路径强制放置在Vagrant VM和主机之间共享的目录中,并使用.gitignore来避免该路径受到源代码控制。
明确地说,对于这棵树:
jcmendez$ tree
.
├── README.md
├── Vagrantfile
├── files
├── puppet
│   ├── manifests
│   │   └── init.pp
│   └── modules
│       ├── misc
│       │   └── manifests
│       │       └── init.pp
│       ├── mysql
   ...
│       └── wordpress
│           ├── files
│           │   ├── wordpress-db.sql
│           │   ├── wp-config.php
│           │   └── wp-tests-config.php
│           └── manifests
│               └── init.pp
└── wordpress

我在.gitignore文件中添加了以下内容:

  /puppet/modules/mysql

Vagrantfile 文件中
  config.vm.provision :shell do |shell|
    shell.inline = "puppet module install puppetlabs/mysql --force --modulepath '/vagrant/puppet/modules'"
  end

  config.vm.provision :puppet do |puppet|
    puppet.manifests_path = 'puppet/manifests'
    puppet.module_path = 'puppet/modules'
    puppet.manifest_file  = "init.pp"
    puppet.options="--verbose --debug"
  end

2
我按照您的方法(除了我正在尝试安装puppetlab-apache):使用inline shell install命令,但是出现了“Unknown function validate_bool at /tmp/vagrant”的错误提示。这通常是一些依赖项没有安装导致的。您是如何安装apache的? - Maciej Gurban
@DiH - 你说得对,确保阅读每个软件包的所有依赖项,因为当未满足依赖关系时出现的错误消息有点神秘。虽然我没有安装apache2,但我们的设置中有nginx。 - Juan Carlos Méndez

4
您可以在您的vagrantdir主机上安装puppet模块:
puppet module --modulepath=./puppet/modules/ install puppetlabs/mysql

Vagrant会将此目录挂载到正确的位置,因此在节点上除了puppet本身之外不需要运行其他脚本。


不是真的。简单地复制模块可能会给您带来麻烦:在 /tmp/vagrant-puppet/modules-0/postgresql/manifests/params.pp:50 处未知函数 pick。我也遇到了同样的问题,而且它有点不确定性。有时会发生,有时不会。但引用的链接指出,“只是复制模块”是其根本原因。 - sumid

2

受wtanaka.com答案的启发,我实现了以下类似的解决方案,我认为这种方案更易读。

1)在与Vagrantfile相同的文件夹下创建一个名为“puppet_deps.rb”的新ruby文件,其代码如下:

def install_dep(name, version, install_dir = nil)
    install_dir ||= '/etc/puppet/modules'
    "mkdir -p #{install_dir} && (puppet module list | grep #{name}) || puppet module install -v #{version} #{name}"
end

2)在您的 Vagrantfile 中,您可以加载此 Ruby 文件并使用它来指定 Puppet 依赖项:

# on top of your Vagrantfile
require './puppet_deps'
...
...
# in your vm definition, use a shell provisioning this:
config.vm.provision :shell, :inline => install_dep('puppetlabs-firewall', '1.1.3')
config.vm.provision :shell, :inline => install_dep('puppetlabs-stdlib', '4.3.2')

2

@brain_bacon的策略对我来说几乎完美地奏效了,只有一个小问题 - 如果该模块已经存在,则配置脚本会失败,停止配置过程。以下调整解决了这个问题:

config.vm.provision :shell, :run => "always" do |shell|
  shell.inline = %{
    mkdir -p /etc/puppet/modules;
    function install_module {
      folder=`echo $1 | sed s/.*-//`
      if [ ! -d /etc/puppet/modules/$folder ]; then
        puppet module install $1
      fi
    }
    install_module stdlib
    install_module apt
    install_module ruby
  }
end

1
你可以创建一个模块目录,并将从forge下载的apt模块添加到其中。因此它将是modules/apt/*。然后,您可以在Vagrantfile中指定此模块目录(module_path相对于Vagrantfile):
Vagrant.configure("2") do |config|
  config.vm.provision :puppet do |puppet|
    puppet.module_path = "modules"
  end
end

更多信息请参见文档


2
这并没有回答如何在脚本中自动下载和安装模块,而不需要预先下载等的问题。 - alonisser
1
你为什么想这么做呢?Puppet脚本通常包含在vagrant设置中。它们甚至后来也不会在你的VM上可用(至少默认情况下不会,需要另行配置puppet)。 - Michael Härtl

1

使用这个问题的答案,我创建了这个脚本:

#!/bin/bash

function install_module {
   IFS=':' read module version <<< "$1"
   if (puppet module list | grep $module ) >/dev/null; then
    echo "Module $module is already installed"
   else
        if [ -z "$version" ]; then
            puppet module install $module
        else 
        puppet module install -v $version $module
    fi
    fi  
}

if dpkg --compare-versions `puppet --version` "lt" 3.8.7; then
    sudo apt-get remove --purge -y puppet
    sudo apt-get -y autoremove
fi

if which puppet >/dev/null; then
    echo "Puppet is already installed"
else
    echo "Installing puppet"
    wget https://apt.puppetlabs.com/puppetlabs-release-trusty.deb
    sudo dpkg -i puppetlabs-release-trusty.deb
    sudo apt-get update
    sudo apt-get install -y puppet=3.8.7*
    mkdir -p /etc/puppet/modules
fi

for var in "$@" 
do
    install_module "$var"
done

然后您可以像这样从您的Vagrantfile中使用它:

puppet_modules = [
    'puppetlabs-stdlib:4.16.0',
    'puppetlabs-apt:2.3.0',
    'puppet-nodejs:2.3.0'
    ]

config.vm.provision "shell", path: "puppet/scripts/puppet.sh", args: puppet_modules.join(" ")

如果版本低于3.8.7,它会从虚拟机中删除puppet,然后安装puppet 3.8.7,最后安装所有模块。
这可能只适用于debian/ubuntu系统。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接