Module: Moose::Inventory::DB::SchemaMigrations
- Included in:
- Moose::Inventory::DB
- Defined in:
- lib/moose_inventory/db/schema_migrations.rb
Overview
Schema definitions, ordered migrations, and schema-artifact helpers for Moose Inventory DB. rubocop:disable Metrics/ModuleLength
Constant Summary collapse
- SCHEMA_VERSION =
4- TABLE_DEFINITIONS =
{ hosts: lambda do |db| db.create_table(:hosts) do primary_key :id column :name, :text, unique: true end end, hostvars: lambda do |db| db.create_table(:hostvars) do primary_key :id foreign_key :host_id column :name, :text column :value, :text end end, groups: lambda do |db| db.create_table(:groups) do primary_key :id column :name, :text, unique: true end end, groups_groups: lambda do |db| db.create_table(:groups_groups) do primary_key :id foreign_key :parent_id, :groups foreign_key :child_id, :groups end end, groupvars: lambda do |db| db.create_table(:groupvars) do primary_key :id foreign_key :group_id column :name, :text column :value, :text end end, groups_hosts: lambda do |db| db.create_table(:groups_hosts) do primary_key :id foreign_key :host_id, :hosts foreign_key :group_id, :groups end end, schema_info: lambda do |db| db.create_table(:schema_info) do primary_key :id column :version, :integer, null: false end end, audit_events: lambda do |db| db.create_table(:audit_events) do primary_key :id column :created_at, :text, null: false column :actor, :text column :command, :text, null: false column :action, :text, null: false column :entity_type, :text column :entity_name, :text column :details, :text end end, tags: lambda do |db| db.create_table(:tags) do primary_key :id column :name, :text, unique: true, null: false end end, hosts_tags: lambda do |db| db.create_table(:hosts_tags) do primary_key :id foreign_key :host_id, :hosts foreign_key :tag_id, :tags end end, groups_tags: lambda do |db| db.create_table(:groups_tags) do primary_key :id foreign_key :group_id, :groups foreign_key :tag_id, :tags end end }.freeze
- SCHEMA_MIGRATIONS =
{ 1 => %i[hosts hostvars groups groups_groups groupvars groups_hosts schema_info], 2 => %i[audit_events], 3 => %i[tags hosts_tags groups_tags], 4 => [] }.freeze
- INDEX_DEFINITIONS =
[ { table: :hostvars, columns: %i[host_id name], unique: true, name: :idx_hostvars_host_id_name }, { table: :groupvars, columns: %i[group_id name], unique: true, name: :idx_groupvars_group_id_name }, { table: :groups_hosts, columns: %i[host_id group_id], unique: true, name: :idx_groups_hosts_host_id_group_id }, { table: :groups_groups, columns: %i[parent_id child_id], unique: true, name: :idx_groups_groups_parent_id_child_id }, { table: :hosts_tags, columns: %i[host_id tag_id], unique: true, name: :idx_hosts_tags_host_id_tag_id }, { table: :groups_tags, columns: %i[group_id tag_id], unique: true, name: :idx_groups_tags_group_id_tag_id }, { table: :groups_hosts, columns: %i[group_id host_id], unique: false, name: :idx_groups_hosts_group_id_host_id }, { table: :groups_groups, columns: %i[child_id parent_id], unique: false, name: :idx_groups_groups_child_id_parent_id }, { table: :hosts_tags, columns: %i[tag_id host_id], unique: false, name: :idx_hosts_tags_tag_id_host_id }, { table: :groups_tags, columns: %i[tag_id group_id], unique: false, name: :idx_groups_tags_tag_id_group_id } ].freeze
Instance Method Summary collapse
- #add_index(definition) ⇒ Object
- #apply_schema_indexes! ⇒ Object
- #apply_schema_migration!(version) ⇒ Object
- #clean_duplicate_index_rows! ⇒ Object
- #create_table(table_name, definition = TABLE_DEFINITIONS.fetch(table_name)) ⇒ Object
- #create_tables ⇒ Object
- #dedupe_duplicate_rows!(table_name, columns, value_columns: []) ⇒ Object
- #duplicate_keys(table_name, columns) ⇒ Object
- #index_exists?(table_name, index_name) ⇒ Boolean
- #migrate_schema! ⇒ Object
- #migration_versions ⇒ Object
- #record_schema_version!(version) ⇒ Object
- #reject_conflicting_duplicates!(table_name, key, rows, value_columns) ⇒ Object
- #reject_future_schema! ⇒ Object
- #schema_indexes_missing? ⇒ Boolean
- #schema_migration_artifacts_missing?(version) ⇒ Boolean
- #schema_migration_tables_missing?(version) ⇒ Boolean
- #schema_version ⇒ Object
Instance Method Details
#add_index(definition) ⇒ Object
199 200 201 202 203 204 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 199 def add_index(definition) return if index_exists?(definition.fetch(:table), definition.fetch(:name)) @db.add_index(definition.fetch(:table), definition.fetch(:columns), unique: definition.fetch(:unique), name: definition.fetch(:name)) end |
#apply_schema_indexes! ⇒ Object
159 160 161 162 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 159 def apply_schema_indexes! clean_duplicate_index_rows! INDEX_DEFINITIONS.each { |definition| add_index(definition) } end |
#apply_schema_migration!(version) ⇒ Object
152 153 154 155 156 157 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 152 def apply_schema_migration!(version) tables = SCHEMA_MIGRATIONS.fetch(version) tables.each { |table_name| create_table(table_name) } apply_schema_indexes! if version == 4 record_schema_version!(version) end |
#clean_duplicate_index_rows! ⇒ Object
164 165 166 167 168 169 170 171 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 164 def clean_duplicate_index_rows! dedupe_duplicate_rows!(:hostvars, %i[host_id name], value_columns: [:value]) dedupe_duplicate_rows!(:groupvars, %i[group_id name], value_columns: [:value]) dedupe_duplicate_rows!(:groups_hosts, %i[host_id group_id]) dedupe_duplicate_rows!(:groups_groups, %i[parent_id child_id]) dedupe_duplicate_rows!(:hosts_tags, %i[host_id tag_id]) dedupe_duplicate_rows!(:groups_tags, %i[group_id tag_id]) end |
#create_table(table_name, definition = TABLE_DEFINITIONS.fetch(table_name)) ⇒ Object
239 240 241 242 243 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 239 def create_table(table_name, definition = TABLE_DEFINITIONS.fetch(table_name)) return if @db.table_exists?(table_name) definition.call(@db) end |
#create_tables ⇒ Object
233 234 235 236 237 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 233 def create_tables TABLE_DEFINITIONS.each do |table_name, definition| create_table(table_name, definition) end end |
#dedupe_duplicate_rows!(table_name, columns, value_columns: []) ⇒ Object
173 174 175 176 177 178 179 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 173 def dedupe_duplicate_rows!(table_name, columns, value_columns: []) duplicate_keys(table_name, columns).each do |key| rows = @db[table_name].where(key).order(:id).all reject_conflicting_duplicates!(table_name, key, rows, value_columns) @db[table_name].where(id: rows.drop(1).map { |row| row.fetch(:id) }).delete end end |
#duplicate_keys(table_name, columns) ⇒ Object
181 182 183 184 185 186 187 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 181 def duplicate_keys(table_name, columns) @db[table_name] .select(*columns) .group(*columns) .having { count(id) > 1 } .all end |
#index_exists?(table_name, index_name) ⇒ Boolean
206 207 208 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 206 def index_exists?(table_name, index_name) @db.indexes(table_name).key?(index_name) end |
#migrate_schema! ⇒ Object
128 129 130 131 132 133 134 135 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 128 def migrate_schema! reject_future_schema! migration_versions.each do |version| next if schema_version.to_i >= version && !schema_migration_artifacts_missing?(version) apply_schema_migration!(version) end end |
#migration_versions ⇒ Object
118 119 120 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 118 def migration_versions SCHEMA_MIGRATIONS.keys.sort end |
#record_schema_version!(version) ⇒ Object
210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 210 def record_schema_version!(version) unless @db.table_exists?(:schema_info) raise @exceptions[:moose], 'Cannot record schema version before schema_info exists.' end if @db[:schema_info].empty? @db[:schema_info].insert(version: version) else @db[:schema_info].update(version: version) end end |
#reject_conflicting_duplicates!(table_name, key, rows, value_columns) ⇒ Object
189 190 191 192 193 194 195 196 197 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 189 def reject_conflicting_duplicates!(table_name, key, rows, value_columns) conflicts = value_columns.any? do |column| rows.map { |row| row[column] }.uniq.length > 1 end return unless conflicts raise @exceptions[:moose], "Cannot add unique indexes because #{table_name} has conflicting duplicates " \ "for #{key}. Resolve duplicate values before migrating." end |
#reject_future_schema! ⇒ Object
223 224 225 226 227 228 229 230 231 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 223 def reject_future_schema! return unless @db.table_exists?(:schema_info) current_version = schema_version return if current_version.nil? || current_version <= SCHEMA_VERSION raise @exceptions[:moose], "Database schema version #{current_version} is newer than supported version " \ "#{SCHEMA_VERSION}. Upgrade moose-inventory before using this database." end |
#schema_indexes_missing? ⇒ Boolean
145 146 147 148 149 150 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 145 def schema_indexes_missing? INDEX_DEFINITIONS.any? do |definition| !@db.table_exists?(definition.fetch(:table)) || !index_exists?(definition.fetch(:table), definition.fetch(:name)) end end |
#schema_migration_artifacts_missing?(version) ⇒ Boolean
137 138 139 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 137 def schema_migration_artifacts_missing?(version) schema_migration_tables_missing?(version) || (version == 4 && schema_indexes_missing?) end |
#schema_migration_tables_missing?(version) ⇒ Boolean
141 142 143 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 141 def schema_migration_tables_missing?(version) SCHEMA_MIGRATIONS.fetch(version).any? { |table_name| !@db.table_exists?(table_name) } end |
#schema_version ⇒ Object
122 123 124 125 126 |
# File 'lib/moose_inventory/db/schema_migrations.rb', line 122 def schema_version return nil unless @db.table_exists?(:schema_info) @db[:schema_info].order(:id).last&.fetch(:version) end |