Module: Vagrant::CapabilityHost

Included in:
Guest, Host, Plugin::V2::Provider, Plugin::V2::SyncedFolder
Defined in:
lib/vagrant/capability_host.rb

Overview

This module enables a class to host capabilities. Prior to being able to use any capabilities, the initialize_capabilities! method must be called.

Capabilities allow small pieces of functionality to be plugged in using the Vagrant plugin model. Capabilities even allow for a certain amount of inheritance, where only a subset of capabilities may be implemented but a parent implements the rest.

Capabilities are used heavily in Vagrant for host/guest interactions. For example, "mount_nfs_folder" is a guest-OS specific operation, so capabilities defer these operations to the guest.

Instance Method Summary collapse

Instance Method Details

#capability(cap_name, *args) ⇒ Object

Executes the capability with the given name, optionally passing more arguments onwards to the capability. If the capability returns a value, it will be returned.

Parameters:

  • cap_name (Symbol)

    Name of the capability



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/vagrant/capability_host.rb', line 94

def capability(cap_name, *args)
  cap_mod = capability_module(cap_name.to_sym)
  if !cap_mod
    raise Errors::CapabilityNotFound,
      cap:  cap_name.to_s,
      host: @cap_host_chain[0][0].to_s
  end

  cap_method = nil
  begin
    cap_method = cap_mod.method(cap_name)
  rescue NameError
    raise Errors::CapabilityInvalid,
      cap: cap_name.to_s,
      host: @cap_host_chain[0][0].to_s
  end

  args = @cap_args + args
  @cap_logger.info(
    "Execute capability: #{cap_name} #{args.inspect} (#{@cap_host_chain[0][0]})")
  cap_method.call(*args)
end

#capability?(cap_name) ⇒ Boolean

Tests whether the given capability is possible.

Parameters:

  • cap_name (Symbol)

    Capability name

Returns:

  • (Boolean)


85
86
87
# File 'lib/vagrant/capability_host.rb', line 85

def capability?(cap_name)
  !capability_module(cap_name.to_sym).nil?
end

#capability_host_chainArray<Array<Symbol, Class>>

Returns the chain of hosts that will be checked for capabilities.

Returns:

  • (Array<Array<Symbol, Class>>)


77
78
79
# File 'lib/vagrant/capability_host.rb', line 77

def capability_host_chain
  @cap_host_chain
end

#initialize_capabilities!(host, hosts, capabilities, *args) ⇒ Object

Initializes the capability system by detecting the proper capability host to execute on and building the chain of capabilities to execute.

Parameters:

  • host (Symbol)

    The host to use for the capabilities, or nil if we should auto-detect it.

  • hosts (Hash<Symbol, Array<Class, Symbol>>)

    Potential capability hosts. The key is the name of the host, value[0] is a class that implements #detect? and value[1] is a parent host (if any).

  • capabilities (Hash<Symbol, Hash<Symbol, Class>>)

    The capabilities that are supported. The key is the host of the capability. Within that is a hash where the key is the name of the capability and the value is the class/module implementing it.



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
# File 'lib/vagrant/capability_host.rb', line 30

def initialize_capabilities!(host, hosts, capabilities, *args)
  @cap_logger = Log4r::Logger.new(
    "vagrant::capability_host::#{self.class.to_s.downcase}")

  if host && !hosts[host]
    raise Errors::CapabilityHostExplicitNotDetected, value: host.to_s
  end

  if !host
    host = autodetect_capability_host(hosts, *args) if !host
    raise Errors::CapabilityHostNotDetected if !host
  end

  if !hosts[host]
    # This should never happen because the autodetect above uses the
    # hosts hash to look up hosts. And if an explicit host is specified,
    # we do another check higher up.
    raise "Internal error. Host not found: #{host}"
  end

  name      = host
  host_info = hosts[name]
  host      = host_info[0].new
  chain     = []
  chain << [name, host]

  # Build the proper chain of parents if there are any.
  # This allows us to do "inheritance" of capabilities later
  if host_info[1]
    parent_name = host_info[1]
    parent_info = hosts[parent_name]
    while parent_info
      chain << [parent_name, parent_info[0].new]
      parent_name = parent_info[1]
      parent_info = hosts[parent_name]
    end
  end

  @cap_host_chain = chain
  @cap_args       = args
  @cap_caps       = capabilities
  true
end