class SkullIsland::Resources::Upstream

The Upstream resource class

@see docs.konghq.com/1.1.x/admin-api/#upstream-objects Upstream API definition

Public Class Methods

batch_import(data, verbose: false, test: false, project: nil, time: nil) click to toggle source

rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/PerceivedComplexity rubocop:disable Metrics/AbcSize

# File lib/skull_island/resources/upstream.rb, line 29
def self.batch_import(data, verbose: false, test: false, project: nil, time: nil)
  raise(Exceptions::InvalidArguments) unless data.is_a?(Array)

  known_ids = []

  data.each_with_index do |rdata, index|
    resource = new
    resource.name = rdata['name']
    resource.algorithm = rdata['algorithm'] if rdata['algorithm']
    resource.slots = rdata['slots'] if rdata['slots']
    resource.hash_on = rdata['hash_on']
    resource.hash_fallback = rdata['hash_fallback'] if rdata['hash_fallback']
    resource.hash_on_header = rdata['hash_on_header'] if rdata['hash_on_header']
    if rdata['hash_fallback_header']
      resource.hash_fallback_header = rdata['hash_fallback_header']
    end
    resource.hash_on_cookie = rdata['hash_on_cookie'] if rdata['hash_on_cookie']
    if rdata['hash_on_cookie_path']
      resource.hash_on_cookie_path = rdata['hash_on_cookie_path']
    end
    resource.healthchecks = rdata['healthchecks'] if rdata['healthchecks']
    resource.host_header = rdata['host_header'] if rdata['host_header']
    resource.tags = rdata['tags'] if rdata['tags']
    resource.project = project if project
    resource.import_time = (time || Time.now.utc.to_i) if project
    resource.import_update_or_skip(index: index, verbose: verbose, test: test)
    known_ids << resource.id
    puts '[INFO] Processing UpstreamTarget entries...' if verbose

    UpstreamTarget.batch_import(
      (rdata['targets'] || []).map { |t| t.merge('upstream' => { 'id' => resource.id }) },
      verbose: verbose,
      test: test,
      project: project,
      time: time
    )
  end

  cleanup_except(project, known_ids) if project

  known_ids
end

Public Instance Methods

add_target!(details) click to toggle source

Convenience method to add upstream targets

# File lib/skull_island/resources/upstream.rb, line 86
def add_target!(details)
  r = if details.is_a?(UpstreamTarget)
        details
      else
        UpstreamTarget.from_hash(details, api_client: api_client)
      end

  r.upstream = self
  r.save
end
export(options = {}) click to toggle source

rubocop:disable Metrics/AbcSize

# File lib/skull_island/resources/upstream.rb, line 121
def export(options = {})
  hash = {
    'name' => name,
    'slots' => slots,
    'hash_on' => hash_on,
    'hash_fallback' => hash_fallback,
    'hash_on_header' => hash_on_header,
    'hash_fallback_header' => hash_fallback_header,
    'hash_on_cookie' => hash_on_cookie,
    'hash_on_cookie_path' => hash_on_cookie_path,
    'healthchecks' => healthchecks
  }
  hash['algorithm'] = algorithm if algorithm
  hash['targets'] = targets.collect { |target| target.export(exclude: 'upstream') }
  hash['host_header'] = host_header if host_header
  hash['tags'] = tags unless tags.empty?
  [*options[:exclude]].each do |exclude|
    hash.delete(exclude.to_s)
  end
  [*options[:include]].each do |inc|
    hash[inc.to_s] = send(inc.to_sym)
  end
  hash.reject { |_, value| value.nil? }
end
health() click to toggle source

rubocop:enable Metrics/CyclomaticComplexity rubocop:enable Metrics/PerceivedComplexity rubocop:enable Metrics/AbcSize

# File lib/skull_island/resources/upstream.rb, line 75
def health
  if new?
    # No health status for new Upstreams
    nil
  else
    health_json = api_client.get("#{relative_uri}/health")
    health_json['data']
  end
end
modified_existing?() click to toggle source

rubocop:enable Metrics/AbcSize

# File lib/skull_island/resources/upstream.rb, line 147
def modified_existing?
  return false unless new?

  # Find routes of the same name
  same_name = self.class.where(:name, name)

  existing = same_name.size == 1 ? same_name.first : nil

  if existing
    @entity['id'] = existing.id
    save
  else
    false
  end
end
target(target_id) click to toggle source
# File lib/skull_island/resources/upstream.rb, line 97
def target(target_id)
  targets.where(:id, target_id).first
end
targets() click to toggle source
# File lib/skull_island/resources/upstream.rb, line 101
def targets
  target_list_data = api_client.get("#{relative_uri}/targets")
  root = 'data' # root for API JSON response data
  # TODO: do something with lazy requests...

  ResourceCollection.new(
    target_list_data[root].map do |record|
      UpstreamTarget.new(
        entity: record,
        lazy: false,
        tainted: false,
        api_client: api_client
      )
    end,
    type: UpstreamTarget,
    api_client: api_client
  )
end

Private Instance Methods

postprocess_healthchecks(value) click to toggle source

Prunes empty values from the healthchecks Hash

# File lib/skull_island/resources/upstream.rb, line 166
def postprocess_healthchecks(value)
  value.is_a?(Hash) ? value.prune : value
end
validate_algorithm(value) click to toggle source

Validates the upstream balancing {#algorithm}

# File lib/skull_island/resources/upstream.rb, line 171
def validate_algorithm(value)
  %w[round-robin consistent-hashing least-connections].include?(value)
end
validate_hash_fallback(value) click to toggle source

Used to validate {#hash_fallback} on set

# File lib/skull_island/resources/upstream.rb, line 182
def validate_hash_fallback(value)
  # only String of an acceptable value are allowed
  %w[none consumer ip header cookie].include?(value)
end
validate_hash_fallback_header(value) click to toggle source

Used to validate {#hash_fallback_header} on set

# File lib/skull_island/resources/upstream.rb, line 194
def validate_hash_fallback_header(value)
  # only String is allowed and only when {#hash_fallback} is set to 'header'
  value.is_a?(String) && hash_fallback == 'header'
end
validate_hash_on(value) click to toggle source

Used to validate {#hash_on} on set

# File lib/skull_island/resources/upstream.rb, line 176
def validate_hash_on(value)
  # only String of an acceptable value are allowed
  %w[none consumer ip header cookie].include?(value)
end
validate_hash_on_header(value) click to toggle source

Used to validate {#hash_on_header} on set

# File lib/skull_island/resources/upstream.rb, line 188
def validate_hash_on_header(value)
  # only String is allowed and only when {#hash_on} is set to 'header'
  value.is_a?(String) && hash_on == 'header'
end
validate_healthchecks(value) click to toggle source

Used to validate {#healthchecks} on set

# File lib/skull_island/resources/upstream.rb, line 224
def validate_healthchecks(value)
  # TODO: seriously need to make this better...
  # only Hash is allowed
  value.is_a?(Hash)
end
validate_host_header(value) click to toggle source

Enforces valid host headers for upstreams

# File lib/skull_island/resources/upstream.rb, line 231
def validate_host_header(value)
  # allow only valid hostnames
  value.match?(host_regex) && !value.match?(/_/)
end
validate_name(value) click to toggle source

Used to validate {#name} on set

# File lib/skull_island/resources/upstream.rb, line 212
def validate_name(value)
  # only String is allowed
  value.is_a?(String)
end
validate_slots(value) click to toggle source

Used to validate {#slots} on set

# File lib/skull_island/resources/upstream.rb, line 218
def validate_slots(value)
  # only Integer is allowed
  value.is_a?(Integer)
end