如何在不更改 .rb 文件的情况下通过 Vagrantfile 扩展 vagrant 插件?

How to extend a vagrant plugin through Vagrantfile without changing the .rb file?

我在 Vagrant 中遇到过这种情况,我想使用 ansible_local 插件修补在 RHEL 8 上安装 ansible 的方式(由于存储库设置导致缺少软件包的某些问题)。所以这就是事情。相反,我想使用 pip3(虽然我知道我可以使用 ansible_local 模块来使用 pip,但由于缺少某些存储库之后它仍然出错,所以我想出了一种修复它的方法)。

在我的 Vagrantfile 中,我有这些行,

.....
      node.vm.provision "ansible_local" do |ansible|
        ansible.playbook = ansible_playbook
        ansible.verbose = true
        ansible.install = true
        ## Actually this line doesn't suffice my problem since it still errs as pip requires other packages. Please check the *.rb file below
        if i == 100
            ansible.install_mode = "pip"
            ansible.version = "2.9"
            #ansible.ansible_rpm_install = Foo
        end
      end
...
.....

但是因为使用pip还是不行,所以我最后改了文件/opt/vagrant/embedded/gems/2.2.9/gems/vagrant-2.2.9/plugins/provisioners/ansible/cap/guest/redhat/ansible_install.rb,我就是这样,


cap/guest/redhat/ansible_install.rb
require_relative“../事实”
require_relative“../pip/pip”

模块 VagrantPlugins
  模块 Ansible
    模组帽
      模块来宾
        红帽模块
          模块 AnsibleInstall

            def self.ansible_install(机器, install_mode, ansible_version, pip_args, pip_install_cmd = "")
              案例 install_mode
              什么时候:点子
                pip_setup 机器,pip_install_cmd
                Pip::pip_install 机器,"ansible",ansible_version,pip_args,真
              当:pip_args_only
                pip_setup 机器,pip_install_cmd
                Pip::pip_install 机器,“”,“”,pip_args,错误
              别的
                <strong>
                // 我快速添加的部分 fix/solution
                如果 machine.config.vm.box == "generic/rhel8"
                   ansible_rpm_install_rhel8 机器
                elsif
                   ansible_rpm_install 机器
                结尾
                </strong>
              结尾
            结尾

            私人的

            def self.ansible_rpm_install(机器)
              rpm_package_manager = Facts::rpm_package_manager(机器)

              epel = machine.communicate.execute "#{rpm_package_manager} repolist epel | grep -q epel", error_check: false
              如果 epel != 0
                machine.communicate.sudo 'sudo rpm -i https://dl.fedoraproject.org/pub/epel/epel-release-latest-`rpm -E %dist | sed -n \'s/.*el\([0-9]\).*//p\'`.noarch.rpm'
              结尾
              machine.communicate.sudo "#{rpm_package_manager} -y --enablerepo=epel install ansible"
            结尾

            def self.pip_setup(机器, pip_install_cmd = "")
              rpm_package_manager = Facts::rpm_package_manager(机器)

              machine.communicate.sudo("#{rpm_package_manager} -y 安装 curl gcc libffi-devel openssl-devel python-crypto python-devel python-setuptools")
              Pip::get_pip 机器,pip_install_cmd
            结尾

            def self.pip_setup(机器, pip_install_cmd = "")
              rpm_package_manager = Facts::rpm_package_manager(机器)

              machine.communicate.sudo("#{rpm_package_manager} -y 安装 curl gcc libffi-devel openssl-devel python-crypto python-devel python-setuptools")
              Pip::get_pip 机器,pip_install_cmd
            结尾

            <strong>
            // 我快速添加的部分 fix/solution
            def self.ansible_rpm_install_rhel8(机器)
              rpm_package_manager = Facts::rpm_package_manager(机器)

              epel = machine.communicate.execute "#{rpm_package_manager} repolist epel | grep -q epel", error_check: false
              如果 epel != 0
                machine.communicate.sudo 'sudo rpm -i https://dl.fedoraproject.org/pub/epel/epel-release-latest-`rpm -E %dist | sed -n \'s/.*el\([0-9]\).*//p\'`.noarch.rpm'
              结尾
              machine.communicate.sudo "dnf -y update; dnf -y install python3 python3-pip; pip3 install ansible"
            结尾
            </strong>
            
          结尾
        结尾
      结尾
    结尾
  结尾
结尾

所以我添加了一个方法 self.ansible_rpm_install_rhel8(machine) 并在框名称为 "generic/rhel8" 时做了一个 if..elsif 作为解决方案。这实际上对我来说很完美。但是,我不喜欢这种方法,即更改文件 /opt/vagrant/embedded/gems/2.2.9/gems/vagrant-2.2.9/plugins/provisioners/ansible/cap/guest/redhat/ansible_install.rb 因为一旦它更改或版本升级,它就会消失。有没有更好的方法可以让我只在 Vagrantfile 中执行此操作,这样可能会覆盖或扩展 class 本身?我不知道该怎么做。

欢迎提出任何想法。

谢谢!

您可以一个接一个地使用多个配置部分,这些部分将按照您在 Vagrantfile 中定义的顺序执行。

与其修补插件,不如尝试相应地准备你的 ansible 执行。

在执行ansible的provisioning部分之前,执行shell provisioning如下:

Vagrant.configure("2") do |node|

    # ...

    node.vm.provision :shell, path: "fix_repo_and_add_packages.sh"

    node.vm.provision "ansible_local" do |ansible|
        ansible.playbook = ansible_playbook
        ansible.verbose = true
        ansible.install = true
        ## Actually this line doesn't suffice my problem since it still errs as pip requires other packages. Please check the *.rb file below
        if i == 100
            ansible.install_mode = "pip"
            ansible.version = "2.9"
            #ansible.ansible_rpm_install = Foo
        end
    end

end

您的 fix_repo_and_add_packages.sh 包含缺少的存储库的设置,您也可以在此处添加包。

有关 shell 配置的更多信息,您可以在 doc

中找到