Skip to content

Commit 6801ff4

Browse files
committed
directory path based on environment variables for dood
1 parent 29b60d2 commit 6801ff4

File tree

3 files changed

+67
-69
lines changed

3 files changed

+67
-69
lines changed

internal/api/helpers.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,3 +565,34 @@ func extractTarGz(archiveReader io.Reader, targetDir string, uid, gid int) error
565565
}
566566
return nil
567567
}
568+
569+
// getLabDirectoryInfo returns the appropriate directory path for a lab based on environment variables,
570+
// along with the user's UID/GID for ownership operations.
571+
// If CLAB_SHARED_LABS_DIR is set, it returns $CLAB_SHARED_LABS_DIR/users/$username/$labName
572+
// Otherwise, it returns $HOME/.clab/$labName
573+
func getLabDirectoryInfo(username, labName string) (targetDir string, uid, gid int, err error) {
574+
// Get user details first (needed for UID/GID regardless of path)
575+
usr, err := user.Lookup(username)
576+
if err != nil {
577+
return "", -1, -1, fmt.Errorf("could not determine user details: %w", err)
578+
}
579+
580+
uid, uidErr := strconv.Atoi(usr.Uid)
581+
if uidErr != nil {
582+
return "", -1, -1, fmt.Errorf("could not process user UID: %w", uidErr)
583+
}
584+
585+
gid, gidErr := strconv.Atoi(usr.Gid)
586+
if gidErr != nil {
587+
return "", -1, -1, fmt.Errorf("could not process user GID: %w", gidErr)
588+
}
589+
590+
// Determine the target directory
591+
sharedDir := os.Getenv("CLAB_SHARED_LABS_DIR")
592+
if sharedDir != "" {
593+
return filepath.Join(sharedDir, "users", username, labName), uid, gid, nil
594+
}
595+
596+
// Fall back to user's home directory
597+
return filepath.Join(usr.HomeDir, ".clab", labName), uid, gid, nil
598+
}

internal/api/lab_handlers.go

Lines changed: 29 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -201,31 +201,15 @@ func DeployLabHandler(c *gin.Context) {
201201

202202
// --- Handle Topology Content Saving (if applicable) ---
203203
if hasContent {
204-
// --- Get User Home Directory, UID/GID ---
205-
usr, err := user.Lookup(username)
204+
// --- Get Lab Directory and User UID/GID ---
205+
targetDir, uid, gid, err := getLabDirectoryInfo(username, originalLabName)
206206
if err != nil {
207-
log.Errorf("DeployLab failed for user '%s': Could not determine user details: %v", username, err)
208-
c.JSON(http.StatusInternalServerError, models.ErrorResponse{Error: "Could not determine user details."})
209-
return
210-
}
211-
homeDir := usr.HomeDir
212-
uid, err := strconv.Atoi(usr.Uid)
213-
if err != nil {
214-
log.Errorf("DeployLab failed for user '%s': Could not process user UID: %v", username, err)
215-
c.JSON(http.StatusInternalServerError, models.ErrorResponse{Error: "Could not process user UID."})
216-
return
217-
}
218-
gid, err := strconv.Atoi(usr.Gid)
219-
if err != nil {
220-
log.Errorf("DeployLab failed for user '%s': Could not process user GID: %v", username, err)
221-
c.JSON(http.StatusInternalServerError, models.ErrorResponse{Error: "Could not process user GID."})
207+
log.Errorf("DeployLab failed for user '%s': %v", username, err)
208+
c.JSON(http.StatusInternalServerError, models.ErrorResponse{Error: err.Error()})
222209
return
223210
}
224211

225-
// --- Construct Paths, Create Dirs, Set Ownership, Write File ---
226-
// Use originalLabName for directory structure to match clab's behavior
227-
clabUserDir := filepath.Join(homeDir, ".clab")
228-
targetDir := filepath.Join(clabUserDir, originalLabName)
212+
// --- Create Directory, Set Ownership, Write File ---
229213
targetFilePath := filepath.Join(targetDir, originalLabName+".clab.yml")
230214
topoPathForClab = targetFilePath // Update path for clab command
231215

@@ -347,22 +331,6 @@ func DeployLabArchiveHandler(c *gin.Context) {
347331
username := c.GetString("username")
348332
ctx := c.Request.Context()
349333

350-
// --- Get User Details (uid, gid, homeDir) ---
351-
usr, err := user.Lookup(username)
352-
if err != nil {
353-
log.Errorf("DeployLab (Archive) failed for user '%s': Could not determine user details: %v", username, err)
354-
c.JSON(http.StatusInternalServerError, models.ErrorResponse{Error: "Could not determine user details."})
355-
return
356-
}
357-
uid, uidErr := strconv.Atoi(usr.Uid)
358-
gid, gidErr := strconv.Atoi(usr.Gid)
359-
if uidErr != nil || gidErr != nil {
360-
log.Errorf("DeployLab (Archive) failed for user '%s': Could not process user UID/GID: %v / %v", username, uidErr, gidErr)
361-
c.JSON(http.StatusInternalServerError, models.ErrorResponse{Error: "Could not process user UID/GID."})
362-
return
363-
}
364-
homeDir := usr.HomeDir
365-
366334
// --- Get Lab Name (Required Query Parameter) ---
367335
labName := c.Query("labName")
368336
if labName == "" {
@@ -411,7 +379,13 @@ func DeployLabArchiveHandler(c *gin.Context) {
411379
return
412380
}
413381

414-
targetDir := filepath.Join(homeDir, ".clab", labName)
382+
// --- Get Lab Directory and User UID/GID ---
383+
targetDir, uid, gid, err := getLabDirectoryInfo(username, labName)
384+
if err != nil {
385+
log.Errorf("DeployLab (Archive) failed for user '%s': %v", username, err)
386+
c.JSON(http.StatusInternalServerError, models.ErrorResponse{Error: err.Error()})
387+
return
388+
}
415389

416390
if exists {
417391
if !reconfigure {
@@ -688,14 +662,25 @@ func DestroyLabHandler(c *gin.Context) {
688662
// We need to derive the *directory* from the path.
689663
if originalTopoPath != "" && !strings.HasPrefix(originalTopoPath, "http") && !strings.Contains(originalTopoPath, "://") { // Basic check it's a local path
690664
targetDir := filepath.Dir(originalTopoPath)
691-
// Sanity check: ensure the directory is within the expected ~/.clab structure
692-
usr, lookupErr := user.Lookup(username)
665+
666+
// Sanity check the directory
667+
// If CLAB_SHARED_LABS_DIR is set, ensure it's within that structure
668+
// Otherwise, ensure it's within the user's ~/.clab structure
669+
sharedDir := os.Getenv("CLAB_SHARED_LABS_DIR")
693670
expectedBase := ""
694-
if lookupErr == nil {
695-
expectedBase = filepath.Join(usr.HomeDir, ".clab")
671+
672+
if sharedDir != "" {
673+
// Using shared directory
674+
expectedBase = filepath.Join(sharedDir, "users", username)
675+
} else {
676+
// Using user's home directory
677+
usr, lookupErr := user.Lookup(username)
678+
if lookupErr == nil {
679+
expectedBase = filepath.Join(usr.HomeDir, ".clab")
680+
}
696681
}
697682

698-
if expectedBase != "" && strings.HasPrefix(targetDir, expectedBase) && targetDir != expectedBase { // Prevent deleting ~/.clab itself
683+
if expectedBase != "" && strings.HasPrefix(targetDir, expectedBase) && targetDir != expectedBase {
699684
log.Infof("DestroyLab user '%s': Cleanup requested. Removing directory: %s", username, targetDir)
700685
cleanupErr := os.RemoveAll(targetDir)
701686
if cleanupErr != nil {
@@ -705,7 +690,7 @@ func DestroyLabHandler(c *gin.Context) {
705690
log.Infof("Successfully cleaned up topology directory '%s' for user '%s'", targetDir, username)
706691
}
707692
} else {
708-
log.Warnf("DestroyLab user '%s': Cleanup requested but skipping directory removal for path '%s'. Reason: Path is not within expected ~/.clab structure or original path unknown/remote.", username, targetDir)
693+
log.Warnf("DestroyLab user '%s': Cleanup requested but skipping directory removal for path '%s'. Reason: Path is not within expected structure or original path unknown/remote.", username, targetDir)
709694
}
710695
} else {
711696
log.Infof("DestroyLab user '%s': Cleanup requested but skipping directory removal. Reason: Lab likely deployed from URL or original path unknown.", username)

internal/api/topology_handlers.go

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"fmt"
77
"net/http"
88
"os"
9-
"os/user"
109
"path/filepath"
1110
"strconv"
1211
"strings"
@@ -148,42 +147,25 @@ func GenerateTopologyHandler(c *gin.Context) {
148147
// --- Determine Output/Action and Target File Path ---
149148
var targetFilePath string // Path used by clab generate --file and clab deploy -t
150149
var err error
151-
var usr *user.User
152150
var uid, gid int
153151

154152
if req.Deploy {
155-
// --- Deploy=true: Save to user's ~/.clab/<labName>/ directory ---
153+
// --- Deploy=true: Save to shared or user's .clab directory ---
156154
if req.OutputFile != "" {
157-
log.Warnf("GenerateTopology user '%s': 'outputFile' field provided but Deploy=true. Ignoring 'outputFile' and saving to user's ~/.clab directory.", username)
155+
log.Warnf("GenerateTopology user '%s': 'outputFile' field provided but Deploy=true. Ignoring 'outputFile' and saving to appropriate lab directory.", username)
158156
}
159157

160-
// Get User Home Directory, UID/GID
161-
usr, err = user.Lookup(username)
158+
// --- Get Lab Directory and User UID/GID ---
159+
targetDir, uid, gid, err := getLabDirectoryInfo(username, req.Name)
162160
if err != nil {
163-
log.Errorf("GenerateTopology failed for user '%s': Could not determine user details: %v", username, err)
164-
c.JSON(http.StatusInternalServerError, models.ErrorResponse{Error: "Could not determine user details."})
165-
return
166-
}
167-
homeDir := usr.HomeDir
168-
uid, err = strconv.Atoi(usr.Uid)
169-
if err != nil {
170-
log.Errorf("GenerateTopology failed for user '%s': Could not process user UID: %v", username, err)
171-
c.JSON(http.StatusInternalServerError, models.ErrorResponse{Error: "Could not process user UID."})
172-
return
173-
}
174-
gid, err = strconv.Atoi(usr.Gid)
175-
if err != nil {
176-
log.Errorf("GenerateTopology failed for user '%s': Could not process user GID: %v", username, err)
177-
c.JSON(http.StatusInternalServerError, models.ErrorResponse{Error: "Could not process user GID."})
161+
log.Errorf("GenerateTopology failed for user '%s': %v", username, err)
162+
c.JSON(http.StatusInternalServerError, models.ErrorResponse{Error: err.Error()})
178163
return
179164
}
180165

181-
// Construct Paths, Create Dir, Set Ownership
182-
clabUserDir := filepath.Join(homeDir, ".clab")
183-
targetDir := filepath.Join(clabUserDir, req.Name) // Use req.Name for the directory
184166
targetFilePath = filepath.Join(targetDir, req.Name+".clab.yml") // Use req.Name for the filename
185167

186-
err = os.MkdirAll(targetDir, 0750) // Create user's lab dir
168+
err = os.MkdirAll(targetDir, 0750) // Create lab dir
187169
if err != nil {
188170
log.Errorf("GenerateTopology failed for user '%s': Failed to create lab directory '%s': %v", username, targetDir, err)
189171
c.JSON(http.StatusInternalServerError, models.ErrorResponse{Error: fmt.Sprintf("Failed to create lab directory: %s.", err.Error())})

0 commit comments

Comments
 (0)