Class: Berkshelf::ChefAPILocation

Inherits:
Object
  • Object
show all
Includes:
Location
Defined in:
lib/berkshelf/locations/chef_api_location.rb

Overview

Author:

Constant Summary

Constants included from Location

Location::OPSCODE_COMMUNITY_API

Instance Attribute Summary collapse

Attributes included from Location

#name, #version_constraint

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Location

#downloaded?, included, init, #to_json, #validate_cached

Constructor Details

#initialize(name, version_constraint, options = {}) ⇒ ChefAPILocation

Returns a new instance of ChefAPILocation.

Parameters:

  • name (#to_s)
  • version_constraint (Solve::Constraint)
  • options (Hash) (defaults to: {})

Options Hash (options):

  • :chef_api (String, Symbol)

    a URL to a Chef API. Alternatively the symbol :config can be provided which will instantiate this location with the values found in your Berkshelf configuration.

  • :node_name (String)

    the name of the client to use to communicate with the Chef API. Default: Chef::Config

  • :client_key (String)

    the filepath to the authentication key for the client Default: Chef::Config



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
# File 'lib/berkshelf/locations/chef_api_location.rb', line 84

def initialize(name, version_constraint, options = {})
  @name               = name
  @version_constraint = version_constraint
  @downloaded_status  = false

  if options[:chef_api] == :knife
    Berkshelf.formatter.deprecation "specifying 'chef_api :knife' is deprecated. Please use 'chef_api :config'."
    options[:chef_api] = :config
  end

  validate_options!(options)

  if options[:chef_api] == :config
    unless Berkshelf::Config.instance.chef.node_name.present? &&
      Berkshelf::Config.instance.chef.client_key.present? &&
      Berkshelf::Config.instance.chef.chef_server_url.present?
      raise ConfigurationError, "A Berkshelf configuration is required with a 'chef.client_key', 'chef.chef_server_Url', and 'chef.node_name' setting to install or upload cookbooks using 'chef_api :config'."
    end
    @node_name  = Berkshelf::Config.instance.chef.node_name
    @client_key = Berkshelf::Config.instance.chef.client_key
    @uri        = Berkshelf::Config.instance.chef.chef_server_url
  else
    @node_name  = options[:node_name]
    @client_key = options[:client_key]
    @uri        = options[:chef_api]
  end

  @rest = Chef::REST.new(uri, node_name, client_key)
end

Instance Attribute Details

#client_keyObject (readonly)

Returns the value of attribute client_key.



68
69
70
# File 'lib/berkshelf/locations/chef_api_location.rb', line 68

def client_key
  @client_key
end

#node_nameObject (readonly)

Returns the value of attribute node_name.



67
68
69
# File 'lib/berkshelf/locations/chef_api_location.rb', line 67

def node_name
  @node_name
end

#uriObject (readonly)

Returns the value of attribute uri.



66
67
68
# File 'lib/berkshelf/locations/chef_api_location.rb', line 66

def uri
  @uri
end

Class Method Details

.validate_client_key(client_key) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


26
27
28
# File 'lib/berkshelf/locations/chef_api_location.rb', line 26

def validate_client_key(client_key)
  File.exists?(client_key)
end

.validate_client_key!(client_key) ⇒ Object



33
34
35
36
37
38
39
# File 'lib/berkshelf/locations/chef_api_location.rb', line 33

def validate_client_key!(client_key)
  unless validate_client_key(client_key)
    raise InvalidChefAPILocation
  end

  true
end

.validate_node_name(node_name) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


8
9
10
# File 'lib/berkshelf/locations/chef_api_location.rb', line 8

def validate_node_name(node_name)
  node_name.is_a?(String) && !node_name.empty?
end

.validate_node_name!(node_name) ⇒ Object



15
16
17
18
19
20
21
# File 'lib/berkshelf/locations/chef_api_location.rb', line 15

def validate_node_name!(node_name)
  unless validate_node_name(node_name)
    raise InvalidChefAPILocation
  end

  true
end

.validate_uri(uri) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


44
45
46
# File 'lib/berkshelf/locations/chef_api_location.rb', line 44

def validate_uri(uri)
  uri =~ URI.regexp(['http', 'https'])
end

.validate_uri!(uri) ⇒ Object

Raises:

See Also:



52
53
54
55
56
57
58
# File 'lib/berkshelf/locations/chef_api_location.rb', line 52

def validate_uri!(uri)
  unless validate_uri(uri)
    raise InvalidChefAPILocation, "'#{uri}' is not a valid Chef API URI."
  end

  true
end

Instance Method Details

#download(destination) ⇒ Berkshelf::CachedCookbook

Parameters:

  • destination (#to_s)

Returns:



117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/berkshelf/locations/chef_api_location.rb', line 117

def download(destination)
  version, uri = target_version
  scratch = download_files(download_manifest(uri))

  cb_path = File.join(destination, "#{name}-#{version}")
  FileUtils.mv(scratch, cb_path)

  cached = CachedCookbook.from_store_path(cb_path)
  validate_cached(cached)

  set_downloaded_status(true)
  cached
end

#latest_versionArray

Returns an array where the first element is a string representing the latest version of the Cookbook and the second element is the download URL for that version.

Examples:

[ "0.101.2" => "https://api.opscode.com/organizations/vialstudios/cookbooks/nginx/0.101.2" ]

Returns:

  • (Array)


164
165
166
167
168
169
170
171
172
173
# File 'lib/berkshelf/locations/chef_api_location.rb', line 164

def latest_version
  graph = Solve::Graph.new
  versions.each do |version, url|
    graph.artifacts(name, version)
  end

  version = Solve.it!(graph, [name])[name]

  [ version, versions[version] ]
end

#to_hashObject



175
176
177
# File 'lib/berkshelf/locations/chef_api_location.rb', line 175

def to_hash
  super.merge(value: self.uri)
end

#to_sObject



179
180
181
# File 'lib/berkshelf/locations/chef_api_location.rb', line 179

def to_s
  "#{self.class.location_key}: '#{uri}'"
end

#versionsHash

Returns a hash representing the cookbook versions on at a Chef API for location’s cookbook. The keys are version strings and the values are URLs to download the cookbook version.

Examples:

{
  "0.101.2" => "https://api.opscode.com/organizations/vialstudios/cookbooks/nginx/0.101.2",
  "0.101.5" => "https://api.opscode.com/organizations/vialstudios/cookbooks/nginx/0.101.5"
}

Returns:

  • (Hash)


141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/berkshelf/locations/chef_api_location.rb', line 141

def versions
  {}.tap do |versions|
    rest.get_rest("cookbooks/#{name}").each do |name, data|
      data["versions"].each do |version_info|
        versions[version_info["version"]] = version_info["url"]
      end
    end
  end
rescue Net::HTTPServerException => e
  if e.response.code == "404"
    raise CookbookNotFound, "Cookbook '#{name}' not found at chef_api: '#{uri}'"
  else
    raise
  end
end