Skip to content

Commit a805f75

Browse files
committed
chore: update CHANGELOG for version 0.3.1
- Added security improvements, including SQL injection protection. - Enhanced error handling and fixed various bugs. - Removed dead code to streamline the codebase.
1 parent 2f18e48 commit a805f75

7 files changed

Lines changed: 55 additions & 30 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

7+
## [0.3.1] - 2026-02-14
8+
9+
### Changed
10+
- security improvements, SQL injection protection
11+
- improved error handling
12+
- bug fixes
13+
- dead code removal
14+
715
## [0.3.0] - 2026-02-14
816

917
### Added

internal/env/detect.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,17 @@ func NewJavaDetector() *JavaDetector {
4343
return &JavaDetector{}
4444
}
4545

46-
// FindJavaHome returns the hardcoded Java 17 path from Homebrew installation
47-
// Java 17 is automatically downloaded via brew during installation
46+
// FindJavaHome returns the Java 17 path from Homebrew installation.
47+
// Checks both ARM (/opt/homebrew) and Intel (/usr/local) Homebrew prefixes.
4848
func (j *JavaDetector) FindJavaHome() string {
49-
const java17Home = "/opt/homebrew/opt/openjdk@17"
50-
if _, err := os.Stat(java17Home); err == nil {
51-
return java17Home
49+
candidates := []string{
50+
"/opt/homebrew/opt/openjdk@17", // ARM Mac
51+
"/usr/local/opt/openjdk@17", // Intel Mac
52+
}
53+
for _, path := range candidates {
54+
if _, err := os.Stat(path); err == nil {
55+
return path
56+
}
5257
}
5358
return ""
5459
}

internal/service/hdfs/discovery.go

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -139,21 +139,6 @@ func IsProcessRunning(pid int) bool {
139139
return err == nil
140140
}
141141

142-
// GetProcessInfo returns information about a process
143-
func GetProcessInfo(pid int) string {
144-
if pid == 0 {
145-
return ""
146-
}
147-
148-
cmd := exec.Command("ps", "-p", strconv.Itoa(pid), "-o", "command=")
149-
output, err := cmd.Output()
150-
if err != nil {
151-
return ""
152-
}
153-
154-
return strings.TrimSpace(string(output))
155-
}
156-
157142
// WaitForSafeMode waits for HDFS to exit safe mode
158143
// Returns error if timeout is reached
159144
func WaitForSafeMode(maxRetries int) error {

internal/service/hdfs/hdfs.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ func (h *HDFSService) startNameNode() error {
129129
// Update PID file
130130
hdfsPaths := h.paths.HDFSPaths()
131131
pidFile := filepath.Join(hdfsPaths.PidsDir, "namenode.pid")
132-
os.WriteFile(pidFile, []byte(fmt.Sprintf("%d", pid)), 0644)
132+
if err := os.WriteFile(pidFile, []byte(fmt.Sprintf("%d", pid)), 0644); err != nil {
133+
util.Warn("Failed to update NameNode PID file: %v", err)
134+
}
133135
util.Log("HDFS NameNode already running (pid %d).", pid)
134136
return nil
135137
}
@@ -171,7 +173,9 @@ func (h *HDFSService) startDataNode() error {
171173
// Update PID file
172174
hdfsPaths := h.paths.HDFSPaths()
173175
pidFile := filepath.Join(hdfsPaths.PidsDir, "datanode.pid")
174-
os.WriteFile(pidFile, []byte(fmt.Sprintf("%d", pid)), 0644)
176+
if err := os.WriteFile(pidFile, []byte(fmt.Sprintf("%d", pid)), 0644); err != nil {
177+
util.Warn("Failed to update DataNode PID file: %v", err)
178+
}
175179
util.Log("HDFS DataNode already running (pid %d).", pid)
176180
return nil
177181
}

internal/service/hive/metastore_bootstrap.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ func (h *HiveService) databaseExists(dbType metastore.DBType, dbURL string) (boo
138138
if err != nil {
139139
return false, err
140140
}
141+
if !dbIdentPattern.MatchString(dbName) {
142+
return false, fmt.Errorf("unsupported postgres database name %q", dbName)
143+
}
141144
sql := fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname='%s';", escapeSQLLiteral(dbName))
142145
cmd := exec.Command("psql", adminURL, "-tAc", sql)
143146
cmd.Env = h.env.Export()
@@ -151,11 +154,14 @@ func (h *HiveService) databaseExists(dbType metastore.DBType, dbURL string) (boo
151154
if err != nil {
152155
return false, err
153156
}
157+
if !dbIdentPattern.MatchString(info.dbName) {
158+
return false, fmt.Errorf("unsupported mysql database name %q", info.dbName)
159+
}
154160
args := mysqlBaseArgs(info)
155161
query := fmt.Sprintf("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='%s';", escapeSQLLiteral(info.dbName))
156162
args = append(args, "-e", query)
157163
cmd := exec.Command("mysql", args...)
158-
cmd.Env = h.env.Export()
164+
cmd.Env = mysqlCmdEnv(h.env.Export(), info)
159165
out, err := cmd.CombinedOutput()
160166
if err != nil {
161167
return false, fmt.Errorf("mysql database existence check failed: %v\nOutput: %s", err, strings.TrimSpace(string(out)))
@@ -195,7 +201,7 @@ func (h *HiveService) createDatabase(dbType metastore.DBType, dbURL string) erro
195201
args := mysqlBaseArgs(info)
196202
args = append(args, "-e", fmt.Sprintf("CREATE DATABASE `%s`;", info.dbName))
197203
cmd := exec.Command("mysql", args...)
198-
cmd.Env = h.env.Export()
204+
cmd.Env = mysqlCmdEnv(h.env.Export(), info)
199205
out, err := cmd.CombinedOutput()
200206
if err != nil {
201207
return fmt.Errorf("failed to create mysql database %q: %v\nOutput: %s", info.dbName, err, strings.TrimSpace(string(out)))
@@ -261,10 +267,18 @@ func mysqlBaseArgs(info *mysqlConnInfo) []string {
261267
if info.user != "" {
262268
args = append(args, "--user", info.user)
263269
}
270+
// Password is passed via MYSQL_PWD env var in mysqlCmdEnv() to avoid
271+
// exposing it in process listings (ps aux).
272+
return args
273+
}
274+
275+
// mysqlCmdEnv returns environment variables for MySQL commands,
276+
// including MYSQL_PWD if a password is set.
277+
func mysqlCmdEnv(baseEnv []string, info *mysqlConnInfo) []string {
264278
if info.password != "" {
265-
args = append(args, fmt.Sprintf("--password=%s", info.password))
279+
return append(baseEnv, "MYSQL_PWD="+info.password)
266280
}
267-
return args
281+
return baseEnv
268282
}
269283

270284
func escapeSQLLiteral(s string) string {

internal/service/hive/mysql.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"path/filepath"
77
"sort"
88
"strings"
9+
10+
"github.com/danieljhkim/local-data-platform/internal/util"
911
)
1012

1113
const DefaultMySQLJDBCVersion = "8.4.0"
@@ -60,7 +62,9 @@ func EnsureMySQLJDBCDriver(hiveHome, sparkHome, baseDir string) (string, error)
6062

6163
if sparkJarsDir != "" {
6264
if _, err := findMySQLJar(sparkJarsDir); err != nil {
63-
_ = ensureJarInSparkDir(foundJar, sparkJarsDir)
65+
if copyErr := ensureJarInSparkDir(foundJar, sparkJarsDir); copyErr != nil {
66+
util.Warn("Could not copy MySQL JDBC driver to %s: %v", sparkJarsDir, copyErr)
67+
}
6468
}
6569
}
6670

internal/service/yarn/yarn.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"path/filepath"
88
"strconv"
99
"strings"
10+
"syscall"
1011
"time"
1112

1213
"github.com/danieljhkim/local-data-platform/internal/config"
@@ -81,7 +82,9 @@ func (y *YARNService) startResourceManager() error {
8182
pid = findWithJPS("ResourceManager")
8283
if pid > 0 && isProcessRunning(pid) {
8384
pidFile := filepath.Join(y.procMgr.PidDir, name+".pid")
84-
os.WriteFile(pidFile, []byte(strconv.Itoa(pid)), 0644)
85+
if err := os.WriteFile(pidFile, []byte(strconv.Itoa(pid)), 0644); err != nil {
86+
util.Warn("Failed to update ResourceManager PID file: %v", err)
87+
}
8588
util.Log("YARN ResourceManager already running (pid %d).", pid)
8689
return nil
8790
}
@@ -115,7 +118,9 @@ func (y *YARNService) startNodeManager() error {
115118
pid = findWithJPS("NodeManager")
116119
if pid > 0 && isProcessRunning(pid) {
117120
pidFile := filepath.Join(y.procMgr.PidDir, name+".pid")
118-
os.WriteFile(pidFile, []byte(strconv.Itoa(pid)), 0644)
121+
if err := os.WriteFile(pidFile, []byte(strconv.Itoa(pid)), 0644); err != nil {
122+
util.Warn("Failed to update NodeManager PID file: %v", err)
123+
}
119124
util.Log("YARN NodeManager already running (pid %d).", pid)
120125
return nil
121126
}
@@ -271,7 +276,7 @@ func isProcessRunning(pid int) bool {
271276
return false
272277
}
273278

274-
err = process.Signal(os.Signal(nil))
279+
err = process.Signal(syscall.Signal(0))
275280
return err == nil
276281
}
277282

0 commit comments

Comments
 (0)