File: provisioner.rb

package info (click to toggle)
vagrant 2.2.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 8,072 kB
  • sloc: ruby: 80,731; sh: 369; makefile: 9; lisp: 1
file content (140 lines) | stat: -rw-r--r-- 5,237 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
require "log4r"
require "vagrant"

module VagrantPlugins
  module CFEngine
    class Provisioner < Vagrant.plugin("2", :provisioner)
      def provision
        if @machine.config.vm.communicator == :winrm
          raise Vagrant::Errors::ProvisionerWinRMUnsupported,
            name: "cfengine"
        end

        @logger = Log4r::Logger.new("vagrant::plugins::cfengine")

        @logger.info("Checking for CFEngine installation...")
        handle_cfengine_installation

        if @config.files_path
          @machine.ui.info(I18n.t("vagrant.cfengine_installing_files_path"))
          install_files(Pathname.new(@config.files_path).expand_path(@machine.env.root_path))
        end

        handle_cfengine_bootstrap if @config.mode == :bootstrap

        if @config.mode == :single_run
          # Just let people know
          @machine.ui.info(I18n.t("vagrant.cfengine_single_run"))
        end

        if @config.run_file
          @machine.ui.info(I18n.t("vagrant.cfengine_single_run_execute"))
          path = Pathname.new(@config.run_file).expand_path(@machine.env.root_path)
          machine.communicate.upload(path.to_s, @config.upload_path)
          cfagent("-KI -f #{@config.upload_path}#{cfagent_classes_args}#{cfagent_extra_args}")
        end
      end

      protected

      # This runs cf-agent with the given arguments.
      def cfagent(args, options=nil)
        options ||= {}
        command = "/var/cfengine/bin/cf-agent #{args}"

        @machine.communicate.sudo(command, error_check: options[:error_check]) do |type, data|
          if [:stderr, :stdout].include?(type)
            # Output the data with the proper color based on the stream.
            color = type == :stdout ? :green : :red
            @machine.ui.info(
              data,
              color: color, new_line: false, prefix: false)
          end
        end
      end

      # Returns the arguments for the classes configuration if they are
      # set.
      #
      # @return [String]
      def cfagent_classes_args
        return "" if !@config.classes

        args = @config.classes.map { |c| "-D#{c}" }.join(" ")
        return " #{args}"
      end

      # Extra arguments for calles to cf-agent.
      #
      # @return [String]
      def cfagent_extra_args
        return "" if !@config.extra_agent_args
        return " #{@config.extra_agent_args}"
      end

      # This handles checking if the CFEngine installation needs to
      # be bootstrapped, and bootstraps if it does.
      def handle_cfengine_bootstrap
        @logger.info("Bootstrapping CFEngine...")
        if !@machine.guest.capability(:cfengine_needs_bootstrap, @config)
          @machine.ui.info(I18n.t("vagrant.cfengine_no_bootstrap"))
          return
        end

        # Needs bootstrap, let's determine the parameters
        policy_server_address = @config.policy_server_address
        if !policy_server_address
          policy_server_address = @machine.guest.capability(:read_ip_address)
          raise Vagrant::Errors::CFEngineCantAutodetectIP if !policy_server_address
          @machine.ui.info(I18n.t("vagrant.cfengine_detected_ip", address: policy_server_address))
        end

        @machine.ui.info(I18n.t("vagrant.cfengine_bootstrapping",
                                policy_server: policy_server_address))
        result = cfagent("--bootstrap #{policy_server_address}", error_check: false)
        raise Vagrant::Errors::CFEngineBootstrapFailed if result != 0

        # Policy hubs need to do additional things before they're ready
        # to accept agents. Force that run now...
        if @config.am_policy_hub
          @machine.ui.info(I18n.t("vagrant.cfengine_bootstrapping_policy_hub"))
          cfagent("-KI -f /var/cfengine/masterfiles/failsafe.cf#{cfagent_classes_args}")
          cfagent("-KI #{cfagent_classes_args}#{cfagent_extra_args}")
        end
      end

      # This handles verifying the CFEngine installation, installing it
      # if it was requested, and so on. This method will raise exceptions
      # if things are wrong.
      def handle_cfengine_installation
        if !@machine.guest.capability?(:cfengine_installed)
          @machine.ui.warn(I18n.t("vagrant.cfengine_cant_detect"))
          return
        end

        installed = @machine.guest.capability(:cfengine_installed)
        if !installed || @config.install == :force
          raise Vagrant::Errors::CFEngineNotInstalled if !@config.install

          @machine.ui.info(I18n.t("vagrant.cfengine_installing"))
          @machine.guest.capability(:cfengine_install, @config)

          if !@machine.guest.capability(:cfengine_installed)
            raise Vagrant::Errors::CFEngineInstallFailed
          end
        end
      end

      # This installs a set of files into the CFEngine folder within
      # the machine.
      #
      # @param [Pathname] local_path
      def install_files(local_path)
        @logger.debug("Copying local files to CFEngine: #{local_path}")
        @machine.communicate.sudo("rm -rf /tmp/cfengine-files")
        @machine.communicate.upload(local_path.to_s, "/tmp/cfengine-files")
        @machine.communicate.sudo("cp -R /tmp/cfengine-files/* /var/cfengine")
      end
    end
  end
end