From 40fc1bab7dacb644b1b6ce6d4f50fc447e269ec9 Mon Sep 17 00:00:00 2001 From: Bhoopesh Date: Sun, 20 Oct 2024 17:00:15 +0530 Subject: [PATCH] fix: result and status Signed-off-by: Bhoopesh --- sztp-agent/cmd/daemon.go | 15 +- sztp-agent/cmd/disable.go | 6 +- sztp-agent/cmd/enable.go | 6 +- sztp-agent/cmd/run.go | 11 +- sztp-agent/cmd/status.go | 6 +- sztp-agent/pkg/secureagent/configuration.go | 16 +- sztp-agent/pkg/secureagent/daemon.go | 15 +- sztp-agent/pkg/secureagent/image.go | 4 +- sztp-agent/pkg/secureagent/status.go | 175 ++++++++++++++------ sztp-agent/pkg/secureagent/utils.go | 22 +-- sztp-agent/pkg/secureagent/utils_test.go | 7 +- 11 files changed, 177 insertions(+), 106 deletions(-) diff --git a/sztp-agent/cmd/daemon.go b/sztp-agent/cmd/daemon.go index 0dc0a0b..e03bf69 100644 --- a/sztp-agent/cmd/daemon.go +++ b/sztp-agent/cmd/daemon.go @@ -55,15 +55,6 @@ func Daemon() *cobra.Command { _, err := url.ParseRequestURI(bootstrapURL) cobra.CheckErr(err) } - if statusFilePath == "" { - return fmt.Errorf("'--status-file-path' is required") - } - if resultFilePath == "" { - return fmt.Errorf("'--result-file-path' is required") - } - if symLinkDir == "" { - return fmt.Errorf("'--symlink-dir' is required") - } for _, filePath := range arrayChecker { info, err := os.Stat(filePath) cobra.CheckErr(err) @@ -87,9 +78,9 @@ func Daemon() *cobra.Command { flags.StringVar(&devicePrivateKey, "device-private-key", "/certs/private_key.pem", "Device's private key") flags.StringVar(&deviceEndEntityCert, "device-end-entity-cert", "/certs/my_cert.pem", "Device's End Entity cert") flags.StringVar(&bootstrapTrustAnchorCert, "bootstrap-trust-anchor-cert", "/certs/opi.pem", "Bootstrap server trust anchor Cert") - flags.StringVar(&statusFilePath, "status-file-path", "/var/lib/sztp/status.json", "Path to the status file") - flags.StringVar(&resultFilePath, "result-file-path", "/var/lib/sztp/result.json", "Path to the result file") - flags.StringVar(&symLinkDir, "sym-link-dir", "/run/sztp", "Path to the symlink directory") + flags.StringVar(&statusFilePath, "status-file-path", "/var/lib/sztp/status.json", "Status file path") + flags.StringVar(&resultFilePath, "result-file-path", "/var/lib/sztp/result.json", "Result file path") + flags.StringVar(&symLinkDir, "sym-link-dir", "/run/sztp", "Sym Link Directory") return cmd } diff --git a/sztp-agent/cmd/disable.go b/sztp-agent/cmd/disable.go index b086aeb..f54a49b 100644 --- a/sztp-agent/cmd/disable.go +++ b/sztp-agent/cmd/disable.go @@ -53,9 +53,9 @@ func Disable() *cobra.Command { flags.StringVar(&devicePrivateKey, "device-private-key", "", "Device's private key") flags.StringVar(&deviceEndEntityCert, "device-end-entity-cert", "", "Device's End Entity cert") flags.StringVar(&bootstrapTrustAnchorCert, "bootstrap-trust-anchor-cert", "", "Bootstrap server trust anchor Cert") - flags.StringVar(&statusFilePath, "status-file-path", "", "Status file path") - flags.StringVar(&resultFilePath, "result-file-path", "", "Result file path") - flags.StringVar(&symLinkDir, "sym-link-dir", "", "Sym Link Directory") + flags.StringVar(&statusFilePath, "status-file-path", "/var/lib/sztp/status.json", "Status file path") + flags.StringVar(&resultFilePath, "result-file-path", "/var/lib/sztp/result.json", "Result file path") + flags.StringVar(&symLinkDir, "sym-link-dir", "/run/sztp", "Sym Link Directory") return cmd } diff --git a/sztp-agent/cmd/enable.go b/sztp-agent/cmd/enable.go index 2c6513d..e87422b 100644 --- a/sztp-agent/cmd/enable.go +++ b/sztp-agent/cmd/enable.go @@ -53,9 +53,9 @@ func Enable() *cobra.Command { flags.StringVar(&devicePrivateKey, "device-private-key", "", "Device's private key") flags.StringVar(&deviceEndEntityCert, "device-end-entity-cert", "", "Device's End Entity cert") flags.StringVar(&bootstrapTrustAnchorCert, "bootstrap-trust-anchor-cert", "", "Bootstrap server trust anchor Cert") - flags.StringVar(&statusFilePath, "status-file-path", "", "Status file path") - flags.StringVar(&resultFilePath, "result-file-path", "", "Result file path") - flags.StringVar(&symLinkDir, "sym-link-dir", "", "Sym Link Directory") + flags.StringVar(&statusFilePath, "status-file-path", "/var/lib/sztp/status.json", "Status file path") + flags.StringVar(&resultFilePath, "result-file-path", "/var/lib/sztp/result.json", "Result file path") + flags.StringVar(&symLinkDir, "sym-link-dir", "/run/sztp", "Sym Link Directory") return cmd } diff --git a/sztp-agent/cmd/run.go b/sztp-agent/cmd/run.go index a76cb79..a86c26b 100644 --- a/sztp-agent/cmd/run.go +++ b/sztp-agent/cmd/run.go @@ -55,15 +55,6 @@ func Run() *cobra.Command { _, err := url.ParseRequestURI(bootstrapURL) cobra.CheckErr(err) } - if statusFilePath == "" { - return fmt.Errorf("'--status-file-path' is required") - } - if resultFilePath == "" { - return fmt.Errorf("'--result-file-path' is required") - } - if symLinkDir == "" { - return fmt.Errorf("'--symlink-dir' is required") - } for _, filePath := range arrayChecker { info, err := os.Stat(filePath) cobra.CheckErr(err) @@ -89,7 +80,7 @@ func Run() *cobra.Command { flags.StringVar(&bootstrapTrustAnchorCert, "bootstrap-trust-anchor-cert", "/certs/opi.pem", "Bootstrap server trust anchor Cert") flags.StringVar(&statusFilePath, "status-file-path", "/var/lib/sztp/status.json", "Status file path") flags.StringVar(&resultFilePath, "result-file-path", "/var/lib/sztp/result.json", "Result file path") - flags.StringVar(&symLinkDir, "sym-link-dir", "", "Sym Link Directory") + flags.StringVar(&symLinkDir, "sym-link-dir", "/run/sztp", "Sym Link Directory") return cmd } diff --git a/sztp-agent/cmd/status.go b/sztp-agent/cmd/status.go index debbaa4..41a03fd 100644 --- a/sztp-agent/cmd/status.go +++ b/sztp-agent/cmd/status.go @@ -53,9 +53,9 @@ func Status() *cobra.Command { flags.StringVar(&devicePrivateKey, "device-private-key", "", "Device's private key") flags.StringVar(&deviceEndEntityCert, "device-end-entity-cert", "", "Device's End Entity cert") flags.StringVar(&bootstrapTrustAnchorCert, "bootstrap-trust-anchor-cert", "", "Bootstrap server trust anchor Cert") - flags.StringVar(&statusFilePath, "status-file-path", "", "Status file path") - flags.StringVar(&resultFilePath, "result-file-path", "", "Result file path") - flags.StringVar(&symLinkDir, "sym-link-dir", "", "Sym Link Directory") + flags.StringVar(&statusFilePath, "status-file-path", "/var/lib/sztp/status.json", "Status file path") + flags.StringVar(&resultFilePath, "result-file-path", "/var/lib/sztp/result.json", "Result file path") + flags.StringVar(&symLinkDir, "sym-link-dir", "/run/sztp", "Sym Link Directory") return cmd } diff --git a/sztp-agent/pkg/secureagent/configuration.go b/sztp-agent/pkg/secureagent/configuration.go index 95b35b6..41a3b80 100644 --- a/sztp-agent/pkg/secureagent/configuration.go +++ b/sztp-agent/pkg/secureagent/configuration.go @@ -10,7 +10,7 @@ import ( func (a *Agent) copyConfigurationFile() error { log.Println("[INFO] Starting the Copy Configuration.") _ = a.doReportProgress(ProgressTypeConfigInitiated, "Configuration Initiated") - _ = a.updateAndSaveStatus("config", true, "") + _ = a.updateAndSaveStatus(StageTypeConfig, true, "") // Copy the configuration file to the device file, err := os.Create(ARTIFACTS_PATH + a.BootstrapServerOnboardingInfo.IetfSztpConveyedInfoOnboardingInformation.InfoTimestampReference + "-config") if err != nil { @@ -37,7 +37,7 @@ func (a *Agent) copyConfigurationFile() error { } log.Println("[INFO] Configuration file copied successfully") _ = a.doReportProgress(ProgressTypeConfigComplete, "Configuration Complete") - _ = a.updateAndSaveStatus("config", false, "") + _ = a.updateAndSaveStatus(StageTypeConfig, false, "") return nil } @@ -58,7 +58,11 @@ func (a *Agent) launchScriptsConfiguration(typeOf string) error { } log.Println("[INFO] Starting the " + scriptName + "-configuration.") _ = a.doReportProgress(reportStart, "Report starting") - _ = a.updateAndSaveStatus(scriptName+"-script", true, "") + if scriptName == "pre" { + _ = a.updateAndSaveStatus(StageTypePreScript, true, "") + } else if scriptName == "post" { + _ = a.updateAndSaveStatus(StageTypePostScript, true, "") + } // nolint:gosec file, err := os.Create(ARTIFACTS_PATH + a.BootstrapServerOnboardingInfo.IetfSztpConveyedInfoOnboardingInformation.InfoTimestampReference + scriptName + "configuration.sh") if err != nil { @@ -92,7 +96,11 @@ func (a *Agent) launchScriptsConfiguration(typeOf string) error { } log.Println(string(out)) // remove it _ = a.doReportProgress(reportEnd, "Report end") - _ = a.updateAndSaveStatus(scriptName+"-script", false, "") + if scriptName == "pre" { + _ = a.updateAndSaveStatus(StageTypePreScript, false, "") + } else if scriptName == "post" { + _ = a.updateAndSaveStatus(StageTypePostScript, false, "") + } log.Println("[INFO] " + scriptName + "-Configuration script executed successfully") return nil } diff --git a/sztp-agent/pkg/secureagent/daemon.go b/sztp-agent/pkg/secureagent/daemon.go index 066e571..a8abd7b 100644 --- a/sztp-agent/pkg/secureagent/daemon.go +++ b/sztp-agent/pkg/secureagent/daemon.go @@ -37,51 +37,60 @@ func (a *Agent) RunCommandDaemon() error { log.Println("failed to prepare status: ", err) return err } + _ = a.updateAndSaveStatus(StageTypeIsCompleted, true, "") for { err := a.performBootstrapSequence() if err != nil { log.Println("[ERROR] Failed to perform the bootstrap sequence: ", err.Error()) log.Println("[INFO] Retrying in 5 seconds") time.Sleep(5 * time.Second) + _ = a.updateAndSaveStatus(StageTypeIsCompleted, false, err.Error()) continue } + _ = a.updateAndSaveStatus(StageTypeIsCompleted, false, "") return nil } } func (a *Agent) performBootstrapSequence() error { - _ = a.updateAndSaveStatus("bootstrap", true, "") var err error err = a.discoverBootstrapURLs() if err != nil { + _ = a.updateAndSaveStatus(StageTypeParsing, false, err.Error()) return err } err = a.doRequestBootstrapServerOnboardingInfo() if err != nil { + _ = a.updateAndSaveStatus(StageTypeOnboarding, false, err.Error()) return err } err = a.doHandleBootstrapRedirect() if err != nil { + _ = a.updateAndSaveStatus(StageTypeBootImage, false, err.Error()) return err } err = a.downloadAndValidateImage() if err != nil { + _ = a.updateAndSaveStatus(StageTypeBootImage, false, err.Error()) return err } err = a.copyConfigurationFile() if err != nil { + _ = a.updateAndSaveStatus(StageTypeConfig, false, err.Error()) return err } err = a.launchScriptsConfiguration(PRE) if err != nil { + _ = a.updateAndSaveStatus(StageTypePreScript, false, err.Error()) return err } err = a.launchScriptsConfiguration(POST) if err != nil { + _ = a.updateAndSaveStatus(StageTypePostScript, false, err.Error()) return err } _ = a.doReportProgress(ProgressTypeBootstrapComplete, "Bootstrap Complete") - _ = a.updateAndSaveStatus("bootstrap", false, "") + _ = a.updateAndSaveStatus(StageTypeBootstrap, false, "") return nil } @@ -148,7 +157,7 @@ func (a *Agent) doRequestBootstrapServerOnboardingInfo() error { } log.Println("[INFO] Response retrieved successfully") _ = a.doReportProgress(ProgressTypeBootstrapInitiated, "Bootstrap Initiated") - _ = a.updateAndSaveStatus("bootstrap", true, "") + _ = a.updateAndSaveStatus(StageTypeBootstrap, true, "") crypto := res.IetfSztpBootstrapServerOutput.ConveyedInformation newVal, err := base64.StdEncoding.DecodeString(crypto) if err != nil { diff --git a/sztp-agent/pkg/secureagent/image.go b/sztp-agent/pkg/secureagent/image.go index 4466698..7362d77 100644 --- a/sztp-agent/pkg/secureagent/image.go +++ b/sztp-agent/pkg/secureagent/image.go @@ -23,7 +23,7 @@ import ( func (a *Agent) downloadAndValidateImage() error { log.Printf("[INFO] Starting the Download Image: %v", a.BootstrapServerOnboardingInfo.IetfSztpConveyedInfoOnboardingInformation.BootImage.DownloadURI) _ = a.doReportProgress(ProgressTypeBootImageInitiated, "BootImage Initiated") - _ = a.updateAndSaveStatus("boot-image", true, "") + _ = a.updateAndSaveStatus(StageTypeBootImage, true, "") // Download the image from DownloadURI and save it to a file a.BootstrapServerOnboardingInfo.IetfSztpConveyedInfoOnboardingInformation.InfoTimestampReference = fmt.Sprintf("%8d", time.Now().Unix()) for i, item := range a.BootstrapServerOnboardingInfo.IetfSztpConveyedInfoOnboardingInformation.BootImage.DownloadURI { @@ -79,7 +79,7 @@ func (a *Agent) downloadAndValidateImage() error { } log.Println("[INFO] Checksum verified successfully") _ = a.doReportProgress(ProgressTypeBootImageComplete, "BootImage Complete") - _ = a.updateAndSaveStatus("boot-image", false, "") + _ = a.updateAndSaveStatus(StageTypeBootImage, false, "") return nil default: return errors.New("unsupported hash algorithm") diff --git a/sztp-agent/pkg/secureagent/status.go b/sztp-agent/pkg/secureagent/status.go index 656471c..7c9d7ee 100644 --- a/sztp-agent/pkg/secureagent/status.go +++ b/sztp-agent/pkg/secureagent/status.go @@ -9,20 +9,68 @@ Copyright (C) 2022 Red Hat. package secureagent import ( - "encoding/json" "fmt" "log" - "os" "path/filepath" "time" ) +type StageType int64 + +const ( + StageTypeInit StageType = iota + StageTypeDownloadingFile + StageTypePendingReboot + StageTypeParsing + StageTypeOnboarding + StageTypeRedirect + StageTypeBootImage + StageTypePreScript + StageTypeConfig + StageTypePostScript + StageTypeBootstrap + StageTypeIsCompleted +) + +func (s StageType) String() string { + switch s { + case StageTypeInit: + return "init" + case StageTypeDownloadingFile: + return "downloading-file" + case StageTypePendingReboot: + return "pending-reboot" + case StageTypeParsing: + return "parsing" + case StageTypeOnboarding: + return "onboarding" + case StageTypeRedirect: + return "redirect" + case StageTypeBootImage: + return "boot-image" + case StageTypePreScript: + return "pre-script" + case StageTypeConfig: + return "config" + case StageTypePostScript: + return "post-script" + case StageTypeBootstrap: + return "bootstrap" + case StageTypeIsCompleted: + return "is-completed" + default: + return "unknown" + } +} + // Status represents the status of the provisioning process. type Status struct { Init StageStatus `json:"init"` - DownloadingFile StageStatus `json:"downloading-file"` // not sure if this is needed + DownloadingFile StageStatus `json:"downloading-file"` PendingReboot StageStatus `json:"pending-reboot"` Parsing StageStatus `json:"parsing"` + Onboarding StageStatus `json:"onboarding"` + Redirect StageStatus `json:"redirect"` BootImage StageStatus `json:"boot-image"` PreScript StageStatus `json:"pre-script"` Config StageStatus `json:"config"` @@ -30,12 +78,10 @@ type Status struct { Bootstrap StageStatus `json:"bootstrap"` IsCompleted StageStatus `json:"is-completed"` Informational string `json:"informational"` - DataSource string `json:"datasource"` Stage string `json:"stage"` } type Result struct { - DataSource string `json:"dat asource"` Errors []string `json:"errors"` } @@ -45,67 +91,78 @@ type StageStatus struct { End float64 `json:"end"` } -// LoadStatusFile loads the current status.json from the filesystem. -func (a *Agent) loadStatusFile() (*Status, error) { - file, err := os.ReadFile(a.GetStatusFilePath()) +func (a *Agent) getCurrStatus() (*Status, error) { + var status Status + err := loadFile(a.GetStatusFilePath(), &status) if err != nil { return nil, err } - var status Status - err = json.Unmarshal(file, &status) + return &status, nil +} + +func (a *Agent) getCurrResult() (*Result, error) { + var result Result + err := loadFile(a.GetResultFilePath(), &result) if err != nil { return nil, err } - return &status, nil + return &result, nil } -func (a *Agent) updateAndSaveStatus(stage string, isStart bool, errMsg string) error { - status, err := a.loadStatusFile() +func (a *Agent) createNewStatus() *Status { + return &Status{ + Stage: "", + IsCompleted: StageStatus{}, + } +} + +// updateAndSaveStatus updates the status object for a specific stage and saves it to the status.json file. +func (a *Agent) updateAndSaveStatus(s StageType, isStart bool, errMsg string) error { + status, err := a.getCurrStatus() if err != nil { fmt.Println("Creating a new status file.") status = a.createNewStatus() } - if err := a.updateStageStatus(status, stage, isStart, errMsg); err != nil { + err = a.updateStageStatus(status, s, isStart, errMsg) + if err != nil { return err } return a.saveStatus(status) } -// createNewStatus initializes a new Status object when status.json doesn't exist. -func (a *Agent) createNewStatus() *Status { - return &Status{ - DataSource: "ds", - Stage: "", - } -} - // updateStageStatus updates the status object for a specific stage. -func (a *Agent) updateStageStatus(status *Status, stage string, isStart bool, errMsg string) error { +func (a *Agent) updateStageStatus(status *Status, stageType StageType, isStart bool, errMsg string) error { now := float64(time.Now().Unix()) - switch stage { - case "init": - updateStage(&status.Init, isStart, now, errMsg) - case "downloading-file": - updateStage(&status.DownloadingFile, isStart, now, errMsg) - case "pending-reboot": - updateStage(&status.PendingReboot, isStart, now, errMsg) - case "is-completed": - updateStage(&status.IsCompleted, isStart, now, errMsg) - case "parsing": - updateStage(&status.Parsing, isStart, now, errMsg) - case "boot-image": - updateStage(&status.BootImage, isStart, now, errMsg) - case "pre-script": - updateStage(&status.PreScript, isStart, now, errMsg) - case "config": - updateStage(&status.Config, isStart, now, errMsg) - case "post-script": - updateStage(&status.PostScript, isStart, now, errMsg) - case "bootstrap": - updateStage(&status.Bootstrap, isStart, now, errMsg) + stage := stageType.String() + + switch stageType { + case StageTypeInit: + a.updateStage(&status.Init, isStart, now, errMsg) + case StageTypeDownloadingFile: + a.updateStage(&status.DownloadingFile, isStart, now, errMsg) + case StageTypePendingReboot: + a.updateStage(&status.PendingReboot, isStart, now, errMsg) + case StageTypeIsCompleted: + a.updateStage(&status.IsCompleted, isStart, now, errMsg) + case StageTypeParsing: + a.updateStage(&status.Parsing, isStart, now, errMsg) + case StageTypeOnboarding: + a.updateStage(&status.Onboarding, isStart, now, errMsg) + case StageTypeRedirect: + a.updateStage(&status.Redirect, isStart, now, errMsg) + case StageTypeBootImage: + a.updateStage(&status.BootImage, isStart, now, errMsg) + case StageTypePreScript: + a.updateStage(&status.PreScript, isStart, now, errMsg) + case StageTypeConfig: + a.updateStage(&status.Config, isStart, now, errMsg) + case StageTypePostScript: + a.updateStage(&status.PostScript, isStart, now, errMsg) + case StageTypeBootstrap: + a.updateStage(&status.Bootstrap, isStart, now, errMsg) default: return fmt.Errorf("unknown stage: %s", stage) @@ -113,15 +170,15 @@ func (a *Agent) updateStageStatus(status *Status, stage string, isStart bool, er // Update the current stage if isStart { - status.Stage = stage + status.Stage = stage + "-in-progress" } else { - status.Stage = "" + status.Stage = stage + "-completed" } return nil } -func updateStage(stageStatus *StageStatus, isStart bool, now float64, errMsg string) { +func (a *Agent) updateStage(stageStatus *StageStatus, isStart bool, now float64, errMsg string) { if isStart { stageStatus.Start = now stageStatus.End = 0 @@ -129,25 +186,39 @@ func updateStage(stageStatus *StageStatus, isStart bool, now float64, errMsg str stageStatus.End = now if errMsg != "" { stageStatus.Errors = append(stageStatus.Errors, errMsg) + a.updateAndSaveResult(errMsg) } } } -// SaveStatusToFile saves the Status object to the status.json file. func (a *Agent) saveStatus(status *Status) error { return saveToFile(status, a.GetStatusFilePath()) } -// SaveResultFile saves the Result object to the result.json file. func (a *Agent) saveResult(result *Result) error { return saveToFile(result, a.GetResultFilePath()) } +func (a *Agent) updateAndSaveResult(errMsg string) error { + result, err := a.getCurrResult() + if err != nil { + fmt.Println("Creating a new result file.") + result = &Result{ + Errors: []string{}, + } + } + + if errMsg != "" { + result.Errors = append(result.Errors, errMsg) + } + + return a.saveResult(result) +} + // RunCommandStatus runs the command in the background func (a *Agent) RunCommandStatus() error { log.Println("RunCommandStatus") - // read the status file and print the status in command line - status, err := a.loadStatusFile() + status, err := a.getCurrStatus() if err != nil { log.Println("failed to load status file: ", err) return err @@ -187,7 +258,7 @@ func (a *Agent) prepareStatus() error { fmt.Println("Symlinks created successfully.") - if err := a.updateAndSaveStatus("init", true, ""); err != nil { + if err := a.updateAndSaveStatus(StageTypeInit, true, ""); err != nil { return err } diff --git a/sztp-agent/pkg/secureagent/utils.go b/sztp-agent/pkg/secureagent/utils.go index 0eddb2f..dcc1f73 100644 --- a/sztp-agent/pkg/secureagent/utils.go +++ b/sztp-agent/pkg/secureagent/utils.go @@ -89,7 +89,6 @@ func calculateSHA256File(filePath string) (string, error) { return checkSum, nil } -// saveToFile writes the given data to a specified file path. func saveToFile(data interface{}, filePath string) error { tempPath := filePath + ".tmp" file, err := os.Create(tempPath) @@ -107,7 +106,6 @@ func saveToFile(data interface{}, filePath string) error { return os.Rename(tempPath, filePath) } -// EnsureDirExists checks if a directory exists, and creates it if it doesn't. func ensureDirExists(dir string) error { if _, err := os.Stat(dir); os.IsNotExist(err) { err := os.MkdirAll(dir, 0755) // Create the directory with appropriate permissions @@ -118,17 +116,13 @@ func ensureDirExists(dir string) error { return nil } -// EnsureFile ensures that a file exists; creates it if it does not. func ensureFileExists(filePath string) error { - // Ensure the directory exists dir := filepath.Dir(filePath) if err := ensureDirExists(dir); err != nil { return err } - // Check if the file already exists if _, err := os.Stat(filePath); os.IsNotExist(err) { - // File does not exist, create it file, err := os.Create(filePath) if err != nil { return fmt.Errorf("failed to create file %s: %v", filePath, err) @@ -141,19 +135,27 @@ func ensureFileExists(filePath string) error { return nil } -// CreateSymlink creates a symlink for a file from target to link location. func createSymlink(targetFile, linkFile string) error { - // Ensure the directory for the symlink exists linkDir := filepath.Dir(linkFile) if err := ensureDirExists(linkDir); err != nil { return err } - // Remove any existing symlink if _, err := os.Lstat(linkFile); err == nil { os.Remove(linkFile) } - // Create a new symlink return os.Symlink(targetFile, linkFile) } + +func loadFile(filePath string, v interface{}) error { + file, err := os.ReadFile(filePath) + if err != nil { + return err + } + err = json.Unmarshal(file, v) + if err != nil { + return err + } + return nil +} diff --git a/sztp-agent/pkg/secureagent/utils_test.go b/sztp-agent/pkg/secureagent/utils_test.go index 42e134f..8d4e635 100644 --- a/sztp-agent/pkg/secureagent/utils_test.go +++ b/sztp-agent/pkg/secureagent/utils_test.go @@ -117,7 +117,7 @@ func Test_saveToFile(t *testing.T) { } } -func TestEnsureDirExists(t *testing.T) { +func Test_ensureDirExists(t *testing.T) { tempDir, err := os.MkdirTemp("", "test_ensure_dir_exists") if err != nil { t.Fatalf("failed to create temp directory: %v", err) @@ -145,7 +145,7 @@ func TestEnsureDirExists(t *testing.T) { } } -func TestEnsureFileExists(t *testing.T) { +func Test_ensureFileExists(t *testing.T) { tempDir, err := os.MkdirTemp("", "test_ensure_file_exists") if err != nil { t.Fatalf("failed to create temp directory: %v", err) @@ -169,7 +169,7 @@ func TestEnsureFileExists(t *testing.T) { } } -func TestCreateSymlink(t *testing.T) { +func Test_createSymlink(t *testing.T) { tempDir, err := os.MkdirTemp("", "test_create_symlink") if err != nil { t.Fatalf("failed to create temp directory: %v", err) @@ -190,7 +190,6 @@ func TestCreateSymlink(t *testing.T) { } linkInfo, err := os.Lstat(linkFile) - t.Logf("linkInfo: %v", linkInfo) /// if err != nil { t.Fatalf("failed to stat symlink: %v", err) }