mirror of
https://github.com/neondatabase/neon.git
synced 2026-01-15 09:22:55 +00:00
Add endpoint that allows extensions to be installed
This commit is contained in:
@@ -19,6 +19,7 @@ use futures::future::join_all;
|
||||
use futures::stream::FuturesUnordered;
|
||||
use futures::StreamExt;
|
||||
use nix::unistd::Pid;
|
||||
use postgres::config::Config;
|
||||
use postgres::error::SqlState;
|
||||
use postgres::{Client, NoTls};
|
||||
use tracing::{debug, error, info, instrument, warn};
|
||||
@@ -1367,6 +1368,28 @@ LIMIT 100",
|
||||
download_size
|
||||
}
|
||||
|
||||
pub fn install_extension(&self, ext_name: &str, db_name: &str) -> Result<()> {
|
||||
let mut conf =
|
||||
Config::from_str(self.connstr.as_str()).context("Failed to parse connection string")?;
|
||||
conf.dbname(db_name);
|
||||
|
||||
let mut db_client = conf
|
||||
.connect(NoTls)
|
||||
.context("Failed to connect to the database")?;
|
||||
|
||||
let query = format!(
|
||||
"CREATE EXTENSION IF NOT EXISTS {}",
|
||||
ext_name.to_string().pg_quote()
|
||||
);
|
||||
info!("creating extension with query: {}", query);
|
||||
|
||||
db_client
|
||||
.execute(&query, &[])
|
||||
.context(format!("Failed to execute query: {}", query))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn prepare_preload_libraries(
|
||||
&self,
|
||||
|
||||
@@ -98,6 +98,32 @@ async fn routes(req: Request<Body>, compute: &Arc<ComputeNode>) -> Response<Body
|
||||
}
|
||||
}
|
||||
|
||||
(&Method::POST, "/extensions") => {
|
||||
info!("serving /extensions POST request");
|
||||
let status = compute.get_status();
|
||||
if status != ComputeStatus::Running {
|
||||
let msg = format!(
|
||||
"invalid compute status for extensions request: {:?}",
|
||||
status
|
||||
);
|
||||
error!(msg);
|
||||
return Response::new(Body::from(msg));
|
||||
}
|
||||
|
||||
let body = hyper::body::to_bytes(req.into_body()).await.unwrap();
|
||||
let body = serde_json::from_slice::<serde_json::Value>(&body).unwrap();
|
||||
let extension = body["extension"].as_str().unwrap();
|
||||
let database = body["database"].as_str().unwrap();
|
||||
let res = compute.install_extension(extension, database);
|
||||
match res {
|
||||
Ok(_) => Response::new(Body::from("true")),
|
||||
Err(e) => {
|
||||
error!("install_extension failed: {}", e);
|
||||
Response::new(Body::from(e.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(&Method::GET, "/info") => {
|
||||
let num_cpus = num_cpus::get_physical();
|
||||
info!("serving /info GET request. num_cpus: {}", num_cpus);
|
||||
|
||||
@@ -144,6 +144,41 @@ paths:
|
||||
description: Error text or 'true' if check passed.
|
||||
example: "true"
|
||||
|
||||
/extensions:
|
||||
post:
|
||||
tags:
|
||||
- Extensions
|
||||
summary: Install extension if possible.
|
||||
description: ""
|
||||
operationId: installExtension
|
||||
requestBody:
|
||||
description: Extension name and database to install it to.
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- extension
|
||||
- database
|
||||
properties:
|
||||
extension:
|
||||
type: string
|
||||
description: Extension name.
|
||||
database:
|
||||
type: string
|
||||
description: Database name.
|
||||
example: "neondb"
|
||||
responses:
|
||||
200:
|
||||
description: Result from extension installation
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
description: Error text or 'true' if extension was installed.
|
||||
example: "true"
|
||||
|
||||
/configure:
|
||||
post:
|
||||
tags:
|
||||
|
||||
Reference in New Issue
Block a user