Skip to content

Commit

Permalink
Take global layer into account (#351)
Browse files Browse the repository at this point in the history
* Add hiera layer abstraction ... #330

And take "global" layer into account when querying data.

* Remove obsolete error class.

* Make location of global hiera.yaml configurable #330

* Fix typo.

* Fix markup #330

Fixes the problem displayed here:
#330 (comment)

* Small fix for rubocop.
  • Loading branch information
oneiros authored Apr 12, 2024
1 parent f22314e commit 594517e
Show file tree
Hide file tree
Showing 40 changed files with 589 additions and 572 deletions.
39 changes: 0 additions & 39 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
# SupportedStyles: with_first_argument, with_fixed_indentation
Layout/ArgumentAlignment:
Exclude:
- 'app/controllers/keys_controller.rb'
- 'app/models/hiera_data/data_file.rb'
- 'test/controllers/keys_controller_test.rb'
- 'test/integration/required_authentication_test.rb'

Expand Down Expand Up @@ -49,21 +47,6 @@ Layout/EmptyLinesAroundClassBody:
Exclude:
- 'test/controllers/sessions_controller_test.rb'

# Offense count: 2
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment.
Layout/ExtraSpacing:
Exclude:
- 'test/models/hiera_data_test.rb'

# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: special_inside_parentheses, consistent, align_brackets
Layout/FirstArrayElementIndentation:
Exclude:
- 'test/models/hiera_data_test.rb'

# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Layout/HeredocIndentation:
Expand All @@ -87,15 +70,6 @@ Layout/IndentationWidth:
- 'app/controllers/users_controller.rb'
- 'test/models/hiera_data/yaml_file_test.rb'

# Offense count: 4
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: aligned, indented, indented_relative_to_receiver
Layout/MultilineMethodCallIndentation:
Exclude:
- 'app/models/hiera_data/data_file.rb'
- 'app/models/key.rb'

# Offense count: 6
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator, EnforcedStyleForRationalLiterals.
Expand All @@ -106,7 +80,6 @@ Layout/SpaceAroundOperators:
- 'app/models/hiera_data/yaml_file.rb'
- 'test/models/hiera_data/data_file_test.rb'
- 'test/models/hiera_data/yaml_file_test.rb'
- 'test/models/hiera_data_test.rb'

# Offense count: 43
# This cop supports safe autocorrection (--autocorrect).
Expand All @@ -118,7 +91,6 @@ Layout/SpaceInsideHashLiteralBraces:
- 'test/models/hiera_data/data_file_test.rb'
- 'test/models/hiera_data/interpolation_test.rb'
- 'test/models/hiera_data/yaml_file_test.rb'
- 'test/models/hiera_data_test.rb'

# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Expand All @@ -127,18 +99,11 @@ Layout/TrailingWhitespace:
Exclude:
- 'config/initializers/friendly_id.rb'

# Offense count: 2
# This cop supports safe autocorrection (--autocorrect).
Lint/AmbiguousRegexpLiteral:
Exclude:
- 'test/models/hiera_data_test.rb'

# Offense count: 2
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: AllowSafeAssignment.
Lint/AssignmentInCondition:
Exclude:
- 'app/models/hiera_data/data_file.rb'
- 'app/models/hiera_data/git_repo.rb'

# Offense count: 1
Expand Down Expand Up @@ -193,7 +158,6 @@ Rails/FilePath:
Exclude:
- 'test/models/hiera_data/data_file_test.rb'
- 'test/models/hiera_data/yaml_file_test.rb'
- 'test/models/hiera_data_test.rb'

# Offense count: 7
# This cop supports safe autocorrection (--autocorrect).
Expand All @@ -203,7 +167,6 @@ Rails/FilePath:
Rails/RefuteMethods:
Exclude:
- 'test/models/hiera_data/yaml_file_test.rb'
- 'test/models/hierarchy_test.rb'
- 'test/models/user_test.rb'

# Offense count: 5
Expand Down Expand Up @@ -279,7 +242,6 @@ Style/GuardClause:
- 'app/controllers/application_controller.rb'
- 'app/controllers/page_controller.rb'
- 'app/controllers/sessions_controller.rb'
- 'app/models/hiera_data/data_file.rb'

# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Expand Down Expand Up @@ -314,7 +276,6 @@ Style/PercentLiteralDelimiters:
Exclude:
- 'config/initializers/friendly_id.rb'
- 'test/models/environment_test.rb'
- 'test/models/key_test.rb'

# Offense count: 3
# This cop supports unsafe autocorrection (--autocorrect-all).
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ production:

config_dir: /etc/puppetlabs/code # puppet code directory

global_hiera_yaml: /etc/puppetlabs/puppet/hiera.yaml

ldap: # LDAP User auth
host: 'localhost'
port: 389
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/api/v1/keys_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ def index

respond_to do |format|
format.json do
render json: @keys.to_json(except: :environment)
render json: @keys.to_json
end
end
end

def show
@key = Key.new(environment: @environment, name: params[:id])
@key = Key.new(name: params[:id])
authorize! :show, @key

respond_to do |format|
Expand All @@ -28,7 +28,7 @@ def show
private

def values_per_hierarchy_and_file
@environment.hierarchies.map do |hierarchy|
@environment.environment_layer.hierarchies.map do |hierarchy|
files = hierarchy.files_for(node: @node).map do |file|
{ path: file.path, value: file.value_for(key: @key).value }
end
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/files_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ class FilesController < ApplicationController
add_breadcrumb "Environments", :environments_path

def index
@files_and_values_by_hierarchy =
@files_and_values =
if can? :show, @key
DataFile.search(@environment, @key)
@key.search(environment: @environment)
else
{}
end
Expand All @@ -20,6 +20,6 @@ def index
private

def load_key
@key = Key.new(environment: @environment, name: params[:key_id].squish)
@key = Key.new(name: params[:key_id].squish)
end
end
20 changes: 1 addition & 19 deletions app/controllers/keys_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,11 @@ def index
def show
@keys = Key.all_for(@node, environment: @environment)
@keys.select! { |k| current_user.may_access?(k) }
@key = Key.new(environment: @environment, name: params[:id])
@key = Key.new(name: params[:id], hiera_data: @environment.hiera_data)
authorize! :show, @key

add_breadcrumb @environment, environment_nodes_path(@environment)
add_breadcrumb @node, environment_node_keys_path(@environment, @node)
add_breadcrumb params[:id], environment_node_key_path(@environment, @node, params[:id])
end

def update
@key = Key.new(@node, params[:id])
authorize! :update, @key
@key.save_value(params[:hierarchy], params[:path], params[:value])

redirect_to environment_node_key_path(@environment, @node, @key),
notice: "Value was saved successfully"
end

def destroy
@key = Key.new(@node, params[:id])
authorize! :destroy, @key
@key.remove_value(params[:hierarchy], params[:path])

redirect_to environment_node_key_path(@environment, @node, @key),
notice: "Value was removed successfully"
end
end
2 changes: 1 addition & 1 deletion app/controllers/lookups_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def show
def load_keys
@keys = Key.all_for(@node, environment: @environment)
@keys.select! { |k| current_user.may_access?(k) }
@key = Key.new(environment: @environment, name: params[:key_id])
@key = Key.new(name: params[:key_id], hiera_data: @environment.hiera_data)
authorize! :show, @key
end

Expand Down
11 changes: 6 additions & 5 deletions app/controllers/values_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class ValuesController < ApplicationController
def update
authorize! :update, Key

@value.update(params[:value], node: @node)
@value.update(params[:value])

redirect_to environment_node_key_path(@environment, @node, @key),
notice: "Value was saved successfully"
Expand All @@ -13,7 +13,7 @@ def update
def destroy
authorize! :destroy, Key

@value.destroy(node: @node)
@value.destroy

redirect_to environment_node_key_path(@environment, @node, @key),
status: :see_other,
Expand All @@ -25,9 +25,10 @@ def destroy
def instantiate_models
@environment = Environment.find(params[:environment_id])
@node = Node.new(hostname: params[:node_id], environment: @environment)
@hierarchy = Hierarchy.find(@environment, params[:hierarchy_id])
@data_file = DataFile.new(hierarchy: @hierarchy, path: params[:data_file_id])
@key = Key.new(environment: @environment, name: params[:key_id])
@layer = @environment.find_layer(name: params[:layer_id])
@hierarchy = Hierarchy.find(layer: @layer, name: params[:hierarchy_id])
@data_file = @hierarchy.file(path: params[:data_file_id], node: @node)
@key = Key.new(name: params[:key_id])
@value = @data_file.value_for(key: @key)
end
end
2 changes: 1 addition & 1 deletion app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def flash_class(level)

def format_path(file, key)
tag_name, classes =
if file.has_key?(key) # rubocop:disable Style/PreferredHashMethods
if file.has_key?(key:) # rubocop:disable Style/PreferredHashMethods
[:b, "text-primary"]
elsif file.exist?
[:span, "text-dark"]
Expand Down
57 changes: 18 additions & 39 deletions app/models/data_file.rb
Original file line number Diff line number Diff line change
@@ -1,53 +1,34 @@
class DataFile < HieraModel
attribute :hierarchy
attribute :node
attribute :path, :string
attribute :exist, :boolean, default: false
attribute :writable, :boolean, default: false
attribute :replaced_from_git, :boolean, default: false
attribute :hiera_file

delegate :environment, to: :hierarchy

def self.search(environment, key)
hierarchies = {}
result = {}
HieraData.new(environment.name).files_including(key.name).each do |file|
hierarchies[file[:hierarchy_name]] ||= Hierarchy.new(
environment:,
name: file[:hierarchy_name],
backend: file[:hierarchy_backend]
)
data_file = new(
hierarchy: hierarchies[file[:hierarchy_name]],
path: file[:path]
)
value = Value.new(data_file:, key:, value: file[:value])
result[hierarchies[file[:hierarchy_name]]] ||= {}
result[hierarchies[file[:hierarchy_name]]][data_file] = value
end
result
end

def initialize(attributes = {})
super(attributes)
file_attributes = hiera_data.file_attributes(hierarchy.name, path, facts: node&.facts)
self.exist = file_attributes[:exist]
self.writable = file_attributes[:writable]
self.replaced_from_git = file_attributes[:replaced_from_git]
return unless hiera_file

self.exist = hiera_file.exist?
self.writable = hiera_file.writable?
self.replaced_from_git = hiera_file.replaced_from_git?
end

def keys
@keys ||= hiera_data.keys_in_file(hierarchy.name, path, facts: node&.facts).map do |key_name|
Key.new(environment:, name: key_name)
@keys ||= hiera_file.keys.map do |key_name|
Key.new(name: key_name)
end
end

def has_key?(key)
def has_key?(key:)
keys.include?(key)
end

def value_for(key:)
raw_value = (hiera_data.value_in_file(hierarchy.name, path, key.name, facts: node&.facts) if has_key?(key)) # rubocop:disable Style/PreferredHashMethods
raw_value = (hiera_file.content_for_key(key.name) if has_key?(key:)) # rubocop:disable Style/PreferredHashMethods
Value.new(data_file: self, key:, value: raw_value)
end

Expand All @@ -71,28 +52,26 @@ def id
[node&.name, path].join("-").parameterize
end

def has_differing_value_in_original_environment?(key)
def has_differing_value_in_original_environment?(node:, key:)
return false unless environment && node.environment
return false if environment == node.environment

candidate_files = node.environment.hierarchies.map do |h|
self.class.new(hierarchy: h, path:, node:)
candidate_files = node.environment.environment_layer.hierarchies.map do |h|
h.file(path:, node:)
end
other_file = candidate_files.find(&:exist?)
return false unless other_file

other_key = Key.new(environment: node.environment, name: key.name)
return false if value_for(key:).value == other_file.value_for(key: other_key).value
return false if value_for(key:).value == other_file.value_for(key:).value

true
end

def value_from_original_environment(key:)
candidate_files = (node&.environment&.hierarchies || []).map do |h|
self.class.new(hierarchy: h, path:, node:)
def value_from_original_environment(node:, key:)
candidate_files = (node&.environment&.environment_layer&.hierarchies || []).map do |h|
h.file(path:, node:)
end
other_file = candidate_files.find(&:exist?)
other_key = Key.new(environment: node.environment, name: key.name)
other_file.value_for(key: other_key)
other_file.value_for(key:)
end
end
20 changes: 17 additions & 3 deletions app/models/environment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ class Environment < HieraModel

def self.all
environments_in_use = PuppetDbClient.environments
available_environments = HieraData.environments
available_environments = HieraData.environments(
config_dir: Rails.configuration.hdm.config_dir
)
all_environments = {}
environments_in_use.sort.each do |e|
all_environments[e] = { name: e, in_use: true }
Expand All @@ -21,8 +23,16 @@ def self.find(name)
all.find { |e| e.name == name }
end

def hierarchies
Hierarchy.all(self)
def layers
Layer.all(environment: self)
end

def find_layer(name:)
layers.find { |l| l.name == name }
end

def environment_layer
@environment_layer ||= find_layer(name: "environment")
end

def in_use?
Expand All @@ -44,4 +54,8 @@ def to_param
def to_s
name
end

def hiera_data
@hiera_data ||= HieraData.new(environment: name)
end
end
Loading

0 comments on commit 594517e

Please sign in to comment.