Class: Constancy::SyncTarget

Inherits:
Object
  • Object
show all
Defined in:
lib/constancy/sync_target.rb

Constant Summary collapse

VALID_CONFIG_KEYS =
%w( name type datacenter prefix path exclude chomp delete erb_enabled )
REQUIRED_CONFIG_KEYS =
%w( prefix )
VALID_TYPES =
[ :dir, :file ]
DEFAULT_TYPE =
:dir

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config:, imperium_config:, base_dir:) ⇒ SyncTarget

Returns a new instance of SyncTarget.



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
# File 'lib/constancy/sync_target.rb', line 12

def initialize(config:, imperium_config:, base_dir:)
  if not config.is_a? Hash
    raise Constancy::ConfigFileInvalid.new("Sync target entries must be specified as hashes")
  end

  if (config.keys - Constancy::SyncTarget::VALID_CONFIG_KEYS) != []
    raise Constancy::ConfigFileInvalid.new("Only the following keys are valid in a sync target entry: #{Constancy::SyncTarget::VALID_CONFIG_KEYS.join(", ")}")
  end

  if (Constancy::SyncTarget::REQUIRED_CONFIG_KEYS - config.keys) != []
    raise Constancy::ConfigFileInvalid.new("The following keys are required in a sync target entry: #{Constancy::SyncTarget::REQUIRED_CONFIG_KEYS.join(", ")}")
  end

  @base_dir = base_dir
  self.datacenter = config['datacenter']
  self.prefix = config['prefix']
  self.path = config['path'] || config['prefix']
  self.name = config['name']
  self.type = (config['type'] || Constancy::SyncTarget::DEFAULT_TYPE).to_sym
  unless Constancy::SyncTarget::VALID_TYPES.include?(self.type)
    raise Constancy::ConfigFileInvalid.new("Sync target '#{self.name || self.path}' has type '#{self.type}'. But only the following types are valid: #{Constancy::SyncTarget::VALID_TYPES.collect(&:to_s).join(", ")}")
  end

  if self.type == :file and File.directory?(self.base_path)
    raise Constancy::ConfigFileInvalid.new("Sync target '#{self.name || self.path}' has type 'file', but path '#{self.path}' is a directory.")
  end

  self.exclude = config['exclude'] || []
  if config.has_key?('chomp')
    @do_chomp = config['chomp'] ? true : false
  end
  if config.has_key?('delete')
    @do_delete = config['delete'] ? true : false
  else
    @do_delete = false
  end

  self.consul = Imperium::KV.new(imperium_config)
  self.erb_enabled = config['erb_enabled']
end

Instance Attribute Details

#consulObject

Returns the value of attribute consul.



6
7
8
# File 'lib/constancy/sync_target.rb', line 6

def consul
  @consul
end

#datacenterObject

Returns the value of attribute datacenter.



6
7
8
# File 'lib/constancy/sync_target.rb', line 6

def datacenter
  @datacenter
end

#erb_enabledObject

Returns the value of attribute erb_enabled.



6
7
8
# File 'lib/constancy/sync_target.rb', line 6

def erb_enabled
  @erb_enabled
end

#excludeObject

Returns the value of attribute exclude.



6
7
8
# File 'lib/constancy/sync_target.rb', line 6

def exclude
  @exclude
end

#nameObject

Returns the value of attribute name.



6
7
8
# File 'lib/constancy/sync_target.rb', line 6

def name
  @name
end

#pathObject

Returns the value of attribute path.



6
7
8
# File 'lib/constancy/sync_target.rb', line 6

def path
  @path
end

#prefixObject

Returns the value of attribute prefix.



6
7
8
# File 'lib/constancy/sync_target.rb', line 6

def prefix
  @prefix
end

#typeObject

Returns the value of attribute type.



6
7
8
# File 'lib/constancy/sync_target.rb', line 6

def type
  @type
end

Instance Method Details

#base_pathObject



80
81
82
# File 'lib/constancy/sync_target.rb', line 80

def base_path
  @base_path ||= File.join(@base_dir, self.path)
end

#chomp?Boolean

Returns:

  • (Boolean)


57
58
59
# File 'lib/constancy/sync_target.rb', line 57

def chomp?
  @do_chomp
end

#clear_cacheObject



73
74
75
76
77
78
# File 'lib/constancy/sync_target.rb', line 73

def clear_cache
  @base_path = nil
  @local_files = nil
  @local_items = nil
  @remote_items = nil
end

#delete?Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/constancy/sync_target.rb', line 61

def delete?
  @do_delete
end

#description(mode = :push) ⇒ Object



65
66
67
68
69
70
71
# File 'lib/constancy/sync_target.rb', line 65

def description(mode = :push)
  if mode == :pull
    "#{self.name.nil? ? '' : self.name.bold + "\n"}#{'consul'.cyan}:#{self.datacenter.green}:#{self.prefix} => #{'local'.blue}:#{self.path}"
  else
    "#{self.name.nil? ? '' : self.name.bold + "\n"}#{'local'.blue}:#{self.path} => #{'consul'.cyan}:#{self.datacenter.green}:#{self.prefix}"
  end
end

#diff(mode) ⇒ Object



146
147
148
# File 'lib/constancy/sync_target.rb', line 146

def diff(mode)
  Constancy::Diff.new(target: self, local: self.local_items, remote: self.remote_items, mode: mode)
end

#erb_enabled?Boolean

Returns:

  • (Boolean)


53
54
55
# File 'lib/constancy/sync_target.rb', line 53

def erb_enabled?
  @erb_enabled
end

#load_local_file(local_file) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/constancy/sync_target.rb', line 119

def load_local_file(local_file)
  file = File.read(local_file)

  if self.chomp?
    encoded_file = file.chomp.force_encoding(Encoding::ASCII_8BIT)
  else
    encoded_file = file.force_encoding(Encoding::ASCII_8BIT)
  end

  return ERB.new(encoded_file).result if erb_enabled?
  encoded_file
end

#local_filesObject



84
85
86
87
# File 'lib/constancy/sync_target.rb', line 84

def local_files
  # see https://stackoverflow.com/questions/357754/can-i-traverse-symlinked-directories-in-ruby-with-a-glob
  @local_files ||= Dir["#{self.base_path}/**{,/*/**}/*"].select { |f| File.file?(f) }
end

#local_itemsObject



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/constancy/sync_target.rb', line 89

def local_items
  return @local_items if not @local_items.nil?
  @local_items = {}

  case self.type
  when :dir
    self.local_files.each do |local_file|
      @local_items[local_file.sub(%r{^#{self.base_path}/?}, '')] =
        load_local_file(local_file)
    end

  when :file
    if File.exist?(self.base_path)
      @local_items = local_items_from_file
    end
  end

  @local_items
end

#local_items_from_fileObject



109
110
111
112
113
114
115
116
117
# File 'lib/constancy/sync_target.rb', line 109

def local_items_from_file
  if erb_enabled?
    loaded_file = YAML.load(ERB.new(File.read(self.base_path)).result)
  else
    loaded_file = YAML.load_file(self.base_path)
  end

  flatten_hash(nil, loaded_file)
end

#remote_itemsObject



132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/constancy/sync_target.rb', line 132

def remote_items
  return @remote_items if not @remote_items.nil?
  @remote_items = {}

  resp = self.consul.get(self.prefix, :recurse, dc: self.datacenter)

  return @remote_items if resp.values.nil?
  Constancy::Util.flatten_hash(resp.values).each_pair do |key, value|
    @remote_items[key.join("/")] = (value.nil? ? '' : value)
  end

  @remote_items
end