Skip to content

Commit 35e64f2

Browse files
AJ0070DevelopmentCatsmatifali
authored
feat(pgadmin): add new module for pgAdmin (#228)
Co-authored-by: DevCats <[email protected]> Co-authored-by: Atif Ali <[email protected]>
1 parent 65edb54 commit 35e64f2

File tree

7 files changed

+225
-0
lines changed

7 files changed

+225
-0
lines changed

.icons/pgadmin.svg

Lines changed: 1 addition & 0 deletions
Loading

registry/AJ0070/.images/avatar.jpeg

63.6 KB
Loading

registry/AJ0070/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
display_name: Jash
3+
bio: Coder user and contributor.
4+
github: AJ0070
5+
avatar: ./.images/avatar.png
6+
status: community
7+
---
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
display_name: "pgAdmin"
3+
description: "A web-based interface for managing PostgreSQL databases in your Coder workspace."
4+
icon: "../../../../.icons/pgadmin.svg"
5+
maintainer_github: "AJ0070"
6+
verified: false
7+
tags: ["database", "postgres", "pgadmin", "web-ide"]
8+
---
9+
10+
# pgAdmin
11+
12+
This module adds a pgAdmin app to your Coder workspace, providing a powerful web-based interface for managing PostgreSQL databases.
13+
14+
It can be served on a Coder subdomain for easy access, or on `localhost` if you prefer to use port-forwarding.
15+
16+
```tf
17+
module "pgadmin" {
18+
count = data.coder_workspace.me.start_count
19+
source = "registry.coder.com/AJ0070/pgadmin/coder"
20+
version = "1.0.0"
21+
agent_id = coder_agent.example.id
22+
}
23+
```
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { describe } from "bun:test";
2+
import { runTerraformInit, testRequiredVariables } from "~test";
3+
4+
describe("pgadmin", async () => {
5+
await runTerraformInit(import.meta.dir);
6+
7+
testRequiredVariables(import.meta.dir, {
8+
agent_id: "foo",
9+
});
10+
});
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
terraform {
2+
required_providers {
3+
coder = {
4+
source = "coder/coder"
5+
}
6+
}
7+
}
8+
9+
variable "agent_id" {
10+
type = string
11+
description = "The agent to install pgAdmin on."
12+
}
13+
14+
variable "port" {
15+
type = number
16+
description = "The port to run pgAdmin on."
17+
default = 5050
18+
}
19+
20+
variable "subdomain" {
21+
type = bool
22+
description = "If true, the app will be served on a subdomain."
23+
default = true
24+
}
25+
26+
variable "config" {
27+
type = any
28+
description = "A map of pgAdmin configuration settings."
29+
default = {
30+
DEFAULT_EMAIL = "[email protected]"
31+
DEFAULT_PASSWORD = "coderPASSWORD"
32+
SERVER_MODE = false
33+
MASTER_PASSWORD_REQUIRED = false
34+
LISTEN_ADDRESS = "127.0.0.1"
35+
}
36+
}
37+
38+
data "coder_workspace" "me" {}
39+
data "coder_workspace_owner" "me" {}
40+
41+
resource "coder_app" "pgadmin" {
42+
count = data.coder_workspace.me.start_count
43+
agent_id = var.agent_id
44+
display_name = "pgAdmin"
45+
slug = "pgadmin"
46+
icon = "/icon/pgadmin.svg"
47+
url = local.url
48+
subdomain = var.subdomain
49+
share = "owner"
50+
51+
healthcheck {
52+
url = local.healthcheck_url
53+
interval = 5
54+
threshold = 6
55+
}
56+
}
57+
58+
resource "coder_script" "pgadmin" {
59+
agent_id = var.agent_id
60+
display_name = "Install and run pgAdmin"
61+
icon = "/icon/pgadmin.svg"
62+
run_on_start = true
63+
script = templatefile("${path.module}/run.sh", {
64+
PORT = var.port,
65+
LOG_PATH = "/tmp/pgadmin.log",
66+
SERVER_BASE_PATH = local.server_base_path,
67+
CONFIG = local.config_content,
68+
PGADMIN_DATA_DIR = local.pgadmin_data_dir,
69+
PGADMIN_LOG_DIR = local.pgadmin_log_dir,
70+
PGADMIN_VENV_DIR = local.pgadmin_venv_dir
71+
})
72+
}
73+
74+
locals {
75+
server_base_path = var.subdomain ? "" : format("/@%s/%s/apps/%s", data.coder_workspace_owner.me.name, data.coder_workspace.me.name, "pgadmin")
76+
url = "http://localhost:${var.port}${local.server_base_path}"
77+
healthcheck_url = "http://localhost:${var.port}${local.server_base_path}/"
78+
79+
# pgAdmin data directories (user-local paths)
80+
pgadmin_data_dir = "$HOME/.pgadmin"
81+
pgadmin_log_dir = "$HOME/.pgadmin/logs"
82+
pgadmin_venv_dir = "$HOME/.pgadmin/venv"
83+
84+
base_config = merge(var.config, {
85+
LISTEN_PORT = var.port
86+
# Override paths for user installation
87+
DATA_DIR = local.pgadmin_data_dir
88+
LOG_FILE = "${local.pgadmin_log_dir}/pgadmin4.log"
89+
SQLITE_PATH = "${local.pgadmin_data_dir}/pgadmin4.db"
90+
SESSION_DB_PATH = "${local.pgadmin_data_dir}/sessions"
91+
STORAGE_DIR = "${local.pgadmin_data_dir}/storage"
92+
# Disable initial setup prompts for automated deployment
93+
SETUP_AUTH = false
94+
})
95+
96+
config_with_path = var.subdomain ? local.base_config : merge(local.base_config, {
97+
APPLICATION_ROOT = local.server_base_path
98+
})
99+
100+
config_content = join("\n", [
101+
for key, value in local.config_with_path :
102+
format("%s = %s", key,
103+
can(regex("^(true|false)$", tostring(value))) ? (value ? "True" : "False") :
104+
can(tonumber(value)) ? tostring(value) :
105+
format("'%s'", tostring(value))
106+
)
107+
])
108+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
PORT=${PORT}
6+
LOG_PATH=${LOG_PATH}
7+
SERVER_BASE_PATH=${SERVER_BASE_PATH}
8+
9+
BOLD='\033[0;1m'
10+
11+
printf "$${BOLD}Installing pgAdmin!\n"
12+
13+
# Check if Python 3 is available
14+
if ! command -v python3 > /dev/null 2>&1; then
15+
echo "⚠️ Warning: Python 3 is not installed. Please install Python 3 before using this module."
16+
exit 0
17+
fi
18+
19+
# Setup pgAdmin directories (from Terraform configuration)
20+
PGADMIN_DATA_DIR="${PGADMIN_DATA_DIR}"
21+
PGADMIN_LOG_DIR="${PGADMIN_LOG_DIR}"
22+
PGADMIN_VENV_DIR="${PGADMIN_VENV_DIR}"
23+
24+
printf "Setting up pgAdmin directories...\n"
25+
mkdir -p "$PGADMIN_DATA_DIR"
26+
mkdir -p "$PGADMIN_LOG_DIR"
27+
28+
# Check if pgAdmin virtual environment already exists and is working
29+
if [ -f "$PGADMIN_VENV_DIR/bin/pgadmin4" ] && [ -f "$PGADMIN_VENV_DIR/bin/activate" ]; then
30+
printf "🥳 pgAdmin virtual environment already exists\n\n"
31+
else
32+
printf "Creating Python virtual environment for pgAdmin...\n"
33+
if ! python3 -m venv "$PGADMIN_VENV_DIR"; then
34+
echo "⚠️ Warning: Failed to create virtual environment"
35+
exit 0
36+
fi
37+
38+
printf "Installing pgAdmin 4 in virtual environment...\n"
39+
if ! "$PGADMIN_VENV_DIR/bin/pip" install pgadmin4; then
40+
echo "⚠️ Warning: Failed to install pgAdmin4"
41+
exit 0
42+
fi
43+
44+
printf "🥳 pgAdmin has been installed successfully\n\n"
45+
fi
46+
47+
printf "$${BOLD}Configuring pgAdmin...\n"
48+
49+
if [ -f "$PGADMIN_VENV_DIR/bin/pgadmin4" ]; then
50+
# pgAdmin installs to a predictable location in the virtual environment
51+
PYTHON_VERSION=$("$PGADMIN_VENV_DIR/bin/python" -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
52+
PGADMIN_INSTALL_DIR="$PGADMIN_VENV_DIR/lib/python$PYTHON_VERSION/site-packages/pgadmin4"
53+
54+
# Create pgAdmin config file in the correct location (next to config.py)
55+
cat > "$PGADMIN_INSTALL_DIR/config_local.py" << EOF
56+
# pgAdmin configuration for Coder workspace
57+
${CONFIG}
58+
EOF
59+
60+
printf "📄 Config written to $PGADMIN_INSTALL_DIR/config_local.py\n"
61+
62+
printf "$${BOLD}Starting pgAdmin in background...\n"
63+
printf "📝 Check logs at $${LOG_PATH}\n"
64+
printf "🌐 Serving at http://localhost:${PORT}${SERVER_BASE_PATH}\n"
65+
66+
# Create required directories
67+
mkdir -p "$PGADMIN_DATA_DIR/sessions"
68+
mkdir -p "$PGADMIN_DATA_DIR/storage"
69+
70+
# Start pgadmin4 from the virtual environment with proper environment
71+
cd "$PGADMIN_DATA_DIR"
72+
PYTHONPATH="$PGADMIN_INSTALL_DIR:$${PYTHONPATH:-}" "$PGADMIN_VENV_DIR/bin/pgadmin4" > "$${LOG_PATH}" 2>&1 &
73+
else
74+
printf "⚠️ Warning: pgAdmin4 virtual environment not found\n"
75+
printf "📝 Installation may have failed - check logs above\n"
76+
fi

0 commit comments

Comments
 (0)