Skip to content

Commit

Permalink
Construct fact override object in API
Browse files Browse the repository at this point in the history
  • Loading branch information
Kevin Paulisse committed Jan 14, 2017
1 parent 0ca8b6c commit 6a574b6
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 157 deletions.
1 change: 1 addition & 0 deletions lib/octocatalog-diff/api/v1.rb
Expand Up @@ -5,6 +5,7 @@
require_relative 'v1/catalog-diff'
require_relative 'v1/config'
require_relative 'v1/diff'
require_relative 'v1/fact_override'

module OctocatalogDiff
module API
Expand Down
22 changes: 22 additions & 0 deletions lib/octocatalog-diff/api/v1/fact_override.rb
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require 'json'

module OctocatalogDiff
module API
module V1
# Sets up the override of a fact during catalog compilation.
class FactOverride
# Accessors
attr_reader :key, :value

# Constructor: Accepts a key and value.
# @param input [Hash] Must contain :key and :value
def initialize(input)
@key = input.fetch(:key)
@value = input.fetch(:value)
end
end
end
end
end
11 changes: 5 additions & 6 deletions lib/octocatalog-diff/cli.rb
Expand Up @@ -2,14 +2,13 @@

require_relative 'api/v1'
require_relative 'catalog-util/cached_master_directory'
require_relative 'errors'
require_relative 'util/catalogs'
require_relative 'version'

require_relative 'cli/diffs'
require_relative 'cli/fact_override'
require_relative 'cli/options'
require_relative 'cli/printer'
require_relative 'cli/helpers/fact_override'
require_relative 'errors'
require_relative 'util/catalogs'
require_relative 'version'

require 'logger'
require 'socket'
Expand Down Expand Up @@ -137,7 +136,7 @@ def self.setup_fact_overrides(options)
next unless o.is_a?(Array)
next unless o.any?
options[key] ||= []
options[key].concat o.map { |x| OctocatalogDiff::Cli::Helpers::FactOverride.new(x) }
options[key].concat o.map { |x| OctocatalogDiff::Cli::FactOverride.fact_override(x) }
end
end

Expand Down
93 changes: 93 additions & 0 deletions lib/octocatalog-diff/cli/fact_override.rb
@@ -0,0 +1,93 @@
# frozen_string_literal: true

require 'json'

require_relative '../api/v1'

module OctocatalogDiff
class Cli
# Helper methods for fact override parsing.
class FactOverride
# Public: Given an input string, construct the fact override object(s).
#
# @param input [String] Input in the format: key=(data type)value
# @return [OctocatalogDiff::API::V1::FactOverride] Constructed override object
def self.fact_override(input, key = nil)
# Normally the input will be a string in the format key=(data type)value where the data
# type is optional and the parentheses are literal. Example:
# foo=1 (auto-determine data type - in this case it would be a fixnum)
# foo=(fixnum)1 (will be a fixnum)
# foo=(string)1 (will be '1' the string)
# If input is not a string, we can still construct the object if the key is given.
# That input would come directly from code and not from the command line, since inputs
# from the command line are always strings.
if key.nil? && input.is_a?(String)
unless input.include?('=')
raise ArgumentError, "Fact override '#{input}' is not in 'key=(data type)value' format"
end
key, raw_value = input.strip.split('=', 2)
value = parsed_value(raw_value)
OctocatalogDiff::API::V1::FactOverride.new(key: key, value: value)
elsif key.nil?
message = "Define a key when the input is not a string (#{input.class} => #{input.inspect})"
raise ArgumentError, message
else
OctocatalogDiff::API::V1::FactOverride.new(key: key, value: input)
end
end

# Guess the datatype from a particular input
# @param input [String] Input in string format
# @return [?] Output in appropriate format
def self.parsed_value(input)
# If data type is explicitly given
if input =~ /^\((\w+)\)(.*)$/m
datatype = Regexp.last_match(1)
value = Regexp.last_match(2)
return convert_to_data_type(datatype.downcase, value)
end

# Guess data type
return input.to_i if input =~ /^-?\d+$/
return input.to_f if input =~ /^-?\d*\.\d+$/
return true if input.casecmp('true').zero?
return false if input.casecmp('false').zero?
input
end

# Handle data type that's explicitly given
# @param datatype [String] Data type (as a string)
# @param value [String] Value given
# @return [?] Value converted to specified data type
def self.convert_to_data_type(datatype, value)
return value if datatype == 'string'
return parse_json(value) if datatype == 'json'
return nil if datatype == 'nil'
if datatype == 'fixnum'
return Regexp.last_match(1).to_i if value =~ /^(-?\d+)$/
raise ArgumentError, "Illegal fixnum '#{value}'"
end
if datatype == 'float'
return Regexp.last_match(1).to_f if value =~ /^(-?\d*\.\d+)$/
return Regexp.last_match(1).to_f if value =~ /^(-?\d+)$/
raise ArgumentError, "Illegal float '#{value}'"
end
if datatype == 'boolean'
return true if value.casecmp('true').zero?
return false if value.casecmp('false').zero?
raise ArgumentError, "Illegal boolean '#{value}'"
end
raise ArgumentError, "Unknown data type '#{datatype}'"
end

# Parse JSON value
# @param input [String] Input, hopefully in JSON format
# @return [?] Output data structure
def self.parse_json(input)
JSON.parse(input)
rescue JSON::ParserError => exc
raise JSON::ParserError, "Failed to parse JSON: input=#{input} error=#{exc}"
end
end
end
end
98 changes: 0 additions & 98 deletions lib/octocatalog-diff/cli/helpers/fact_override.rb

This file was deleted.

4 changes: 2 additions & 2 deletions spec/octocatalog-diff/tests/catalog-util/builddir_spec.rb
Expand Up @@ -3,7 +3,7 @@
require_relative '../spec_helper'
require OctocatalogDiff::Spec.require_path('/facts')
require OctocatalogDiff::Spec.require_path('/catalog-util/builddir')
require OctocatalogDiff::Spec.require_path('/cli/helpers/fact_override')
require OctocatalogDiff::Spec.require_path('/cli/fact_override')
require 'socket'
require 'yaml'

Expand Down Expand Up @@ -531,7 +531,7 @@
context 'with fact overrides' do
it 'should create and populate the fact file' do
overrides_raw = %w(ipaddress=10.30.50.70 fizz=buzz jsontest=(json){"foo":"bar"})
overrides = overrides_raw.map { |x| OctocatalogDiff::Cli::Helpers::FactOverride.new(x) }
overrides = overrides_raw.map { |x| OctocatalogDiff::Cli::FactOverride.fact_override(x) }
options = {
basedir: OctocatalogDiff::Spec.fixture_path('repos/default'),
fact_file: OctocatalogDiff::Spec.fixture_path('facts/valid-facts.yaml'),
Expand Down

0 comments on commit 6a574b6

Please sign in to comment.