This file is indexed.

/usr/lib/ruby/vendor_ruby/fog/core/service.rb is in ruby-fog-core 1.45.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
require "fog/core/utils"

module Fog
  def self.services
    @services ||= {}
  end

  class Service
    class Error < Fog::Errors::Error; end
    class NotFound < Fog::Errors::NotFound; end

    module NoLeakInspector
      def inspect
        "#<#{self.class}:#{object_id} #{(instance_variables - service.secrets).map { |iv| [iv, instance_variable_get(iv).inspect].join("=") }.join(" ")}>"
      end
    end

    module Collections
      def collections
        service.collections
      end

      def mocked_requests
        service.mocked_requests
      end

      def requests
        service.requests
      end
    end

    class << self
      def inherited(child)
        child.class_eval <<-EOS, __FILE__, __LINE__
          class Error < Fog::Service::Error; end
          class NotFound < Fog::Service::NotFound; end

          module Collections
            include Fog::Service::Collections

            def service
              #{child}
            end
          end

          def self.service
            #{child}
          end
        EOS
      end

      # {Fog::Service} is (unfortunately) both a builder class and the subclass for any fog service.
      #
      # Creating a {new} instance using the builder will return either an instance of
      # +Fog::<Service>::<Provider>::Real+ or +Fog::<Service>::<Provider>::Mock+ based on the value
      # of {Fog.mock?} when the builder is used.
      #
      # Each provider can require or recognize different settings (often prefixed with the providers
      # name). These settings map to keys in the +~/.fog+ file.
      #
      # Settings can be passed as either a Hash or an object that responds to +config_service?+ with
      # +true+. This object will be passed through unchanged to the +Real+ or +Mock+ service that is
      # created. It is up to providers to adapt services to use these config objects.
      #
      # @abstract Subclass and implement real or mock code
      #
      # @param [Hash,#config_service?] config
      #   Settings or an object used to build a service instance
      # @option config [Hash] :headers
      #   Passed to the underlying {Fog::Core::Connection} unchanged
      #
      # @return [Fog::Service::Provider::Real] if created while mocking is disabled
      # @return [Fog::Service::Provider::Mock] if created while mocking is enabled
      # @raise [ArgumentError] if a setting required by the provider was not passed in
      #
      # @example Minimal options (dependent on ~/.fog)
      #   @service = Fog::Compute::Example.new # => <#Fog::Compute::Example::Real>
      #
      # @example Mocked service
      #   Fog.mock!
      #   @service = Fog::Compute::Example.new # => <#Fog::Compute::Example::Mock>
      #
      # @example Configured using many options (options merged into ~/.fog)
      #   @options = {
      #     :example_username => "fog",
      #     :example_password => "fog"
      #   }
      #   @service = Fog::Compute::Example.new(@options)
      #
      # @example Configured using external config object (~/.fog ignored completely)
      #   @config = Fog::Example::Config.new(...)
      #   @service = Fog::Compute::Example.new(@config)
      #
      def new(config = {})
        if config.respond_to?(:config_service?) && config.config_service?
          cleaned_settings = config
        else
          cleaned_settings = handle_settings(config)
        end
        setup_requirements

        svc = service
        if Fog.mocking?
          while svc != Fog::Service
            service::Mock.send(:include, svc::Collections)
            svc = svc.superclass
          end
          service::Mock.new(cleaned_settings)
        else
          while svc != Fog::Service
            service::Real.send(:include, svc::Collections)
            svc = svc.superclass
          end
          service::Real.send(:include, service::NoLeakInspector)
          service::Real.new(cleaned_settings)
        end
      end

      # @deprecated
      def fetch_credentials(_options)
        # attempt to load credentials from config file
        Fog.credentials.reject { |key, _value| !(recognized | requirements).include?(key) }
      rescue ::Fog::Errors::LoadError
        # if there are no configured credentials, do nothing
        {}
      end

      def setup_requirements
        if superclass.respond_to?(:setup_requirements)
          superclass.setup_requirements
        end

        @required ||= false

        return false if @required

        require_models
        require_collections_and_define
        require_requests_and_mock
        @required = true
      end

      # @note This path is used to require model and collection files
      def model_path(new_path)
        @model_path = new_path
      end

      def collection(new_collection, path = nil)
        collection_files << [path, new_collection]
        collections << new_collection
      end

      def collection_files
        @collection_files ||= []
      end

      def collections
        @collections ||= []
      end

      def coerce_options(options)
        options.each do |key, value|
          value_string = value.to_s.downcase
          if value.nil?
            options.delete(key)
          elsif value_string.to_i.to_s == value
            options[key] = value.to_i
          else
            options[key] = case value_string
                           when "false"
                             false
                           when "true"
                             true
                           else
                             value
                           end
          end
        end
      end

      def mocked_requests
        @mocked_requests ||= []
      end

      def model(new_model, path = nil)
        model_files << [path, new_model]
        models << [new_model]
      end

      def model_files
        @model_files ||= []
      end

      def models
        @models ||= []
      end

      def request_path(new_path)
        @request_path = new_path
      end

      def request(new_request, path = nil)
        requests << [path, new_request]
      end

      def requests
        @requests ||= []
      end

      def secrets(*args)
        if args.empty?
          @secrets ||= []
        else
          args.reduce(secrets) do |secrets, secret|
            secrets << "@#{secret}".to_sym
          end
        end
      end

      def requires(*args)
        requirements.concat(args)
      end

      def requirements
        @requirements ||= []
      end

      def recognizes(*args)
        recognized.concat(args)
      end

      def recognized
        @recognized ||= [:connection_options]
      end

      def validate_options(options)
        keys = []
        options.each_pair do |key, value|
          keys << key unless value.nil?
        end
        missing = requirements - keys

        unless missing.empty?
          raise ArgumentError, "Missing required arguments: #{missing.join(", ")}"
        end

        unless recognizes.empty?
          unrecognized = options.keys - requirements - recognized
          unless unrecognized.empty?
            Fog::Logger.warning("Unrecognized arguments: #{unrecognized.join(", ")}")
          end
        end
      end

      private

      # This is the original way service settings were handled. Settings from +~/.fog+ were merged
      # together with the passed options, keys are turned to symbols and coerced into Boolean or
      # Fixnums.
      #
      # If the class has declared any required settings then {ArgumentError} will be raised.
      #
      # Any setting that is not whitelisted will cause a warning to be output.
      #
      def handle_settings(settings)
        combined_settings = fetch_credentials(settings).merge(settings)
        prepared_settings = Fog::Core::Utils.prepare_service_settings(combined_settings)
        validate_options(prepared_settings)
        coerce_options(prepared_settings)
      end

      # This will attempt to require all model files declared by the service using fog"s DSL
      def require_models
        model_files.each { |model| require_item(model, @model_path) }
      end

      def require_collections_and_define
        collection_files.each do |collection|
          require_item(collection, @model_path)
          constant = camel_case_collection_name(collection.last)
          service::Collections.module_eval <<-EOS, __FILE__, __LINE__
            def #{collection.last}(attributes = {})
              #{service}::#{constant}.new({ :service => self }.merge(attributes))
            end
          EOS
        end
      end

      # This converts names of collections from Symbols as defined in the DSL (+:database_server+)
      # into CamelCase version (+DatabaseServer+) for metaprogramming skulduggery.
      #
      # @param [String,Symbol] collection The name of the collection broken with underscores
      # @return [String] in camel case
      def camel_case_collection_name(collection)
        collection.to_s.split("_").map(&:capitalize).join
      end

      # This will attempt to require all request files declared in the service using fog"s DSL
      def require_requests_and_mock
        requests.each do |request|
          require_item(request, @request_path)
          if service::Mock.method_defined?(request.last)
            mocked_requests << request.last
          else
            service::Mock.module_eval <<-EOS, __FILE__, __LINE__
              def #{request.last}(*args)
                Fog::Mock.not_implemented
              end
            EOS
          end
        end
      end

      # Requires the correct file for an item (collection, model, or request).
      #
      # @param [Array] item
      #   An item to require. Should be an array in the form of [path, file].
      # @param [String] fallback_dir
      #   The directory to look for the file in if the first element of `item`
      #   is nil.
      # @return [Boolean] Returns the same as `Kernel#require`.
      def require_item(item, fallback_dir)
        path, file = item
        require File.join(path || fallback_dir, file.to_s)
      end
    end
  end
end