diff --git a/nuvolaris/apihost_util.py b/nuvolaris/apihost_util.py index de829912..8c44603a 100644 --- a/nuvolaris/apihost_util.py +++ b/nuvolaris/apihost_util.py @@ -161,17 +161,6 @@ def extract_port(url): parsed_url = urllib.parse.urlparse(url) return parsed_url.port -def extract_hostname(url): - """ - Parse a url and extract the hostname part - >>> extract_hostname('http://localhost:8080') - 'localhost' - >>> extract_hostname('https://nuvolaris.org') - 'nuvolaris.org' - """ - parsed_url = urllib.parse.urlparse(url) - return parsed_url.hostname - def split_hostname_port(url): """ Parse a url and extract the port part @@ -190,9 +179,6 @@ def get_user_static_hostname(runtime, username, apihost): inside the cm/config configMap prepending the user_namespace when needed. """ - if apihost not in ["auto"]: - return apihost - apihost_url = util.get_apihost_from_config_map() if apihost_url: diff --git a/nuvolaris/kube.py b/nuvolaris/kube.py index a741b507..827f9967 100644 --- a/nuvolaris/kube.py +++ b/nuvolaris/kube.py @@ -37,7 +37,7 @@ # default output is text # if you specify jsonpath it will filter and parse the json output # returns exceptions if errors -def kubectl(*args, namespace="nuvolaris", input=None, jsonpath=None, debugresult=True): +def kubectl(*args, namespace="nuvolaris", input=None, jsonpath=None, debugresult=True, timeout=None): # support for mocked requests mres = mocker.invoke(*args) if mres: @@ -55,7 +55,7 @@ def kubectl(*args, namespace="nuvolaris", input=None, jsonpath=None, debugresult # executing logging.debug(cmd) - res = subprocess.run(cmd, capture_output=True, input=input) + res = subprocess.run(cmd, capture_output=True, input=input, timeout=timeout) global returncode, output, error returncode = res.returncode diff --git a/nuvolaris/postgres_operator.py b/nuvolaris/postgres_operator.py index 91b5c694..fb11659a 100644 --- a/nuvolaris/postgres_operator.py +++ b/nuvolaris/postgres_operator.py @@ -178,12 +178,16 @@ def render_postgres_script(namespace,template,data): file = ntp.spool_template(template, out, data) return os.path.abspath(file) -def exec_psql_command(pod_name,path_to_psql_script,path_to_pgpass): +def exec_psql_command(pod_name,path_to_psql_script,path_to_pgpass,additional_psql_args=''): logging.info(f"passing script {path_to_psql_script} to pod {pod_name}") res = kube.kubectl("cp",path_to_psql_script,f"{pod_name}:{path_to_psql_script}") res = kube.kubectl("cp",path_to_pgpass,f"{pod_name}:/tmp/.pgpass") res = kube.kubectl("exec","-it",pod_name,"--","/bin/bash","-c",f"chmod 600 /tmp/.pgpass") - res = kube.kubectl("exec","-it",pod_name,"--","/bin/bash","-c",f"PGPASSFILE='/tmp/.pgpass' psql --username postgres --dbname postgres -f {path_to_psql_script}") + + cmd = f"PGPASSFILE='/tmp/.pgpass' psql --username postgres --dbname postgres {additional_psql_args} -f {path_to_psql_script}" + logging.info(f"executing command: {cmd}") + res = kube.kubectl("exec","-it",pod_name,"--","/bin/bash","-c",cmd) + os.remove(path_to_psql_script) os.remove(path_to_pgpass) return res @@ -209,6 +213,10 @@ def create_db_user(ucfg: UserConfig, user_metadata: UserMetadata): if res: _add_pdb_user_metadata(ucfg, user_metadata) + path_to_pgpass = render_postgres_script(ucfg.get('namespace'),"dbname_pgpass_tpl.properties",data) + path_to_schema_script = render_postgres_script(ucfg.get('namespace'),"postgres_manage_user_schema_tpl.sql",data) + res = exec_psql_command_in_db(database,pod_name,path_to_schema_script,path_to_pgpass) + data["extensions"]=["vector"] path_to_pgpass = render_postgres_script(ucfg.get('namespace'),"dbname_pgpass_tpl.properties",data) path_to_extensions_script = render_postgres_script(ucfg.get('namespace'),"postgres_manage_user_extension_tpl.sql",data) @@ -232,12 +240,17 @@ def delete_db_user(namespace, database): data["database"]=database data["mode"]="delete" - path_to_pgpass = render_postgres_script(namespace,"pgpass_tpl.properties",data) - path_to_mdb_script = render_postgres_script(namespace,"postgres_manage_user_tpl.sql",data) + pod_name = util.get_pod_name_by_selector("app=nuvolaris-postgres","{.items[?(@.metadata.labels.replicationRole == 'primary')].metadata.name}") if(pod_name): - res = exec_psql_command(pod_name,path_to_mdb_script,path_to_pgpass) + path_to_pgpass = render_postgres_script(namespace,"pgpass_tpl.properties",data) + path_to_ter_script = render_postgres_script(namespace,"postgres_terminate_tpl.sql",data) + res = exec_psql_command(pod_name,path_to_ter_script,path_to_pgpass,' -q -t ') + + path_to_pgpass = render_postgres_script(namespace,"pgpass_tpl.properties",data) + path_to_mdb_script = render_postgres_script(namespace,"postgres_manage_user_tpl.sql",data) + res += exec_psql_command(pod_name,path_to_mdb_script,path_to_pgpass) return res return None diff --git a/nuvolaris/templates/postgres_manage_user_extension_tpl.sql b/nuvolaris/templates/postgres_manage_user_extension_tpl.sql index 25730a07..d465f8d5 100644 --- a/nuvolaris/templates/postgres_manage_user_extension_tpl.sql +++ b/nuvolaris/templates/postgres_manage_user_extension_tpl.sql @@ -19,7 +19,7 @@ {% if mode == 'create' %} {% for extension in extensions -%} -CREATE EXTENSION IF NOT EXISTS {{extension}}; +CREATE EXTENSION IF NOT EXISTS {{extension}} WITH SCHEMA {{username}}_schema; {% endfor %} {% endif %} diff --git a/nuvolaris/templates/postgres_manage_user_schema_tpl.sql b/nuvolaris/templates/postgres_manage_user_schema_tpl.sql new file mode 100644 index 00000000..83c2cdf9 --- /dev/null +++ b/nuvolaris/templates/postgres_manage_user_schema_tpl.sql @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +{% if mode == 'create' %} +-- Create schema only if not exists and owned by correct user +CREATE SCHEMA IF NOT EXISTS {{username}}_schema; +ALTER SCHEMA {{username}}_schema OWNER TO {{username}}; +ALTER DATABASE {{database}} SET search_path TO {{username}}_schema, pg_catalog; +{% endif %} diff --git a/nuvolaris/templates/postgres_manage_user_tpl.sql b/nuvolaris/templates/postgres_manage_user_tpl.sql index c4f49883..ab5640ed 100644 --- a/nuvolaris/templates/postgres_manage_user_tpl.sql +++ b/nuvolaris/templates/postgres_manage_user_tpl.sql @@ -25,12 +25,7 @@ REVOKE CONNECT ON DATABASE {{database}} from public; {% endif %} {% if mode == 'delete' %} -SELECT pg_terminate_backend(pg_stat_activity.pid) -FROM pg_stat_activity -WHERE pg_stat_activity.datname = '{{database}}'; - DROP DATABASE {{database}}; - DROP OWNED BY {{username}}; DROP USER {{username}}; {% endif %} \ No newline at end of file diff --git a/nuvolaris/templates/postgres_terminate_tpl.sql b/nuvolaris/templates/postgres_terminate_tpl.sql new file mode 100644 index 00000000..10247605 --- /dev/null +++ b/nuvolaris/templates/postgres_terminate_tpl.sql @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +DO $$ +BEGIN + PERFORM pg_catalog.pg_terminate_backend(pid) + FROM pg_catalog.pg_stat_activity + WHERE pg_stat_activity.datname = '{{database}}' + AND pg_stat_activity.pid <> pg_catalog.pg_backend_pid(); +END; +$$; + +