Skip to content

Commit 614ee3d

Browse files
committed
feat: support output the log to file
Signed-off-by: chlins <chlins.zhang@gmail.com>
1 parent 3a2aab2 commit 614ee3d

File tree

29 files changed

+301
-62
lines changed

29 files changed

+301
-62
lines changed

cmd/attach.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func runAttach(ctx context.Context, filepath string) error {
8484
sp.Start()
8585
defer sp.Stop()
8686

87-
nydusName, err := b.Nydusify(ctx, attachConfig.Target)
87+
nydusName, err := b.Nydusify(ctx, attachConfig.Target, rootConfig)
8888
if err != nil {
8989
err = fmt.Errorf("failed to nydusify %s: %w", attachConfig.Target, err)
9090
sp.FinalMSG = err.Error()

cmd/build.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ import (
2121
"fmt"
2222
"time"
2323

24-
"github.com/CloudNativeAI/modctl/pkg/backend"
25-
"github.com/CloudNativeAI/modctl/pkg/config"
2624
"github.com/briandowns/spinner"
27-
2825
"github.com/spf13/cobra"
2926
"github.com/spf13/viper"
27+
28+
"github.com/CloudNativeAI/modctl/pkg/backend"
29+
"github.com/CloudNativeAI/modctl/pkg/config"
3030
)
3131

3232
var buildConfig = config.NewBuild()
@@ -86,7 +86,7 @@ func runBuild(ctx context.Context, workDir string) error {
8686
sp.Start()
8787
defer sp.Stop()
8888

89-
nydusName, err := b.Nydusify(ctx, buildConfig.Target)
89+
nydusName, err := b.Nydusify(ctx, buildConfig.Target, rootConfig)
9090
if err != nil {
9191
err = fmt.Errorf("failed to nydusify %s: %w", buildConfig.Target, err)
9292
sp.FinalMSG = err.Error()

cmd/push.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func runPush(ctx context.Context, target string) error {
8181
sp.Start()
8282
defer sp.Stop()
8383

84-
nydusName, err := b.Nydusify(ctx, target)
84+
nydusName, err := b.Nydusify(ctx, target, rootConfig)
8585
if err != nil {
8686
err = fmt.Errorf("failed to nydusify %s: %w", target, err)
8787
sp.FinalMSG = err.Error()

cmd/root.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ import (
2424
"os/signal"
2525
"syscall"
2626

27-
"github.com/CloudNativeAI/modctl/cmd/modelfile"
28-
"github.com/CloudNativeAI/modctl/pkg/config"
29-
27+
"github.com/sirupsen/logrus"
3028
"github.com/spf13/cobra"
3129
"github.com/spf13/viper"
30+
31+
"github.com/CloudNativeAI/modctl/cmd/modelfile"
32+
"github.com/CloudNativeAI/modctl/pkg/config"
3233
)
3334

3435
var rootConfig *config.Root
@@ -51,6 +52,23 @@ var rootCmd = &cobra.Command{
5152
}
5253
}()
5354
}
55+
56+
// Initialize logger.
57+
logFile, err := os.OpenFile(rootConfig.LogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
58+
if err != nil {
59+
logrus.Fatalf("Failed to open log file: %v", err)
60+
}
61+
// defer logFile.Close()
62+
63+
logLevel, err := logrus.ParseLevel(rootConfig.LogLevel)
64+
if err != nil {
65+
logrus.Fatalf("Failed to parse log level: %v", err)
66+
}
67+
68+
logrus.SetOutput(logFile)
69+
logrus.SetLevel(logLevel)
70+
logrus.SetFormatter(&logrus.TextFormatter{})
71+
5472
return nil
5573
},
5674
}
@@ -83,6 +101,8 @@ func init() {
83101
flags.StringVar(&rootConfig.StoargeDir, "storage-dir", rootConfig.StoargeDir, "specify the storage directory for modctl")
84102
flags.BoolVar(&rootConfig.Pprof, "pprof", rootConfig.Pprof, "enable pprof")
85103
flags.StringVar(&rootConfig.PprofAddr, "pprof-addr", rootConfig.PprofAddr, "specify the address for pprof")
104+
flags.StringVar(&rootConfig.LogLevel, "log-level", rootConfig.LogLevel, "specify the log level")
105+
flags.StringVar(&rootConfig.LogFile, "log-file", rootConfig.LogFile, "specify the log file")
86106

87107
// Bind common flags.
88108
if err := viper.BindPFlags(flags); err != nil {

pkg/archiver/archiver.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@ import (
2323
"os"
2424
"path/filepath"
2525
"strings"
26+
27+
"github.com/sirupsen/logrus"
2628
)
2729

2830
// Tar creates a tar archive of the specified path (file or directory)
2931
// and returns the content as a stream. For individual files, it preserves
3032
// the directory structure relative to the working directory.
3133
func Tar(srcPath string, workDir string) (io.Reader, error) {
34+
logrus.Infof("Taring %s, work dir: %s", srcPath, workDir)
3235
pr, pw := io.Pipe()
3336

3437
go func() {
@@ -38,6 +41,7 @@ func Tar(srcPath string, workDir string) (io.Reader, error) {
3841

3942
info, err := os.Stat(srcPath)
4043
if err != nil {
44+
logrus.Errorf("failed to stat source path: %v", err)
4145
pw.CloseWithError(fmt.Errorf("failed to stat source path: %w", err))
4246
return
4347
}
@@ -53,28 +57,33 @@ func Tar(srcPath string, workDir string) (io.Reader, error) {
5357
// Create a relative path for the tar file header.
5458
relPath, err := filepath.Rel(workDir, path)
5559
if err != nil {
60+
logrus.Errorf("failed to get relative path: %v", err)
5661
return fmt.Errorf("failed to get relative path: %w", err)
5762
}
5863

5964
header, err := tar.FileInfoHeader(info, "")
6065
if err != nil {
66+
logrus.Errorf("failed to create tar header: %v", err)
6167
return fmt.Errorf("failed to create tar header: %w", err)
6268
}
6369

6470
// Set the header name to preserve directory structure.
6571
header.Name = relPath
6672
if err := tw.WriteHeader(header); err != nil {
73+
logrus.Errorf("failed to write header: %v", err)
6774
return fmt.Errorf("failed to write header: %w", err)
6875
}
6976

7077
if !info.IsDir() {
7178
file, err := os.Open(path)
7279
if err != nil {
80+
logrus.Errorf("failed to open file %s: %v", path, err)
7381
return fmt.Errorf("failed to open file %s: %w", path, err)
7482
}
7583
defer file.Close()
7684

7785
if _, err := io.Copy(tw, file); err != nil {
86+
logrus.Errorf("failed to write file %s to tar: %v", path, err)
7887
return fmt.Errorf("failed to write file %s to tar: %w", path, err)
7988
}
8089
}
@@ -83,20 +92,23 @@ func Tar(srcPath string, workDir string) (io.Reader, error) {
8392
})
8493

8594
if err != nil {
95+
logrus.Errorf("failed to walk directory: %v", err)
8696
pw.CloseWithError(fmt.Errorf("failed to walk directory: %w", err))
8797
return
8898
}
8999
} else {
90100
// For a single file, include the directory structure.
91101
file, err := os.Open(srcPath)
92102
if err != nil {
103+
logrus.Errorf("failed to open file %s: %v", srcPath, err)
93104
pw.CloseWithError(fmt.Errorf("failed to open file: %w", err))
94105
return
95106
}
96107
defer file.Close()
97108

98109
header, err := tar.FileInfoHeader(info, "")
99110
if err != nil {
111+
logrus.Errorf("failed to create tar header for file %s: %v", srcPath, err)
100112
pw.CloseWithError(fmt.Errorf("failed to create tar header: %w", err))
101113
return
102114
}
@@ -105,18 +117,21 @@ func Tar(srcPath string, workDir string) (io.Reader, error) {
105117
// This keeps the directory structure as part of the file path in the tar.
106118
relPath, err := filepath.Rel(workDir, srcPath)
107119
if err != nil {
120+
logrus.Errorf("failed to get relative path for file %s: %v", srcPath, err)
108121
pw.CloseWithError(fmt.Errorf("failed to get relative path: %w", err))
109122
return
110123
}
111124

112125
// Use the relative path (including directories) as the header name.
113126
header.Name = relPath
114127
if err := tw.WriteHeader(header); err != nil {
128+
logrus.Errorf("failed to write header for file %s: %v", srcPath, err)
115129
pw.CloseWithError(fmt.Errorf("failed to write header: %w", err))
116130
return
117131
}
118132

119133
if _, err := io.Copy(tw, file); err != nil {
134+
logrus.Errorf("failed to copy file to tar for file %s: %v", srcPath, err)
120135
pw.CloseWithError(fmt.Errorf("failed to copy file to tar: %w", err))
121136
return
122137
}
@@ -129,10 +144,12 @@ func Tar(srcPath string, workDir string) (io.Reader, error) {
129144
// Untar extracts the contents of a tar archive from the provided reader
130145
// to the specified destination path.
131146
func Untar(reader io.Reader, destPath string) error {
147+
logrus.Infof("Untaring archive to %s", destPath)
132148
tarReader := tar.NewReader(reader)
133149

134150
// Ensure destination directory exists.
135151
if err := os.MkdirAll(destPath, 0755); err != nil {
152+
logrus.Errorf("failed to create destination directory: %v", err)
136153
return fmt.Errorf("failed to create destination directory: %w", err)
137154
}
138155

@@ -142,12 +159,14 @@ func Untar(reader io.Reader, destPath string) error {
142159
break
143160
}
144161
if err != nil {
162+
logrus.Errorf("error reading tar: %v", err)
145163
return fmt.Errorf("error reading tar: %w", err)
146164
}
147165

148166
// Sanitize file paths to prevent directory traversal.
149167
cleanPath := filepath.Clean(header.Name)
150168
if strings.Contains(cleanPath, "..") || strings.HasPrefix(cleanPath, "/") || strings.HasPrefix(cleanPath, ":\\") {
169+
logrus.Errorf("tar file contains invalid path: %s", cleanPath)
151170
return fmt.Errorf("tar file contains invalid path: %s", cleanPath)
152171
}
153172

@@ -156,12 +175,14 @@ func Untar(reader io.Reader, destPath string) error {
156175
// Create directories for all path components.
157176
dirPath := filepath.Dir(targetPath)
158177
if err := os.MkdirAll(dirPath, 0755); err != nil {
178+
logrus.Errorf("failed to create directory %s: %v", dirPath, err)
159179
return fmt.Errorf("failed to create directory %s: %w", dirPath, err)
160180
}
161181

162182
switch header.Typeflag {
163183
case tar.TypeDir:
164184
if err := os.MkdirAll(targetPath, os.FileMode(header.Mode)); err != nil {
185+
logrus.Errorf("failed to create directory %s: %v", targetPath, err)
165186
return fmt.Errorf("failed to create directory %s: %w", targetPath, err)
166187
}
167188

@@ -172,21 +193,25 @@ func Untar(reader io.Reader, destPath string) error {
172193
os.FileMode(header.Mode),
173194
)
174195
if err != nil {
196+
logrus.Errorf("failed to create file %s: %v", targetPath, err)
175197
return fmt.Errorf("failed to create file %s: %w", targetPath, err)
176198
}
177199

178200
if _, err := io.Copy(file, tarReader); err != nil {
179201
file.Close()
202+
logrus.Errorf("failed to write to file %s: %v", targetPath, err)
180203
return fmt.Errorf("failed to write to file %s: %w", targetPath, err)
181204
}
182205
file.Close()
183206

184207
case tar.TypeSymlink:
185208
if isRel(header.Linkname, destPath) && isRel(header.Name, destPath) {
186209
if err := os.Symlink(header.Linkname, targetPath); err != nil {
210+
logrus.Errorf("failed to create symlink %s -> %s: %v", targetPath, header.Linkname, err)
187211
return fmt.Errorf("failed to create symlink %s -> %s: %w", targetPath, header.Linkname, err)
188212
}
189213
} else {
214+
logrus.Errorf("symlink %s -> %s points outside of destination directory", targetPath, header.Linkname)
190215
return fmt.Errorf("symlink %s -> %s points outside of destination directory", targetPath, header.Linkname)
191216
}
192217

pkg/backend/attach.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
modelspec "github.com/CloudNativeAI/model-spec/specs-go/v1"
2828
godigest "github.com/opencontainers/go-digest"
2929
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
30+
"github.com/sirupsen/logrus"
3031

3132
internalpb "github.com/CloudNativeAI/modctl/internal/pb"
3233
"github.com/CloudNativeAI/modctl/pkg/backend/build"
@@ -58,13 +59,17 @@ var (
5859

5960
// Attach attaches user materials into the model artifact which follows the Model Spec.
6061
func (b *backend) Attach(ctx context.Context, filepath string, cfg *config.Attach) error {
62+
logrus.Infof("Attaching file %s to %s", filepath, cfg.Source)
63+
6164
srcManifest, err := b.getManifest(ctx, cfg.Source, cfg)
6265
if err != nil {
66+
logrus.Errorf("failed to get source manifest: %v", err)
6367
return fmt.Errorf("failed to get source manifest: %w", err)
6468
}
6569

6670
srcModelConfig, err := b.getModelConfig(ctx, cfg.Source, srcManifest.Config, cfg)
6771
if err != nil {
72+
logrus.Errorf("failed to get source model config: %v", err)
6873
return fmt.Errorf("failed to get source model config: %w", err)
6974
}
7075

@@ -95,11 +100,13 @@ func (b *backend) Attach(ctx context.Context, filepath string, cfg *config.Attac
95100

96101
proc := b.getProcessor(filepath)
97102
if proc == nil {
103+
logrus.Errorf("failed to get processor for file %s", filepath)
98104
return fmt.Errorf("failed to get processor for file %s", filepath)
99105
}
100106

101107
builder, err := b.getBuilder(cfg.Target, cfg)
102108
if err != nil {
109+
logrus.Errorf("failed to create builder: %v", err)
103110
return fmt.Errorf("failed to create builder: %w", err)
104111
}
105112

@@ -109,6 +116,7 @@ func (b *backend) Attach(ctx context.Context, filepath string, cfg *config.Attac
109116

110117
newLayers, err := proc.Process(ctx, builder, ".", processor.WithProgressTracker(pb))
111118
if err != nil {
119+
logrus.Errorf("failed to process layers: %v", err)
112120
return fmt.Errorf("failed to process layers: %w", err)
113121
}
114122

@@ -122,6 +130,7 @@ func (b *backend) Attach(ctx context.Context, filepath string, cfg *config.Attac
122130
}
123131
// Return earlier if the diffID has no changed, which means the artifact has not changed.
124132
if reflect.DeepEqual(diffIDs, srcModelConfig.ModelFS.DiffIDs) {
133+
logrus.Info("The artifact has not changed after attaching layer, skip to attach")
125134
return nil
126135
}
127136

@@ -147,6 +156,7 @@ func (b *backend) Attach(ctx context.Context, filepath string, cfg *config.Attac
147156
}),
148157
))
149158
if err != nil {
159+
logrus.Errorf("failed to build model config: %v", err)
150160
return fmt.Errorf("failed to build model config: %w", err)
151161
}
152162

@@ -163,9 +173,12 @@ func (b *backend) Attach(ctx context.Context, filepath string, cfg *config.Attac
163173
}),
164174
))
165175
if err != nil {
176+
logrus.Errorf("failed to build model manifest: %v", err)
166177
return fmt.Errorf("failed to build model manifest: %w", err)
167178
}
168179

180+
logrus.Infof("Attched %s to %s successfully", filepath, cfg.Source)
181+
169182
return nil
170183
}
171184

pkg/backend/backend.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ type Backend interface {
6565
Tag(ctx context.Context, source, target string) error
6666

6767
// Nydusify converts the model artifact to nydus format.
68-
Nydusify(ctx context.Context, target string) (string, error)
68+
Nydusify(ctx context.Context, target string, cfg *config.Root) (string, error)
6969
}
7070

7171
// backend is the implementation of Backend.

0 commit comments

Comments
 (0)