Class: Vagrant::BoxMetadata

Inherits:
Object
  • Object
show all
Defined in:
lib/vagrant/box_metadata.rb

Overview

BoxMetadata represents metadata about a box, including the name it should have, a description of it, the versions it has, and more.

Defined Under Namespace

Classes: Provider, Version

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io, **_) ⇒ BoxMetadata

Loads the metadata associated with the box from the given IO.

Parameters:

  • io (IO)

    An IO object to read the metadata from.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/vagrant/box_metadata.rb', line 25

def initialize(io, **_)
  begin
    @raw = JSON.load(io)
  rescue JSON::ParserError => e
    raise Errors::BoxMetadataMalformed,
      error: e.to_s
  end

  @raw ||= {}
  @name = @raw["name"]
  @description = @raw["description"]
  @version_map = (@raw["versions"] || []).map do |v|
    begin
      [Gem::Version.new(v["version"]), Version.new(v)]
    rescue ArgumentError
      raise Errors::BoxMetadataMalformedVersion,
        version: v["version"].to_s
    end
  end
  @version_map = Hash[@version_map]
end

Instance Attribute Details

#descriptionString

The long-form human-readable description of a box.

Returns:

  • (String)


19
20
21
# File 'lib/vagrant/box_metadata.rb', line 19

def description
  @description
end

#nameString

The name that the box should be if it is added.

Returns:

  • (String)


14
15
16
# File 'lib/vagrant/box_metadata.rb', line 14

def name
  @name
end

Instance Method Details

#compatible_version_update?(current_version, new_version, **opts) ⇒ Boolean

Returns:

  • (Boolean)


122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/vagrant/box_metadata.rb', line 122

def compatible_version_update?(current_version, new_version, **opts) 
  return false if Gem::Version.new(new_version) <= Gem::Version.new(current_version)

  architecture = opts[:architecture]
  provider = opts[:provider]
  # If the specific provider isn't available, there is nothing further to check for compatibility
  return true if provider.nil?

  # If the current_provider isn't found in the metadata, it cannot be compared against. Default to allowing updates
  current_provider  = version(current_version.to_s, provider: provider, architecture: architecture)&.provider(provider, architecture)
  return true if current_provider.nil? 

  # If the new provider isn't found, the new version isn't compatible
  new_provider = version(new_version.to_s, provider: provider, architecture: architecture)&.provider(provider, architecture)
  return false if new_provider.nil?

  # Disallow updates from a known architecture to an unknown architecture, because it can not be verified, unless architecture is explicitly set to `nil`
  return false if !architecture.nil? &&  new_provider.architecture == "unknown" && current_provider.architecture != "unknown"

  # New version is compatible
  return true
end

#version(version, **opts) ⇒ Version

Returns data about a single version that is included in this metadata.

Parameters:

  • version (String)

    The version to return, this can also be a constraint.

  • [Symbol, (Hash)

    a customizable set of options

  • [Symbol] (Hash)

    a customizable set of options

Returns:

  • (Version)

    The matching version or nil if a matching version was not found.



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

def version(version, **opts)
  requirements = version.split(",").map do |v|
    Gem::Requirement.new(v.strip)
  end

  providers = nil
  providers = Array(opts[:provider]).map(&:to_sym) if opts[:provider]
  # NOTE: The :auto value is not expanded here since no architecture
  #       value comparisons are being done within this method
  architecture = opts.fetch(:architecture, :auto)

  @version_map.keys.sort.reverse.each do |v|
    next if !requirements.all? { |r| r.satisfied_by?(v) }
    version = @version_map[v]
    valid_providers = version.providers

    # If filtering by provider(s), apply filter
    valid_providers &= providers if providers

    # Skip if no valid providers are found
    next if valid_providers.empty?

    # Skip if no valid provider includes support
    # the desired architecture
    next if architecture && valid_providers.none? { |p|
      version.provider(p, architecture)
    }

    return version
  end

  nil
end

#versions(**opts) ⇒ Object

Returns all the versions supported by this metadata. These versions are sorted so the last element of the list is the latest version. Optionally filter versions by a matching provider.

@return[Array]

Parameters:

  • [Symbol, (Hash)

    a customizable set of options

  • [Symbol] (Hash)

    a customizable set of options



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/vagrant/box_metadata.rb', line 100

def versions(**opts)
  architecture = opts[:architecture]
  provider = Array(opts[:provider]).map(&:to_sym) if opts[:provider]

  # Return full version list if no filters provided
  if provider.nil? && architecture.nil?
    return @version_map.keys.sort.map(&:to_s)
  end

  # If a specific provider is not provided, filter
  # only on architecture
  if provider.nil?
    return @version_map.select { |_, version|
      !version.providers(architecture).empty?
    }.keys.sort.map(&:to_s)
  end

  @version_map.select { |_, version|
    provider.any? { |pv| version.provider(pv, architecture) }
  }.keys.sort.map(&:to_s)
end