Class: Puppet::Indirector::Request

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/indirector/request.rb

Overview

This class encapsulates all of the information you need to make an Indirection call, and as a result also handles REST calls. It’s somewhat analogous to an HTTP Request object, except tuned for our Indirector.

API:

  • public

Constant Summary collapse

OPTION_ATTRIBUTES =

trusted_information is specifically left out because we can’t serialize it and keep it “trusted”

API:

  • public

[:ip, :node, :authenticated, :ignore_terminus, :ignore_cache, :instance, :environment]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(indirection_name, method, key, instance, options = {}) ⇒ Request

Returns a new instance of Request.

API:

  • public



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/puppet/indirector/request.rb', line 119

def initialize(indirection_name, method, key, instance, options = {})
  @instance = instance
  options ||= {}

  self.indirection_name = indirection_name
  self.method = method

  options = options.inject({}) { |hash, ary| hash[ary[0].to_sym] = ary[1]; hash }

  set_attributes(options)

  @options = options

  if key
    # If the request key is a URI, then we need to treat it specially,
    # because it rewrites the key.  We could otherwise strip server/port/etc
    # info out in the REST class, but it seemed bad design for the REST
    # class to rewrite the key.

    if key.to_s =~ /^\w+:\// and not Puppet::Util.absolute_path?(key.to_s) # it's a URI
      set_uri_key(key)
    else
      @key = key
    end
  end

  @key = @instance.name if ! @key and @instance
end

Instance Attribute Details

#authenticatedObject

API:

  • public



11
12
13
# File 'lib/puppet/indirector/request.rb', line 11

def authenticated
  @authenticated
end

#ignore_cacheObject

API:

  • public



11
12
13
# File 'lib/puppet/indirector/request.rb', line 11

def ignore_cache
  @ignore_cache
end

#ignore_terminusObject

API:

  • public



11
12
13
# File 'lib/puppet/indirector/request.rb', line 11

def ignore_terminus
  @ignore_terminus
end

#indirection_nameObject

API:

  • public



15
16
17
# File 'lib/puppet/indirector/request.rb', line 15

def indirection_name
  @indirection_name
end

#instanceObject

API:

  • public



11
12
13
# File 'lib/puppet/indirector/request.rb', line 11

def instance
  @instance
end

#ipObject

API:

  • public



11
12
13
# File 'lib/puppet/indirector/request.rb', line 11

def ip
  @ip
end

#keyObject

API:

  • public



11
12
13
# File 'lib/puppet/indirector/request.rb', line 11

def key
  @key
end

#methodObject

API:

  • public



11
12
13
# File 'lib/puppet/indirector/request.rb', line 11

def method
  @method
end

#nodeObject

API:

  • public



11
12
13
# File 'lib/puppet/indirector/request.rb', line 11

def node
  @node
end

#optionsObject

API:

  • public



11
12
13
# File 'lib/puppet/indirector/request.rb', line 11

def options
  @options
end

#portObject

API:

  • public



13
14
15
# File 'lib/puppet/indirector/request.rb', line 13

def port
  @port
end

#protocolObject

API:

  • public



13
14
15
# File 'lib/puppet/indirector/request.rb', line 13

def protocol
  @protocol
end

#serverObject

API:

  • public



13
14
15
# File 'lib/puppet/indirector/request.rb', line 13

def server
  @server
end

#uriObject

API:

  • public



13
14
15
# File 'lib/puppet/indirector/request.rb', line 13

def uri
  @uri
end

Class Method Details

.from_data_hash(data) ⇒ Object

Raises:

API:

  • public



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/puppet/indirector/request.rb', line 23

def self.from_data_hash(data)
  raise ArgumentError, "No indirection name provided in data" unless indirection_name = data['type']
  raise ArgumentError, "No method name provided in data" unless method = data['method']
  raise ArgumentError, "No key provided in data" unless key = data['key']

  request = new(indirection_name, method, key, nil, data['attributes'])

  if instance = data['instance']
    klass = Puppet::Indirector::Indirection.instance(request.indirection_name).model
    if instance.is_a?(klass)
      request.instance = instance
    else
      request.instance = klass.from_data_hash(instance)
    end
  end

  request
end

.from_pson(json) ⇒ Object

API:

  • public



42
43
44
45
# File 'lib/puppet/indirector/request.rb', line 42

def self.from_pson(json)
  Puppet.deprecation_warning("from_pson is being removed in favour of from_data_hash.")
  self.from_data_hash(json)
end

Instance Method Details

#authenticated?Boolean

Is this an authenticated request?

Returns:

API:

  • public



80
81
82
83
# File 'lib/puppet/indirector/request.rb', line 80

def authenticated?
  # Double negative, so we just get true or false
  ! ! authenticated
end

#do_request(srv_service = :puppet, default_server = , default_port = , &block) ⇒ Object

API:

  • public



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/puppet/indirector/request.rb', line 241

def do_request(srv_service=:puppet, default_server=Puppet.settings[:server], default_port=Puppet.settings[:masterport], &block)
  # We were given a specific server to use, so just use that one.
  # This happens if someone does something like specifying a file
  # source using a puppet:// URI with a specific server.
  return yield(self) if !self.server.nil?

  if Puppet.settings[:use_srv_records]
    Puppet::Network::Resolver.each_srv_record(Puppet.settings[:srv_domain], srv_service) do |srv_server, srv_port|
      begin
        self.server = srv_server
        self.port   = srv_port
        return yield(self)
      rescue SystemCallError => e
        Puppet.warning "Error connecting to #{srv_server}:#{srv_port}: #{e.message}"
      end
    end
  end

  # ... Fall back onto the default server.
  Puppet.debug "No more servers left, falling back to #{default_server}:#{default_port}" if Puppet.settings[:use_srv_records]
  self.server = default_server
  self.port   = default_port
  return yield(self)
end

#encode_params(params) ⇒ Object

API:

  • public



220
221
222
223
224
# File 'lib/puppet/indirector/request.rb', line 220

def encode_params(params)
  params.collect do |key, value|
    "#{key}=#{CGI.escape(value.to_s)}"
  end.join("&")
end

#environmentObject

API:

  • public



85
86
87
88
89
# File 'lib/puppet/indirector/request.rb', line 85

def environment
  # If environment has not been set directly, we should use the application's
  # current environment
  @environment ||= Puppet.lookup(:current_environment)
end

#environment=(env) ⇒ Object

API:

  • public



91
92
93
94
95
96
97
98
99
100
# File 'lib/puppet/indirector/request.rb', line 91

def environment=(env)
  @environment =
  if env.is_a?(Puppet::Node::Environment)
    env
  elsif (current_environment = Puppet.lookup(:current_environment)).name == env
    current_environment
  else
    Puppet.lookup(:environments).get!(env)
  end
end

#escaped_keyObject

API:

  • public



102
103
104
# File 'lib/puppet/indirector/request.rb', line 102

def escaped_key
  URI.escape(key)
end

#expand_into_parameters(data) ⇒ Object

API:

  • public



191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/puppet/indirector/request.rb', line 191

def expand_into_parameters(data)
  data.inject([]) do |params, key_value|
    key, value = key_value

    expanded_value = case value
                     when Array
                       value.collect { |val| [key, val] }
                     else
                       [key_value]
                     end

    params.concat(expand_primitive_types_into_parameters(expanded_value))
  end
end

#expand_primitive_types_into_parameters(data) ⇒ Object

API:

  • public



206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/puppet/indirector/request.rb', line 206

def expand_primitive_types_into_parameters(data)
  data.inject([]) do |params, key_value|
    key, value = key_value
    case value
    when nil
      params
    when true, false, String, Symbol, Fixnum, Bignum, Float
      params << [key, value]
    else
      raise ArgumentError, "HTTP REST queries cannot handle values of type '#{value.class}'"
    end
  end
end

#ignore_cache?Boolean

LAK:NOTE This is a messy interface to the cache, and it’s only used by the Configurer class. I decided it was better to implement it now and refactor later, when we have a better design, than to spend another month coming up with a design now that might not be any better.

Returns:

API:

  • public



111
112
113
# File 'lib/puppet/indirector/request.rb', line 111

def ignore_cache?
  ignore_cache
end

#ignore_terminus?Boolean

Returns:

API:

  • public



115
116
117
# File 'lib/puppet/indirector/request.rb', line 115

def ignore_terminus?
  ignore_terminus
end

#indirectionObject

Look up the indirection based on the name provided.

API:

  • public



149
150
151
# File 'lib/puppet/indirector/request.rb', line 149

def indirection
  Puppet::Indirector::Indirection.instance(indirection_name)
end

#modelObject

Raises:

API:

  • public



157
158
159
160
# File 'lib/puppet/indirector/request.rb', line 157

def model
  raise ArgumentError, "Could not find indirection '#{indirection_name}'" unless i = indirection
  i.model
end

#plural?Boolean

Are we trying to interact with multiple resources, or just one?

Returns:

API:

  • public



163
164
165
# File 'lib/puppet/indirector/request.rb', line 163

def plural?
  method == :search
end

#query_stringObject

Create the query string, if options are present.

API:

  • public



168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/puppet/indirector/request.rb', line 168

def query_string
  return "" if options.nil? || options.empty?

  # For backward compatibility with older (pre-3.3) masters,
  # this puppet option allows serialization of query parameter
  # arrays as yaml.  This can be removed when we remove yaml
  # support entirely.
  if Puppet.settings[:legacy_query_parameter_serialization]
    replace_arrays_with_yaml
  end

  "?" + encode_params(expand_into_parameters(options.to_a))
end

#remote?Boolean

Returns:

API:

  • public



266
267
268
# File 'lib/puppet/indirector/request.rb', line 266

def remote?
  self.node or self.ip
end

#replace_arrays_with_yamlObject

API:

  • public



182
183
184
185
186
187
188
189
# File 'lib/puppet/indirector/request.rb', line 182

def replace_arrays_with_yaml
  options.each do |key, value|
    case value
      when Array
        options[key] = YAML.dump(value)
    end
  end
end

#to_data_hashObject

API:

  • public



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/puppet/indirector/request.rb', line 47

def to_data_hash
  result = {
    'type' => indirection_name,
    'method' => method,
    'key' => key
  }
  attributes = {}
  OPTION_ATTRIBUTES.each do |key|
    next unless value = send(key)
    attributes[key] = value
  end

  options.each do |opt, value|
    attributes[opt] = value
  end

  result['attributes'] = attributes unless attributes.empty?
  result['instance'] = instance if instance
  result
end

#to_hashObject

API:

  • public



226
227
228
229
230
231
232
233
234
235
# File 'lib/puppet/indirector/request.rb', line 226

def to_hash
  result = options.dup

  OPTION_ATTRIBUTES.each do |attribute|
    if value = send(attribute)
      result[attribute] = value
    end
  end
  result
end

#to_pson(*args) ⇒ Object

API:

  • public



75
76
77
# File 'lib/puppet/indirector/request.rb', line 75

def to_pson(*args)
  to_pson_data_hash.to_pson(*args)
end

#to_pson_data_hashObject

API:

  • public



68
69
70
71
72
73
# File 'lib/puppet/indirector/request.rb', line 68

def to_pson_data_hash
  {
    'document_type' => 'IndirectorRequest',
    'data' => to_data_hash,
  }
end

#to_sObject

API:

  • public



237
238
239
# File 'lib/puppet/indirector/request.rb', line 237

def to_s
  return(uri ? uri : "/#{indirection_name}/#{key}")
end