diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 02fde23..7de8612 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2024-10-07 16:25:55 UTC using RuboCop version 1.66.1. +# on 2024-10-07 18:05:57 UTC using RuboCop version 1.66.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -33,7 +33,7 @@ Lint/UnderscorePrefixedVariableName: Exclude: - 'spec/lib/droplet_kit/client_spec.rb' -# Offense count: 37 +# Offense count: 38 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AutoCorrect, IgnoreEmptyBlocks, AllowUnusedKeywordArguments. Lint/UnusedBlockArgument: @@ -51,16 +51,16 @@ Lint/Void: Metrics/AbcSize: Max: 184 -# Offense count: 16 +# Offense count: 24 # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode. # AllowedMethods: refine Metrics/BlockLength: - Max: 138 + Max: 158 # Offense count: 1 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 144 + Max: 164 # Offense count: 6 # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. @@ -70,7 +70,7 @@ Metrics/MethodLength: # Offense count: 1 # Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: - Max: 169 + Max: 183 # Offense count: 1 # This cop supports unsafe autocorrection (--autocorrect-all). @@ -90,7 +90,7 @@ Naming/VariableNumber: - 'spec/lib/droplet_kit/resources/firewall_resource_spec.rb' - 'spec/lib/droplet_kit/resources/load_balancer_resource_spec.rb' -# Offense count: 34 +# Offense count: 46 # Configuration parameters: Prefixes, AllowedPatterns. # Prefixes: when, with, without RSpec/ContextWording: @@ -110,7 +110,7 @@ RSpec/ContextWording: - 'spec/lib/droplet_kit/resources/vpc_resource_spec.rb' - 'spec/support/resource_context.rb' -# Offense count: 123 +# Offense count: 130 # Configuration parameters: CountAsOne. RSpec/ExampleLength: Max: 43 @@ -125,7 +125,7 @@ RSpec/LeakyConstantDeclaration: Exclude: - 'spec/lib/droplet_kit/client_spec.rb' -# Offense count: 123 +# Offense count: 129 RSpec/MultipleExpectations: Max: 30 @@ -145,7 +145,7 @@ RSpec/NestedGroups: RSpec/SpecFilePathFormat: Enabled: false -# Offense count: 170 +# Offense count: 186 # Configuration parameters: AllowedConstants. Style/Documentation: Enabled: false @@ -173,7 +173,7 @@ Style/SymbolProc: - 'lib/droplet_kit/resources/kubernetes_cluster_resource.rb' - 'lib/tasks/resource_doc.rake' -# Offense count: 92 +# Offense count: 106 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. # URISchemes: http, https diff --git a/README.md b/README.md index 215b76f..4ce6d77 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,18 @@ Actions supported: * `client.databases.get_sql_mode(id: 'id')` * `client.databases.get_metrics_credentials` * `client.databases.update_metrics_credentials(database_metrics_credentials)` +* `client.databases.get_mongo_config(id: 'id')` +* `client.databases.get_postgres_config(id: 'id')` +* `client.databases.get_mysql_config(id: 'id')` +* `client.databases.get_redis_config(id: 'id')` +* `client.databases.get_kafka_config(id: 'id')` +* `client.databases.get_opensearch_config(id: 'id')` +* `client.databases.update_mongo_config(mongo_config, id: 'id')` +* `client.databases.update_postgres_config(postgres_config, id: 'id')` +* `client.databases.update_mysql_config(mysql_config, id: 'id')` +* `client.databases.update_redis_config(redis_config, id: 'id')` +* `client.databases.update_kafka_config(kafka_config, id: 'id')` +* `client.databases.update_opensearch_config(opensearch_config, id: 'id')` ## Droplet resource diff --git a/lib/droplet_kit.rb b/lib/droplet_kit.rb index b2553a9..bd468a1 100644 --- a/lib/droplet_kit.rb +++ b/lib/droplet_kit.rb @@ -49,6 +49,14 @@ module DropletKit autoload :DatabaseMaintenanceWindow, 'droplet_kit/models/database_maintenance_window' autoload :DatabaseReplica, 'droplet_kit/models/database_replica' autoload :DatabaseSQLMode, 'droplet_kit/models/database_sql_mode' + autoload :DatabaseMongoConfig, 'droplet_kit/models/database_mongo_config' + autoload :DatabaseKafkaConfig, 'droplet_kit/models/database_kafka_config' + autoload :DatabaseMysqlConfig, 'droplet_kit/models/database_mysql_config' + autoload :DatabasePostgresTimescaledbConfig, 'droplet_kit/models/database_postgres_config' + autoload :DatabasePostgresPgbouncerConfig, 'droplet_kit/models/database_postgres_config' + autoload :DatabasePostgresConfig, 'droplet_kit/models/database_postgres_config' + autoload :DatabaseRedisConfig, 'droplet_kit/models/database_redis_config' + autoload :DatabaseOpensearchConfig, 'droplet_kit/models/database_opensearch_config' autoload :DatabaseUser, 'droplet_kit/models/database_user' autoload :DatabaseUserResetAuth, 'droplet_kit/models/database_user_reset_auth' autoload :DatabaseUserMySQLSettings, 'droplet_kit/models/database_user_mysql_settings' @@ -151,6 +159,12 @@ module DropletKit autoload :DatabaseMaintenanceWindowMapping, 'droplet_kit/mappings/database_maintenance_window_mapping' autoload :DatabaseReplicaMapping, 'droplet_kit/mappings/database_replica_mapping' autoload :DatabaseSQLModeMapping, 'droplet_kit/mappings/database_sql_mode_mapping' + autoload :DatabaseMongoConfigMapping, 'droplet_kit/mappings/database_mongo_config_mapping' + autoload :DatabaseKafkaConfigMapping, 'droplet_kit/mappings/database_kafka_config_mapping' + autoload :DatabaseMysqlConfigMapping, 'droplet_kit/mappings/database_mysql_config_mapping' + autoload :DatabasePostgresConfigMapping, 'droplet_kit/mappings/database_postgres_config_mapping' + autoload :DatabaseRedisConfigMapping, 'droplet_kit/mappings/database_redis_config_mapping' + autoload :DatabaseOpensearchConfigMapping, 'droplet_kit/mappings/database_opensearch_config_mapping' autoload :DatabaseUserMapping, 'droplet_kit/mappings/database_user_mapping' autoload :DatabaseUserResetAuthMapping, 'droplet_kit/mappings/database_user_reset_auth_mapping' autoload :DatabaseMetricsCredentialsMapping, 'droplet_kit/mappings/database_metrics_credentials_mapping' diff --git a/lib/droplet_kit/mappings/database_kafka_config_mapping.rb b/lib/droplet_kit/mappings/database_kafka_config_mapping.rb new file mode 100644 index 0000000..fa318ab --- /dev/null +++ b/lib/droplet_kit/mappings/database_kafka_config_mapping.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module DropletKit + class DatabaseKafkaConfigMapping + include Kartograph::DSL + + kartograph do + mapping DatabaseKafkaConfig + root_key singular: 'config', scopes: %i[read update] + + scoped :read, :update do + %i[compression_type + group_initial_rebalance_delay_ms + group_min_session_timeout_ms + group_max_session_timeout_ms + connections_max_idle_ms + max_incremental_fetch_session_cache_slots + message_max_bytes + offsets_retention_minutes + log_cleaner_delete_retention_ms + log_cleaner_min_cleanable_ratio + log_cleaner_max_compaction_lag_ms + log_cleaner_min_compaction_lag_ms + log_cleanup_policy + log_flush_interval_messages + log_flush_interval_ms + log_index_interval_bytes + log_index_size_max_bytes + log_message_downconversion_enable + log_message_timestamp_type + log_message_timestamp_difference_max_ms + log_preallocate + log_retention_bytes + log_retention_hours + log_retention_ms + log_roll_jitter_ms + log_roll_ms + log_segment_bytes + log_segment_delete_delay_ms + auto_create_topics_enable + min_insync_replicas + num_partitions + default_replication_factor + replica_fetch_max_bytes + replica_fetch_response_max_bytes + max_connections_per_ip + producer_purgatory_purge_interval_requests + socket_request_max_bytes + transaction_state_log_segment_bytes + transaction_remove_expired_transaction_cleanup_interval_ms].each do |key| + property(key) + end + end + end + end +end diff --git a/lib/droplet_kit/mappings/database_mongo_config_mapping.rb b/lib/droplet_kit/mappings/database_mongo_config_mapping.rb new file mode 100644 index 0000000..ad6b178 --- /dev/null +++ b/lib/droplet_kit/mappings/database_mongo_config_mapping.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module DropletKit + class DatabaseMongoConfigMapping + include Kartograph::DSL + + kartograph do + mapping DatabaseMongoConfig + root_key singular: 'config', scopes: %i[read update] + + scoped :read, :update do + %i[default_read_concern + default_write_concern + transaction_lifetime_limit_seconds + slow_op_threshold_ms + verbosity].each do |key| + property(key) + end + end + end + end +end diff --git a/lib/droplet_kit/mappings/database_mysql_config_mapping.rb b/lib/droplet_kit/mappings/database_mysql_config_mapping.rb new file mode 100644 index 0000000..479f0a3 --- /dev/null +++ b/lib/droplet_kit/mappings/database_mysql_config_mapping.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +module DropletKit + class DatabaseMysqlConfigMapping + include Kartograph::DSL + + kartograph do + mapping DatabaseMysqlConfig + root_key singular: 'config', scopes: %i[read update] + + scoped :read, :update do + %i[backup_hour + backup_minute + sql_mode + connect_timeout + default_time_zone + group_concat_max_len + information_schema_stats_expiry + innodb_ft_min_token_size + innodb_ft_server_stopword_table + innodb_lock_wait_timeout + innodb_log_buffer_size + innodb_online_alter_log_max_size + innodb_print_all_deadlocks + innodb_rollback_on_timeout + interactive_timeout + internal_tmp_mem_storage_engine + net_read_timeout + net_write_timeout + sql_require_primary_key + wait_timeout + max_allowed_packet + max_heap_table_size + sort_buffer_size + tmp_table_size + slow_query_log + long_query_time + binlog_retention_period + innodb_change_buffer_max_size + innodb_flush_neighbors + innodb_read_io_threads + innodb_write_io_threads + innodb_thread_concurrency + net_buffer_length].each do |key| + property(key) + end + end + end + end +end diff --git a/lib/droplet_kit/mappings/database_opensearch_config_mapping.rb b/lib/droplet_kit/mappings/database_opensearch_config_mapping.rb new file mode 100644 index 0000000..fedb9fc --- /dev/null +++ b/lib/droplet_kit/mappings/database_opensearch_config_mapping.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +module DropletKit + class DatabaseOpensearchConfigMapping + include Kartograph::DSL + + kartograph do + mapping DatabaseOpensearchConfig + root_key singular: 'config', scopes: %i[read update] + + scoped :read, :update do + %i[http_max_content_length_bytes + http_max_header_size_bytes + http_max_initial_line_length_bytes + indices_query_bool_max_clause_count + indices_fielddata_cache_size_percentage + indices_memory_index_buffer_size_percentage + indices_memory_min_index_buffer_size_mb + indices_memory_max_index_buffer_size_mb + indices_queries_cache_size_percentage + indices_recovery_max_mb_per_sec + indices_recovery_max_concurrent_file_chunks + thread_pool_search_size + thread_pool_search_throttled_size + thread_pool_get_size + thread_pool_analyze_size + thread_pool_write_size + thread_pool_force_merge_size + thread_pool_search_queue_size + thread_pool_search_throttled_queue_size + thread_pool_get_queue_size + thread_pool_analyze_queue_size + thread_pool_write_queue_size + ism_enabled + ism_history_enabled + ism_history_max_age_hours + ism_history_max_docs + ism_history_rollover_check_period_hours + ism_history_rollover_retention_period_days + search_max_buckets + action_auto_create_index_enabled + enable_security_audit + action_destructive_requires_name + cluster_max_shards_per_node + override_main_response_version + script_max_compilations_rate + cluster_routing_allocation_node_concurrent_recoveries + reindex_remote_whitelist + plugins_alerting_filter_by_backend_roles_enabled].each do |key| + property(key) + end + end + end + end +end diff --git a/lib/droplet_kit/mappings/database_postgres_config_mapping.rb b/lib/droplet_kit/mappings/database_postgres_config_mapping.rb new file mode 100644 index 0000000..a9e0e81 --- /dev/null +++ b/lib/droplet_kit/mappings/database_postgres_config_mapping.rb @@ -0,0 +1,97 @@ +# frozen_string_literal: true + +module DropletKit + class DatabasePostgresPgbouncerConfigMapping + include Kartograph::DSL + kartograph do + mapping DatabasePostgresPgbouncerConfig + + scoped :read, :update do + property :server_reset_query_always + property :ignore_startup_parameters + property :min_pool_size + property :server_lifetime + property :server_idle_timeout + property :autodb_pool_size + property :autodb_pool_mode + property :autodb_max_db_connections + property :autodb_idle_timeout + end + end + end + + class DatabasePostgresTimescaledbConfigMapping + include Kartograph::DSL + kartograph do + mapping DatabasePostgresTimescaledbConfig + property :max_background_workers, scopes: %i[read update] + end + end + + class DatabasePostgresConfigMapping + include Kartograph::DSL + + kartograph do + mapping DatabasePostgresConfig + root_key singular: 'config', scopes: %i[read update] + + scoped :read, :update do + %i[autovacuum_freeze_max_age + autovacuum_max_workers + autovacuum_naptime + autovacuum_vacuum_threshold + autovacuum_analyze_threshold + autovacuum_vacuum_scale_factor + autovacuum_analyze_scale_factor + autovacuum_vacuum_cost_delay + autovacuum_vacuum_cost_limit + bgwriter_delay + bgwriter_flush_after + bgwriter_lru_maxpages + bgwriter_lru_multiplier + deadlock_timeout + default_toast_compression + idle_in_transaction_session_timeout + jit + log_autovacuum_min_duration + log_error_verbosity + log_line_prefix + log_min_duration_statement + max_files_per_process + max_prepared_transactions + max_pred_locks_per_transaction + max_locks_per_transaction + max_stack_depth + max_standby_archive_delay + max_standby_streaming_delay + max_replication_slots + max_logical_replication_workers + max_parallel_workers + max_parallel_workers_per_gather + max_worker_processes + temp_file_limit + timezone + track_activity_query_size + track_commit_timestamp + track_functions + track_io_timing + max_wal_senders + wal_sender_timeout + wal_writer_delay + shared_buffers_percentage + backup_hour + backup_minute + work_mem].each do |key| + property(key) + end + + property :pg_partman_bgw_role, key: 'pg_partman_bgw.role' + property :pg_partman_bgw_interval, key: 'pg_partman_bgw.interval' + property :pg_stat_statements_track, key: 'pg_stat_statements.track' + + property :pgbouncer, include: DatabasePostgresPgbouncerConfigMapping + property :timescaledb, include: DatabasePostgresTimescaledbConfigMapping + end + end + end +end diff --git a/lib/droplet_kit/mappings/database_redis_config_mapping.rb b/lib/droplet_kit/mappings/database_redis_config_mapping.rb new file mode 100644 index 0000000..9104c38 --- /dev/null +++ b/lib/droplet_kit/mappings/database_redis_config_mapping.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module DropletKit + class DatabaseRedisConfigMapping + include Kartograph::DSL + + kartograph do + mapping DatabaseRedisConfig + root_key singular: 'config', scopes: %i[read update] + + scoped :read, :update do + %i[redis_maxmemory_policy + redis_pubsub_client_output_buffer_limit + redis_number_of_databases + redis_io_threads + redis_lfu_log_factor + redis_lfu_decay_time + redis_ssl + redis_timeout + redis_notify_keyspace_events + redis_persistence + redis_acl_channels_default].each do |key| + property(key) + end + end + end + end +end diff --git a/lib/droplet_kit/models/database_kafka_config.rb b/lib/droplet_kit/models/database_kafka_config.rb new file mode 100644 index 0000000..216e847 --- /dev/null +++ b/lib/droplet_kit/models/database_kafka_config.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module DropletKit + class DatabaseKafkaConfig < BaseModel + %i[compression_type + group_initial_rebalance_delay_ms + group_min_session_timeout_ms + group_max_session_timeout_ms + connections_max_idle_ms + max_incremental_fetch_session_cache_slots + message_max_bytes + offsets_retention_minutes + log_cleaner_delete_retention_ms + log_cleaner_min_cleanable_ratio + log_cleaner_max_compaction_lag_ms + log_cleaner_min_compaction_lag_ms + log_cleanup_policy + log_flush_interval_messages + log_flush_interval_ms + log_index_interval_bytes + log_index_size_max_bytes + log_message_downconversion_enable + log_message_timestamp_type + log_message_timestamp_difference_max_ms + log_preallocate + log_retention_bytes + log_retention_hours + log_retention_ms + log_roll_jitter_ms + log_roll_ms + log_segment_bytes + log_segment_delete_delay_ms + auto_create_topics_enable + min_insync_replicas + num_partitions + default_replication_factor + replica_fetch_max_bytes + replica_fetch_response_max_bytes + max_connections_per_ip + producer_purgatory_purge_interval_requests + socket_request_max_bytes + transaction_state_log_segment_bytes + transaction_remove_expired_transaction_cleanup_interval_ms].each do |key| + attribute(key) + end + end +end diff --git a/lib/droplet_kit/models/database_mongo_config.rb b/lib/droplet_kit/models/database_mongo_config.rb new file mode 100644 index 0000000..7aabc41 --- /dev/null +++ b/lib/droplet_kit/models/database_mongo_config.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module DropletKit + class DatabaseMongoConfig < BaseModel + %i[default_read_concern + default_write_concern + transaction_lifetime_limit_seconds + slow_op_threshold_ms + verbosity].each do |key| + attribute(key) + end + end +end diff --git a/lib/droplet_kit/models/database_mysql_config.rb b/lib/droplet_kit/models/database_mysql_config.rb new file mode 100644 index 0000000..f0c221a --- /dev/null +++ b/lib/droplet_kit/models/database_mysql_config.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module DropletKit + class DatabaseMysqlConfig < BaseModel + %i[backup_hour + backup_minute + sql_mode + connect_timeout + default_time_zone + group_concat_max_len + information_schema_stats_expiry + innodb_ft_min_token_size + innodb_ft_server_stopword_table + innodb_lock_wait_timeout + innodb_log_buffer_size + innodb_online_alter_log_max_size + innodb_print_all_deadlocks + innodb_rollback_on_timeout + interactive_timeout + internal_tmp_mem_storage_engine + net_read_timeout + net_write_timeout + sql_require_primary_key + wait_timeout + max_allowed_packet + max_heap_table_size + sort_buffer_size + tmp_table_size + slow_query_log + long_query_time + binlog_retention_period + innodb_change_buffer_max_size + innodb_flush_neighbors + innodb_read_io_threads + innodb_write_io_threads + innodb_thread_concurrency + net_buffer_length].each do |key| + attribute(key) + end + end +end diff --git a/lib/droplet_kit/models/database_opensearch_config.rb b/lib/droplet_kit/models/database_opensearch_config.rb new file mode 100644 index 0000000..4e434c7 --- /dev/null +++ b/lib/droplet_kit/models/database_opensearch_config.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module DropletKit + class DatabaseOpensearchConfig < BaseModel + %i[http_max_content_length_bytes + http_max_header_size_bytes + http_max_initial_line_length_bytes + indices_query_bool_max_clause_count + indices_fielddata_cache_size_percentage + indices_memory_index_buffer_size_percentage + indices_memory_min_index_buffer_size_mb + indices_memory_max_index_buffer_size_mb + indices_queries_cache_size_percentage + indices_recovery_max_mb_per_sec + indices_recovery_max_concurrent_file_chunks + thread_pool_search_size + thread_pool_search_throttled_size + thread_pool_get_size + thread_pool_analyze_size + thread_pool_write_size + thread_pool_force_merge_size + thread_pool_search_queue_size + thread_pool_search_throttled_queue_size + thread_pool_get_queue_size + thread_pool_analyze_queue_size + thread_pool_write_queue_size + ism_enabled + ism_history_enabled + ism_history_max_age_hours + ism_history_max_docs + ism_history_rollover_check_period_hours + ism_history_rollover_retention_period_days + search_max_buckets + action_auto_create_index_enabled + enable_security_audit + action_destructive_requires_name + cluster_max_shards_per_node + override_main_response_version + script_max_compilations_rate + cluster_routing_allocation_node_concurrent_recoveries + reindex_remote_whitelist + plugins_alerting_filter_by_backend_roles_enabled].each do |key| + attribute(key) + end + end +end diff --git a/lib/droplet_kit/models/database_postgres_config.rb b/lib/droplet_kit/models/database_postgres_config.rb new file mode 100644 index 0000000..39a8871 --- /dev/null +++ b/lib/droplet_kit/models/database_postgres_config.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +module DropletKit + class DatabasePostgresTimescaledbConfig < BaseModel + attribute :max_background_workers + end + + class DatabasePostgresPgbouncerConfig < BaseModel + attribute :server_reset_query_always + attribute :ignore_startup_parameters + attribute :min_pool_size + attribute :server_lifetime + attribute :server_idle_timeout + attribute :autodb_pool_size + attribute :autodb_pool_mode + attribute :autodb_max_db_connections + attribute :autodb_idle_timeout + end + + class DatabasePostgresConfig < BaseModel + %i[autovacuum_freeze_max_age + autovacuum_max_workers + autovacuum_naptime + autovacuum_vacuum_threshold + autovacuum_analyze_threshold + autovacuum_vacuum_scale_factor + autovacuum_analyze_scale_factor + autovacuum_vacuum_cost_delay + autovacuum_vacuum_cost_limit + bgwriter_delay + bgwriter_flush_after + bgwriter_lru_maxpages + bgwriter_lru_multiplier + deadlock_timeout + default_toast_compression + idle_in_transaction_session_timeout + jit + log_autovacuum_min_duration + log_error_verbosity + log_line_prefix + log_min_duration_statement + max_files_per_process + max_prepared_transactions + max_pred_locks_per_transaction + max_locks_per_transaction + max_stack_depth + max_standby_archive_delay + max_standby_streaming_delay + max_replication_slots + max_logical_replication_workers + max_parallel_workers + max_parallel_workers_per_gather + max_worker_processes + pg_partman_bgw_role + pg_partman_bgw_interval + pg_stat_statements_track + temp_file_limit + timezone + track_activity_query_size + track_commit_timestamp + track_functions + track_io_timing + max_wal_senders + wal_sender_timeout + wal_writer_delay + shared_buffers_percentage + backup_hour + backup_minute + work_mem].each do |key| + attribute(key) + end + + attribute :timescaledb, DatabasePostgresTimescaledbConfig + attribute :pgbouncer, DatabasePostgresPgbouncerConfig + end +end diff --git a/lib/droplet_kit/models/database_redis_config.rb b/lib/droplet_kit/models/database_redis_config.rb new file mode 100644 index 0000000..170952b --- /dev/null +++ b/lib/droplet_kit/models/database_redis_config.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module DropletKit + class DatabaseRedisConfig < BaseModel + %i[redis_maxmemory_policy + redis_pubsub_client_output_buffer_limit + redis_number_of_databases + redis_io_threads + redis_lfu_log_factor + redis_lfu_decay_time + redis_ssl + redis_timeout + redis_notify_keyspace_events + redis_persistence + redis_acl_channels_default].each do |key| + attribute(key) + end + end +end diff --git a/lib/droplet_kit/resources/database_resource.rb b/lib/droplet_kit/resources/database_resource.rb index 5fdca6d..eacf052 100644 --- a/lib/droplet_kit/resources/database_resource.rb +++ b/lib/droplet_kit/resources/database_resource.rb @@ -179,6 +179,28 @@ class DatabaseResource < ResourceKit::Resource body { |object| DatabaseMetricsCredentialsMapping.representation_for(:update, object) } handler(204) { |response| true } end + + %w[ + kafka + postgres + redis + opensearch + mysql + mongo + ].each do |database| + action :"get_#{database}_config", 'GET /v2/databases/:id/config' do + handler(200) do |response| + DropletKit.const_get("Database#{database.capitalize}ConfigMapping").extract_single(response.body, :read) + end + end + + action :"update_#{database}_config", 'PATCH /v2/databases/:id/config' do + body do |object| + DropletKit.const_get("Database#{database.capitalize}ConfigMapping").representation_for(:update, object) + end + handler(200) { |response| true } + end + end end def all(*args) diff --git a/spec/fixtures/databases/get_config_kafka_response.json b/spec/fixtures/databases/get_config_kafka_response.json new file mode 100644 index 0000000..711ebae --- /dev/null +++ b/spec/fixtures/databases/get_config_kafka_response.json @@ -0,0 +1,21 @@ +{ + "config": { + "group_initial_rebalance_delay_ms": 3000, + "group_min_session_timeout_ms": 6000, + "group_max_session_timeout_ms": 1800000, + "message_max_bytes": 1048588, + "log_cleaner_delete_retention_ms": 86400000, + "log_cleaner_min_compaction_lag_ms": 0, + "log_flush_interval_ms": 60000, + "log_index_interval_bytes": 4096, + "log_message_downconversion_enable": true, + "log_message_timestamp_difference_max_ms": 120000, + "log_preallocate": false, + "log_retention_bytes": -1, + "log_retention_hours": 168, + "log_retention_ms": 604800000, + "log_roll_jitter_ms": 0, + "log_segment_delete_delay_ms": 60000, + "auto_create_topics_enable": true + } +} diff --git a/spec/fixtures/databases/get_config_mongo_response.json b/spec/fixtures/databases/get_config_mongo_response.json new file mode 100644 index 0000000..46267a3 --- /dev/null +++ b/spec/fixtures/databases/get_config_mongo_response.json @@ -0,0 +1,9 @@ +{ + "config": { + "default_read_concern": "LOCAL", + "default_write_concern": "majority", + "transaction_lifetime_limit_seconds": 60, + "slow_op_threshold_ms": 100, + "verbosity": 0 + } +} diff --git a/spec/fixtures/databases/get_config_mysql_response.json b/spec/fixtures/databases/get_config_mysql_response.json new file mode 100644 index 0000000..e290382 --- /dev/null +++ b/spec/fixtures/databases/get_config_mysql_response.json @@ -0,0 +1,14 @@ +{ + "config": { + "sql_mode": "ANSI,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,STRICT_ALL_TABLES", + "sql_require_primary_key": true, + "innodb_ft_min_token_size": 3, + "innodb_ft_server_stopword_table": "", + "innodb_print_all_deadlocks": false, + "innodb_rollback_on_timeout": false, + "slow_query_log": false, + "long_query_time": 10, + "backup_hour": 21, + "backup_minute": 59 + } +} diff --git a/spec/fixtures/databases/get_config_opensearch_response.json b/spec/fixtures/databases/get_config_opensearch_response.json new file mode 100644 index 0000000..7f9eba5 --- /dev/null +++ b/spec/fixtures/databases/get_config_opensearch_response.json @@ -0,0 +1,41 @@ +{ + "config": { + "ism_enabled": true, + "ism_history_enabled": true, + "ism_history_max_age_hours": 24, + "ism_history_max_docs": 2500000, + "ism_history_rollover_check_period_hours": 8, + "ism_history_rollover_retention_period_days": 30, + "http_max_content_length_bytes": 100000000, + "http_max_header_size_bytes": 8192, + "http_max_initial_line_length_bytes": 4096, + "indices_query_bool_max_clause_count": 1024, + "search_max_buckets": 10000, + "indices_fielddata_cache_size_percentage": 0, + "indices_memory_index_buffer_size_percentage": 10, + "indices_memory_min_index_buffer_size_mb": 48, + "indices_memory_max_index_buffer_size_mb": 0, + "indices_queries_cache_size_percentage": 10, + "indices_recovery_max_mb_per_sec": 40, + "indices_recovery_max_concurrent_file_chunks": 2, + "action_auto_create_index_enabled": true, + "action_destructive_requires_name": false, + "enable_security_audit": false, + "thread_pool_search_size": 0, + "thread_pool_search_throttled_size": 0, + "thread_pool_search_throttled_queue_size": 0, + "thread_pool_search_queue_size": 0, + "thread_pool_get_size": 0, + "thread_pool_get_queue_size": 0, + "thread_pool_analyze_size": 0, + "thread_pool_analyze_queue_size": 0, + "thread_pool_write_size": 0, + "thread_pool_write_queue_size": 0, + "thread_pool_force_merge_size": 0, + "override_main_response_version": false, + "script_max_compilations_rate": "use-context", + "cluster_max_shards_per_node": 0, + "cluster_routing_allocation_node_concurrent_recoveries": 2, + "plugins_alerting_filter_by_backend_roles_enabled": true + } +} diff --git a/spec/fixtures/databases/get_config_postgres_response.json b/spec/fixtures/databases/get_config_postgres_response.json new file mode 100644 index 0000000..dbd900e --- /dev/null +++ b/spec/fixtures/databases/get_config_postgres_response.json @@ -0,0 +1,35 @@ +{ + "config": { + "autovacuum_naptime": 60, + "autovacuum_vacuum_threshold": 50, + "autovacuum_analyze_threshold": 50, + "autovacuum_vacuum_scale_factor": 0.2, + "autovacuum_analyze_scale_factor": 0.2, + "autovacuum_vacuum_cost_delay": 20, + "autovacuum_vacuum_cost_limit": -1, + "bgwriter_flush_after": 512, + "bgwriter_lru_maxpages": 100, + "bgwriter_lru_multiplier": 2, + "idle_in_transaction_session_timeout": 0, + "jit": true, + "log_autovacuum_min_duration": -1, + "log_min_duration_statement": -1, + "max_prepared_transactions": 0, + "max_parallel_workers": 8, + "max_parallel_workers_per_gather": 2, + "temp_file_limit": -1, + "wal_sender_timeout": 60000, + "backup_hour": 18, + "backup_minute": 26, + "pg_partman_bgw.role": "role", + "pg_partman_bgw.interval": 3600, + "pg_stat_statements.track": "all", + "timescaledb": { + "max_background_workers": 1 + }, + "pgbouncer": { + "server_reset_query_always": true, + "ignore_startup_parameters": ["param1", "param2"] + } + } +} diff --git a/spec/fixtures/databases/get_config_redis_response.json b/spec/fixtures/databases/get_config_redis_response.json new file mode 100644 index 0000000..0549c16 --- /dev/null +++ b/spec/fixtures/databases/get_config_redis_response.json @@ -0,0 +1,12 @@ +{ + "config": { + "redis_maxmemory_policy": "allkeys-lru", + "redis_lfu_log_factor": 10, + "redis_lfu_decay_time": 1, + "redis_ssl": true, + "redis_timeout": 300, + "redis_notify_keyspace_events": "", + "redis_persistence": "off", + "redis_acl_channels_default": "allchannels" + } +} diff --git a/spec/lib/droplet_kit/resources/database_resource_spec.rb b/spec/lib/droplet_kit/resources/database_resource_spec.rb index 5bc4536..37df9ef 100644 --- a/spec/lib/droplet_kit/resources/database_resource_spec.rb +++ b/spec/lib/droplet_kit/resources/database_resource_spec.rb @@ -621,6 +621,183 @@ end end + describe '#get__config' do + context 'for a mongo database' do + it 'returns the config' do + request = stub_do_api("/v2/databases/#{database_cluster_id}/config", :get).to_return(body: api_fixture('databases/get_config_mongo_response'), status: 200) + config = resource.get_mongo_config(id: database_cluster_id) + + expect(config).to be_a(DropletKit::DatabaseMongoConfig) + expect(config.default_write_concern).to eq('majority') + expect(request).to have_been_made + end + end + + context 'for a kafka database' do + it 'returns the config' do + request = stub_do_api("/v2/databases/#{database_cluster_id}/config", :get).to_return(body: api_fixture('databases/get_config_kafka_response'), status: 200) + config = resource.get_kafka_config(id: database_cluster_id) + + expect(config).to be_a(DropletKit::DatabaseKafkaConfig) + expect(config.log_retention_bytes).to eq(-1) + expect(request).to have_been_made + end + end + + context 'for a mysql database' do + it 'returns the config' do + request = stub_do_api("/v2/databases/#{database_cluster_id}/config", :get).to_return(body: api_fixture('databases/get_config_mysql_response'), status: 200) + config = resource.get_mysql_config(id: database_cluster_id) + + expect(config).to be_a(DropletKit::DatabaseMysqlConfig) + expect(config.sql_mode).to eq('ANSI,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,STRICT_ALL_TABLES') + expect(request).to have_been_made + end + end + + context 'for a postgres database' do + it 'returns the config' do + request = stub_do_api("/v2/databases/#{database_cluster_id}/config", :get).to_return(body: api_fixture('databases/get_config_postgres_response'), status: 200) + config = resource.get_postgres_config(id: database_cluster_id) + + expect(config).to be_a(DropletKit::DatabasePostgresConfig) + expect(config.autovacuum_naptime).to eq(60) + expect(config.pg_partman_bgw_role).to eq('role') + expect(config.pg_partman_bgw_interval).to eq(3600) + expect(config.pg_stat_statements_track).to eq('all') + expect(config.timescaledb).to be_a(DropletKit::DatabasePostgresTimescaledbConfig) + expect(config.timescaledb.max_background_workers).to eq(1) + expect(config.pgbouncer).to be_a(DropletKit::DatabasePostgresPgbouncerConfig) + expect(config.pgbouncer.server_reset_query_always).to be_truthy + expect(config.pgbouncer.ignore_startup_parameters).to eq(%w[param1 param2]) + expect(request).to have_been_made + end + end + + context 'for a redis database' do + it 'returns the config' do + request = stub_do_api("/v2/databases/#{database_cluster_id}/config", :get).to_return(body: api_fixture('databases/get_config_redis_response'), status: 200) + config = resource.get_redis_config(id: database_cluster_id) + + expect(config).to be_a(DropletKit::DatabaseRedisConfig) + expect(config.redis_maxmemory_policy).to eq('allkeys-lru') + expect(request).to have_been_made + end + end + + context 'for a opensearch database' do + it 'returns the config' do + request = stub_do_api("/v2/databases/#{database_cluster_id}/config", :get).to_return(body: api_fixture('databases/get_config_opensearch_response'), status: 200) + config = resource.get_opensearch_config(id: database_cluster_id) + + expect(config).to be_a(DropletKit::DatabaseOpensearchConfig) + expect(config.ism_enabled).to be_truthy + expect(request).to have_been_made + end + end + end + + describe '#update__config' do + context 'for a mongo database' do + it 'updates the config' do + mongo_config = DropletKit::DatabaseMongoConfig.new( + default_read_concern: 'majority', + default_write_concern: 'majority', + transaction_lifetime_limit_seconds: 60, + slow_op_threshold_ms: 250, + verbosity: '1' + ) + + json_body = DropletKit::DatabaseMongoConfigMapping.representation_for(:update, mongo_config) + request = stub_do_api("/v2/databases/#{database_cluster_id}/config", :patch).with(body: json_body).to_return(status: 200) + resource.update_mongo_config(mongo_config, id: database_cluster_id) + + expect(request).to have_been_made + end + end + + context 'for a kafka database' do + it 'updates the config' do + kafka_config = DropletKit::DatabaseKafkaConfig.new( + log_retention_bytes: -1, + log_retention_hours: 168 + ) + + json_body = DropletKit::DatabaseKafkaConfigMapping.representation_for(:update, kafka_config) + request = stub_do_api("/v2/databases/#{database_cluster_id}/config", :patch).with(body: json_body).to_return(status: 200) + resource.update_kafka_config(kafka_config, id: database_cluster_id) + + expect(request).to have_been_made + end + end + + context 'for a mysql database' do + it 'updates the config' do + mysql_config = DropletKit::DatabaseMysqlConfig.new( + sql_mode: 'ANSI,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,STRICT_ALL_TABLES' + ) + + json_body = DropletKit::DatabaseMysqlConfigMapping.representation_for(:update, mysql_config) + request = stub_do_api("/v2/databases/#{database_cluster_id}/config", :patch).with(body: json_body).to_return(status: 200) + resource.update_mysql_config(mysql_config, id: database_cluster_id) + + expect(request).to have_been_made + end + end + + context 'for a postgres database' do + it 'updates the config' do + postgres_config = DropletKit::DatabasePostgresConfig.new( + autovacuum_naptime: 60, + pg_partman_bgw_role: 'role', + pg_partman_bgw_interval: 3600, + pg_stat_statements_track: 'all', + timescaledb: DropletKit::DatabasePostgresTimescaledbConfig.new( + max_background_workers: 1 + ), + pgbouncer: DropletKit::DatabasePostgresPgbouncerConfig.new( + server_reset_query_always: true, + ignore_startup_parameters: %w[param1 param2] + ) + ) + + json_body = DropletKit::DatabasePostgresConfigMapping.representation_for(:update, postgres_config) + request = stub_do_api("/v2/databases/#{database_cluster_id}/config", :patch).with(body: json_body).to_return(status: 200) + resource.update_postgres_config(postgres_config, id: database_cluster_id) + + expect(request).to have_been_made + end + end + + context 'for a redis database' do + it 'updates the config' do + redis_config = DropletKit::DatabaseRedisConfig.new( + redis_maxmemory_policy: 'allkeys-lru' + ) + + json_body = DropletKit::DatabaseRedisConfigMapping.representation_for(:update, redis_config) + request = stub_do_api("/v2/databases/#{database_cluster_id}/config", :patch).with(body: json_body).to_return(status: 200) + resource.update_redis_config(redis_config, id: database_cluster_id) + + expect(request).to have_been_made + end + end + + context 'for a opensearch database' do + it 'updates the config' do + opensearch_config = DropletKit::DatabaseOpensearchConfig.new( + ism_enabled: true + ) + + json_body = DropletKit::DatabaseOpensearchConfigMapping.representation_for(:update, opensearch_config) + request = stub_do_api("/v2/databases/#{database_cluster_id}/config", :patch).with(body: json_body).to_return(status: 200) + resource.update_opensearch_config(opensearch_config, id: database_cluster_id) + + expect(request).to have_been_made + end + end + end + describe '#get_metrics_credentials' do it 'returns the metrics credentials' do request = stub_do_api('/v2/databases/metrics/credentials', :get).to_return(body: api_fixture('databases/get_metrics_credentials_response'), status: 200)