# # # bundle agent mysql(cfg_param) { vars: "default_cfg" data => '{ "bind_address":"127.0.0.1", "user":"mysql", "port":"3306", "backup_dir":"/var/backups", "mariadb":true }'; "cfg" data => mergedata(@(default_cfg),@(cfg_param)); freebsd:: "user" string => "mysql"; "server_pkgs" slist => {"mysql80-server"}; "client_pkgs" slist => {"mysql80-client"}; "type" string => "mysql8"; "server_pkgs" slist => {"mariadb106-server"}, if => strcmp("$(cfg[mariadb])","true"); "client_pkgs" slist => {"mariadb106-client"}, if => strcmp("$(cfg[mariadb])","true"); "type" string => "mariadb",if => strcmp("$(cfg[mariadb])","true"); "service_name" string => "mysql-server"; "cfg_dir" string => "/usr/local/etc/mysql"; "cfg_file" string => "/usr/local/etc/mysql/my.cnf"; "bin_dir" string => "/usr/local/bin"; "default_datadir" string => "/var/db/mysql"; "mysqld_cmd" string => "/usr/local/libexec/mysqld"; debian:: "user" string => "mysql"; "server_pkgs" slist => {"mariadb-server"}; "client_pkgs" slist => {"mariadb-client"}; "type" string => "mariadb"; "service_name" string => "mysql"; "cfg_dir" string => "/etc/mysql"; "cfg_file" string => "/etc/mysql/my.cnf"; "bin_dir" string => "/usr/bin"; "default_datadir" string => "/var/lib/mysql"; "mysqld_cmd" string => "/usr/sbin/mysqld"; fedora|centos:: "user" string => "mysql"; "server_pkgs" slist => {"mariadb-server"}; "client_pkgs" slist => {"mariadb-client"}; "server_pkgs" slist => {"MariaDB-server"}; "client_pkgs" slist => {"MariaDB-client"}; "type" string => "mariadb"; "service_name" string => "mariadb"; "cfg_dir" string => "/etc/mysql"; "cfg_file" string => "/etc/my.cnf"; "bin_dir" string => "/usr/bin"; "default_datadir" string => "/var/lib/mysql"; "mysqld_cmd" string => "/usr/sbin/mysqld"; any:: "mysql_cmd" string => "$(bin_dir)/mysql"; "mysqldump_cmd" string => "$(bin_dir)/mysqldump"; files: freebsd:: "/etc/rc.conf.d/mysql" create => "true", content => "mysql_enable=YES"; any:: "$(cfg_dir)/." create => "true", perms => m("0755"), handle => "mysql_cfg_dir_created"; "$(cfg_file)" #create => "true", perms => m("644"), copy_from => seed_cp("$(sys.workdir)/inputs/$(def.wmde_libdir)/templates/my.cnf.mustache"), # edit_template => "$(sys.workdir)/inputs/$(def.wmde_libdir)/templates/my.cnf.mustache", # template_method => "mustache", handle => "mysql_cfg_created", depends_on => {"mysql_cfg_dir_created"}, classes => if_repaired("mysql_repaired"); services: "$(service_name)" depends_on => {"mysql_pkgs_installed"}, service_policy => "start", handle => "mysql_running"; mysql_repaired:: "$(service_name)" service_policy => "restart", depends_on => {"mysql_running","mysql_cfg_created"}; reports: } bundle agent install_mysql_server(cfg) { classes: "type_$(mysql.type)" ; vars: "mysqld_idx" slist => getindices(@(cfg[settings][mysqld])); "settings[mysqld][$(mysqld_idx)]" string => "$(cfg[settings][mysqld][$(mysqld_idx)])"; "datadir" string => ifelse(isvariable("cfg[settings][mysqld][datadir]"), "$(cfg[settings][mysqld][datadir])", "$(mysql.default_datadir)"); type_mariadb:: "install_db_exe" string => ifelse(fileexists("$(mysql.bin_dir)/mysql_install_db"), "$(mysql.bin_dir)/mysql_install_db", "$(mysql.bin_dir)/mariadb-install-db"); "install_db_cmd" string => "if [ ! -d $(datadir)/mysql ]; then $(install_db_exe) --user=$(mysql.user)>/dev/null ; fi"; type_mysql8:: "install_db_cmd" string => "if [ ! -d $(datadir)/mysql ]; then $(mysql.mysqld_cmd) --initialize-insecure --user=$(mysql.user); fi"; "j" string => storejson(@(cfg)); methods: "any" usebundle => mysql(@(cfg)); "any" usebundle => wmde_install_packages(@(mysql.server_pkgs),"mysql_server"); files: "$(mysql.cfg_file)" copy_from => seed_cp("$(sys.workdir)/inputs/$(def.wmde_libdir)/templates/my.cnf.mustache"), handle => "myslq_server_cfg_created", depends_on => {"mysql_server_pkgs_installed"}; "$(mysql.cfg_file)" create => "true", perms => m("644"), edit_line => set_variable_values_inix("$(this.bundle).settings","mysqld"), depends_on => {"myslq_server_cfg_created"}, handle => "myslq_server_cfg_edited", classes => if_repaired("mysql_server_repaired"); commands: "$(install_db_cmd)" handle=>"mysql_datadir_initialized", contain => wmde_cmd_useshell, inform => "false", depends_on => {"myslq_server_cfg_edited"}; methods: "any" usebundle => wmde_service("$(mysql.service_name)","mysql_server_kept","mysql_server_repaired"), depends_on => {"mysql_datadir_initialized"}; reports: } bundle edit_line set_variable_values_inix(tab, sectionName) { vars: "index" slist => getindices("$(tab)[$(sectionName)]"); # Be careful if the index string contains funny chars "cindex[$(index)]" string => canonify("$(index)"); classes: "edit_$(cindex[$(index)])" not => strcmp("$($(tab)[$(sectionName)][$(index)])","dontchange"), comment => "Create conditions to make changes"; field_edits: # If the line is there, but commented out, first uncomment it # "#+\s*$(index)\s*=.*" # select_region => INI_section(escape("$(sectionName)")), # edit_field => col("\s*=\s*","1","$(index)","set"), # if => "edit_$(cindex[$(index)])"; # match a line starting like the key something "\s*$(index)\s*=.*" edit_field => col("\s*=\s*","2","$($(tab)[$(sectionName)][$(index)])","set"), select_region => INI_section(escape("$(sectionName)")), classes => results("bundle", "set_variable_values_ini_not_$(cindex[$(index)])"), if => "edit_$(cindex[$(index)])"; delete_lines: "!include.*"; insert_lines: "[$(sectionName)]" location => start, comment => "Insert lines"; "$(index)=$($(tab)[$(sectionName)][$(index)])" select_region => INI_section(escape("$(sectionName)")), if => "!(set_variable_values_ini_not_$(cindex[$(index)])_kept|set_variable_values_ini_not_$(cindex[$(index)])_repaired).edit_$(cindex[$(index)])"; } bundle agent install_mysql_client { methods: "any" usebundle => wmde_install_packages(@(mysql.client_pkgs),"mysql_client"), handle => "mysql_client_installed"; } body contain mysql_cmd { useshell=>"useshell"; } bundle agent mysql_table_exists(dbdef,table_name) { vars: "pass_arg" string => ifelse ( isvariable("dbdef[db_pass]"), "-p$(dbdef[db_pass])","" ); "host_arg" string => ifelse ( isvariable("dbdef[db_host]"), "-h$(dbdef[db_host])","" ); "user_arg" string => ifelse ( isvariable("dbdef[db_user]"), "-u$(dbdef[db_user])","" ); "xargs" string => "$(pass_arg) $(host_arg) $(user_arg)"; "classname" string => "mysql_$(dbdef[db_name])_$(table_name)_exists"; "cmd" string => 'if mysql $(xargs) -e "show tables LIKE \'$(table_name)\'" $(dbdef[db_name]) | grep -q \'$(table_name)\'; then echo "+$(classname)"; else echo "-$(classname)"; fi'; commands: "$(cmd)" contain => mysql_cmd, inform => "false", module => "true"; reports: } bundle agent mysql_backup_all(cfg) { vars: "cmd" string => '$(mysql.mysql_cmd) -N -e \'show databases\' | while read dbname; do $(mysql.mysqldump_cmd) --default-character-set=utf8mb4 --complete-insert --routines --triggers --single-transaction --max_allowed_packet=512M "$dbname" > $(cfg[backup_dir])/"$dbname".sql; done'; reports: # "CMD: $(cmd)"; } bundle agent mysql_backup_db(cfg,file) { classes: "type_$(mysql.type)" ; vars: "table_exists_cmd" string => '$(mysql.mysql_cmd) -e "show tables LIKE \'$(table_name)\'" $(cdfg[db_name]) | grep -q $(table_name)'; "cmd" string => "$(mysql.mysqldump_cmd) --default-character-set=utf8mb4 --no-tablespaces --complete-insert --routines --triggers --single-transaction --max_allowed_packet=512M -h$(cfg[db_host]) -u$(cfg[db_user]) -p$(cfg[db_pass]) $(cfg[db_name]) >$(file)"; } # # Create cronjob # @param cfg definition for database, db_user, db_host, db_pass, db_name # @param file file to dump database into # @table_name a table in the database which has to exist, if not no dump will be done # @run "true" or "false", means create cron job or not # bundle agent create_mysql_backup_cron_job(cfg,file,table_name,run) { classes: "type_$(mysql.type)" ; "create_cron" expression => strcmp("$(run)","true"); vars: "table_exists_cmd" string => '$(mysql.mysql_cmd) -h$(cfg[db_host]) -u$(cfg[db_user]) -p$(cfg[db_pass]) $(cfg[db_name]) -e "show tables LIKE \'$(table_name)\'" | grep -q $(table_name)'; type_mariadb:: "backup_cmd" string => "$(mysql.mysqldump_cmd) --default-character-set=utf8mb4 --complete-insert --routines --triggers --single-transaction --max_allowed_packet=512M -h$(cfg[db_host]) -u$(cfg[db_user]) -p$(cfg[db_pass]) $(cfg[db_name]) >$(file)"; type_mysql8:: "backup_cmd" string => "$(mysql.mysqldump_cmd) --set-gtid-purged=OFF --no-tablespaces --complete-insert --routines --triggers --single-transaction --max_allowed_packet=512M -h$(cfg[db_host]) -u$(cfg[db_user]) -p$(cfg[db_pass]) $(cfg[db_name]) >$(file)"; files: !create_cron:: "/etc/cron.d/dump-mysql-db-$(cfg[db_name])" delete=>tidy; create_cron:: "/etc/cron.d/dump-mysql-db-$(cfg[db_name])" perms => m("644"), create => "true", content => " # # /etc/cron.d/roundcube # SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 0 * * * * root $(table_exists_cmd) && $(backup_cmd) "; } # # Create cronjob # @param cfg definition for database, db_user, db_host, db_pass, db_name # @param file file to dump database into # @run "true" or "false", means create cron job or not # bundle agent create_mysqldump_cron(cfg,file,run) { classes: "type_$(mysql.type)" ; "create_cron" expression => strcmp("$(run)","true"); vars: "cron" string => ifelse(isvariable("cfg[db_cron]"), "$(cfg[db_cron])","0 1 * * * "); "table_exists_cmd" string => '$(mysql.mysql_cmd) -h$(cfg[db_host]) -u$(cfg[db_user]) -p$(cfg[db_pass]) $(cfg[db_name]) -e "show tables LIKE \'$(cfg[db_check_table])\'" | grep -q $(cfg[db_check_table])'; type_mariadb:: "backup_cmd" string => "$(mysql.mysqldump_cmd) --default-character-set=utf8mb4 --complete-insert --routines --triggers --single-transaction --max_allowed_packet=512M -h$(cfg[db_host]) -u$(cfg[db_user]) -p$(cfg[db_pass]) $(cfg[db_name]) >$(file)"; type_mysql8:: "backup_cmd" string => "$(mysql.mysqldump_cmd) --set-gtid-purged=OFF --no-tablespaces --complete-insert --routines --triggers --single-transaction --max_allowed_packet=512M -h$(cfg[db_host]) -u$(cfg[db_user]) -p$(cfg[db_pass]) $(cfg[db_name]) >$(file)"; files: !create_cron:: "/etc/cron.d/mysqldump-$(cfg[db_name])" delete=>tidy; create_cron:: "/etc/cron.d/mysqldump-$(cfg[db_name])" perms => m("644"), create => "true", content => " # # /etc/cron.d/mysqldump-$(cfg[db_name]) # SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin $(cron) root $(table_exists_cmd) && $(backup_cmd) "; } bundle agent create_mysql_db(cfg) { classes: "type_$(mysql.type)" ; # "do_restore" expression => isvariable("cfg[restore]"); "do_restore" expression => strcmp("$(cfg[db_restore])","true"); "do_backup" expression => strcmp("$(cfg[db_backup])","true"); vars: "db_name" string => "$(cfg[db_name])"; "db_user" string => "$(cfg[db_user])"; "host" string => "$(cfg[db_user_host])"; "db_pass" string => "$(cfg[db_pass])"; "args" string => "pnunf"; type_mariadb:: "args" string => "-e \"CREATE DATABASE IF NOT EXISTS $(db_name); GRANT ALL PRIVILEGES ON $(db_name).* TO '$(db_user)'@'$(host)' IDENTIFIED BY '$(db_pass)'; \" "; type_mysql8:: "args" string => "-e \"CREATE DATABASE IF NOT EXISTS $(db_name); CREATE USER IF NOT EXISTS '$(db_user)'@'$(host)'; ALTER USER '$(db_user)'@'$(host)' IDENTIFIED BY '$(db_pass)'; GRANT RELOAD ON *.* to '$(db_user)'@'$(host)'; GRANT ALL PRIVILEGES ON $(db_name).* TO '$(db_user)'@'$(host)';\" "; methods: do_restore:: "any" usebundle => restore_mysql_db_conditional(@(cfg),"$(mysql.cfg[backup_dir])/$(cfg[db_name])-dmp.sql"), depends_on => {"mysql_$(cfg[db_name])_created"}; do_backup:: "any" usebundle => create_mysqldump_cron(@(cfg),"$(mysql.cfg[backup_dir])/$(cfg[db_name])-dmp.sql","true"); !do_backup:: "any" usebundle => create_mysqldump_cron(@(cfg),"$(mysql.cfg[backup_dir])/$(cfg[db_name])-dmp.sql","false"); commands: "$(mysql.mysql_cmd)" args => "$(args)", handle => "mysql_$(cfg[db_name])_created", inform => "false"; reports: } bundle agent restore_mysql_db(cfg,file) { commands: "$(mysql.mysql_cmd)" args => "-h$(cfg[db_host]) -u$(cfg[db_user]) -p$(cfg[db_pass]) $(cfg[db_name]) < $(file)", contain => wmde_cmd_useshell; } bundle agent restore_mysql_db_conditional(cfg,file) { classes: "backup_exists" expression => fileexists("$(file)"); vars: "table_exists" string => "mysql_$(cfg[db_name])_$(cfg[db_check_table])_exists"; methods: "any" usebundle => mysql_table_exists(@(cfg),"$(cfg[db_check_table])"), handle=>"$(table_exists)_checked"; "!$(table_exists)&backup_exists":: "any" usebundle => restore_mysql_db(@(cfg),"$(file)"), depends_on=>{"$(table_exists)_checked"}; reports: }