-
Notifications
You must be signed in to change notification settings - Fork 75
Backup and restore container gateway postgres DB #905
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
384b86f to
5814c0e
Compare
|
I looked into the issue where stderr makes it into the dump file. It seems that this was always the case since the final command looks like I'm guessing this wasn't an issue before because |
214ff13 to
4818b98
Compare
|
I also ended up adding lines to change the backup ownership to |
3ae9e8c to
9f3a763
Compare
0762bac to
1a0161a
Compare
wbclark
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @ianballou !
I've shared some thoughts from my initial reading of this.
Regarding the proposal for some more abstraction here now that we've added a fourth(!) DB, it looks like it could also make sense for the definitions for online DB backup procedures and DB restore procedures?
I am curious to know what you think about it, and perhaps @evgeni would have some insight as well about whether this has been discussed before, and whether it's worth doing now
| feature(:foreman_database) || feature(:candlepin_database) || | ||
| feature(:pulpcore_database) || feature(:container_gateway_database) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| feature(:foreman_database) || feature(:candlepin_database) || | |
| feature(:pulpcore_database) || feature(:container_gateway_database) | |
| %i[ | |
| foreman_database | |
| candlepin_database | |
| pulpcore_database | |
| container_gateway_database | |
| ].any? { |db| feature(db) } |
[nit] this one sparks joy
| @@ -0,0 +1,29 @@ | |||
| module Checks | |||
| module ContainerGateway | |||
| class DBUp < ForemanMaintain::Check | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[idea] It looks like we'll have nearly identical code at definitions/checks/{foreman,candlepin,pulpcore,container_gateway}/db_up.rb... what do you think about abstracting these into a common subclass of ForemanMaintain::Check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sounds like a good idea to me, the files appear to be very similar.
|
I originally thought this would be required for Katello 4.14 since I assume the change to postgres would introduce a regression in backup & restore. It looks like it does not, in fact it appears that offline backup is backing up the container gateway DB for free somehow. Once the installer is run, the container_gateway DB is correctly created. So, users restoring at least can still just do a smart proxy sync to restore their content. As such, I don't think we need to rush this for the upcoming Foreman release in case there are other concerns with the implementation that pop up. I'm personally a bit busy with getting other things in shape for the release, but please let me know if anyone thinks there's a new regression that I'm missing. |
1a0161a to
fb56093
Compare
|
@wbclark I've implemented your ideas |
It will not anymore (since we merged #893), so caution! :) |
|
Since this has slipped a little on our team priorities, I'm going to call this a PoC and get things updated once the strategy is determined to be sound. |
|
I'll preface this by saying I'm not sure if we support external DBs for proxies, but, if we do ... We did not test external container gateway external DBs. If I remember correctly, we have all of the connection information ready to be modified to an external host, so it should work to be remote. If my PR here does not respect external databases but should, I'll fix it. |
evgeni
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be simplified, see inline comments :)
| base_cmd = if config['connection_string'] | ||
| 'pg_restore' | ||
| else | ||
| base_command(config, 'pg_restore') | ||
| end | ||
| dump_cmd = base_cmd + | ||
| ' --no-privileges --clean --disable-triggers -n public ' \ | ||
| "-d #{config['database']} #{file}" | ||
| if config['user'] | ||
| execute!("chown -R #{config['user']}:#{config['user']} #{File.dirname(file)}") | ||
| end | ||
| execute!(dump_cmd, :hidden_patterns => [config['password']], | ||
| :valid_exit_statuses => [0, 1]) | ||
| :valid_exit_statuses => [0, 1], :user => config['user']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the DB is remote, we don't need to change to config[user] (=foreman-proxy), as the DB communication happens over the network and doesn't require a specific user to initiate it.
| connection_string = config[:db_connection_string] | ||
| if connection_string | ||
| uri = URI.parse(connection_string) | ||
| @configuration['connection_string'] = connection_string | ||
| @configuration['user'] = 'foreman-proxy' | ||
| @configuration['database'] = uri.path[1..] | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So looking at theforeman/puppet-foreman_proxy#835, the connection_string is something like postgres:///container_gateway (for a local setup) or postgres://configurableuser:[email protected]:5432/container_gateway (for a remote DB, supported or not).
Now, the other code in this PR depends on the user definition whether it switches to that (shell) user or not.
That switching is unnecessary for the remote-DB case!
| connection_string = config[:db_connection_string] | |
| if connection_string | |
| uri = URI.parse(connection_string) | |
| @configuration['connection_string'] = connection_string | |
| @configuration['user'] = 'foreman-proxy' | |
| @configuration['database'] = uri.path[1..] | |
| end | |
| connection_string = config[:db_connection_string] | |
| if connection_string | |
| uri = URI.parse(connection_string) | |
| @configuration['connection_string'] = connection_string | |
| @configuration['user'] = 'foreman-proxy' unless uri.host | |
| @configuration['database'] = uri.path[1..] | |
| end |
definitions/procedures/repositories/index_katello_repositories_container_metadata.rb
Outdated
Show resolved
Hide resolved
| def dump_db(file, config = configuration) | ||
| execute!(dump_command(config) + " > #{file}", :hidden_patterns => [config['password']]) | ||
| if config['user'] | ||
| execute!("chown -R #{config['user']}:#{config['user']} #{File.dirname(file)}") | ||
| end | ||
| execute!(dump_command(config) + " -f #{file}", | ||
| :hidden_patterns => [config['password']], :user => config['user']) | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now, this relies on the DB credentials we parse from the config and in the super special case of gateway, the shell user of the proxy.
For restores, we have this "if local, use postgres user, else the parsed config as root", if we use the same logic for dumping, we reduce the special-casing for gateway (as we either use postgres, which has access to all databases anyway, or a remote connection that doesn't require foreman-proxy user).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I wrote this I didn't think I could use the postgres user for some reason. Using postgres would make the code here a whole lot simpler 👍
0c1dfc0 to
cc3b128
Compare
4158dc1 to
58141a0
Compare
876b819 to
1954032
Compare
|
@evgeni I've rebased this and changed the PR to use the I need to get the tests passing again. I've tested this on a container gateway enabled smart proxy with online backup & restore. |
e5f68d3 to
6375b67
Compare
|
The latest code ensures all local DB connections use unix sockets with a simple connection string (like Edit: the satellite system test worked. |
3ee90d9 to
26050cf
Compare
adamruzicka
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't tested, but looks reasonable at a glance
| if connection_string | ||
| uri = URI.parse(connection_string) | ||
| @configuration['connection_string'] = connection_string | ||
| @configuration['database'] = uri.path[1..] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The path[1..] is there "just" to strip the leading forward slash?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, lemme change it to delete_prefix('/') to make it more clear.
| execute!(dump_command, :env => base_env) | ||
| if local? | ||
| dump_command = "pg_dump --format=c #{configuration['connection_string']}" | ||
| execute!("chown -R postgres:postgres #{File.dirname(file)}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why wasn't this needed previously?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously we ran this as root, but since now I'm using the postgres user, we need to ensure the dump directory is reachable by postgres. Alternatively we could just throw an error saying to ensure the directory is reachable by the postgres user if making the change for the user is overstepping.
| execute?( | ||
| "runuser - postgres -c 'psql -d #{configuration['database']} -c \"SELECT 1 as ping\"'" | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the query be passed on stdin same as on L76-78?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it could, let me try.
7600871 to
4da99fe
Compare
|
@adamruzicka I think I've addressed your comments. |
Allow executing commands as a different user Use --file and --format with pg_dump Refactor DBUps into subclasses Fix rubocop errors Use postgres user for container gateway backup/restore Remove user config for container gateway backup
9438828 to
3347a9e
Compare
Adds backup and restore support for the container gateway DB. Only adds support for the postgres version of the database for now.
One notable change was that the DB commands need to be run as
foreman-proxysince no password is saved for the database. The container gateway uses unix socket auth for the connection, so only the owning user can access the DB (as far as I know).As such, I've added support for running generic commands as a different user.
To test, try backup and restore on both a normal Foreman/Katello install and on a smart proxy with the container gateway installed.
ToDos: