Skip to content

Commit 426fea3

Browse files
authored
feat: support nydusify for build and push (#128)
Signed-off-by: chlins <[email protected]>
1 parent 264624f commit 426fea3

File tree

7 files changed

+149
-0
lines changed

7 files changed

+149
-0
lines changed

cmd/build.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ func init() {
5555
flags.BoolVarP(&buildConfig.OutputRemote, "output-remote", "", false, "turning on this flag will output model artifact to remote registry directly")
5656
flags.BoolVarP(&buildConfig.PlainHTTP, "plain-http", "", false, "turning on this flag will use plain HTTP instead of HTTPS")
5757
flags.BoolVarP(&buildConfig.Insecure, "insecure", "", false, "turning on this flag will disable TLS verification")
58+
flags.BoolVar(&buildConfig.Nydusify, "nydusify", false, "[EXPERIMENTAL] nydusify the model artifact")
59+
flags.MarkHidden("nydusify")
5860

5961
if err := viper.BindPFlags(flags); err != nil {
6062
panic(fmt.Errorf("bind cache list flags to viper: %w", err))
@@ -73,5 +75,16 @@ func runBuild(ctx context.Context, workDir string) error {
7375
}
7476

7577
fmt.Printf("Successfully built model artifact: %s\n", buildConfig.Target)
78+
79+
// nydusify the model artifact if needed.
80+
if buildConfig.Nydusify {
81+
nydusName, err := b.Nydusify(ctx, buildConfig.Target)
82+
if err != nil {
83+
return fmt.Errorf("failed to nydusify %s: %w", buildConfig.Target, err)
84+
}
85+
86+
fmt.Printf("Successfully nydusify model artifact: %s\n", nydusName)
87+
}
88+
7689
return nil
7790
}

cmd/push.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ func init() {
5151
flags := pushCmd.Flags()
5252
flags.IntVar(&pushConfig.Concurrency, "concurrency", pushConfig.Concurrency, "specify the number of concurrent push operations")
5353
flags.BoolVar(&pushConfig.PlainHTTP, "plain-http", false, "use plain HTTP instead of HTTPS")
54+
flags.BoolVar(&pushConfig.Nydusify, "nydusify", false, "[EXPERIMENTAL] nydusify the model artifact")
55+
flags.MarkHidden("nydusify")
5456

5557
if err := viper.BindPFlags(flags); err != nil {
5658
panic(fmt.Errorf("bind cache push flags to viper: %w", err))
@@ -69,5 +71,16 @@ func runPush(ctx context.Context, target string) error {
6971
}
7072

7173
fmt.Printf("Successfully pushed model artifact: %s\n", target)
74+
75+
// nydusify the model artifact if needed.
76+
if pushConfig.Nydusify {
77+
nydusName, err := b.Nydusify(ctx, target)
78+
if err != nil {
79+
return fmt.Errorf("failed to nydusify %s: %w", target, err)
80+
}
81+
82+
fmt.Printf("Successfully nydusify model artifact: %s\n", nydusName)
83+
}
84+
7285
return nil
7386
}

pkg/backend/backend.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ type Backend interface {
5757

5858
// Tag creates a new tag that refers to the source model artifact.
5959
Tag(ctx context.Context, source, target string) error
60+
61+
// Nydusify converts the model artifact to nydus format.
62+
Nydusify(ctx context.Context, target string) (string, error)
6063
}
6164

6265
// backend is the implementation of Backend.

pkg/backend/nydusify.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2025 The CNAI Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package backend
18+
19+
import (
20+
"context"
21+
"os/exec"
22+
)
23+
24+
const (
25+
// nydusImageTagSuffix is the suffix for the nydus image tag.
26+
nydusImageTagSuffix = "_nydus_v2"
27+
)
28+
29+
// Nydusify is a function that converts a given model artifact to a nydus image.
30+
func (b *backend) Nydusify(ctx context.Context, source string) (string, error) {
31+
target := source + nydusImageTagSuffix
32+
cmd := exec.CommandContext(
33+
ctx,
34+
"nydusify",
35+
"convert",
36+
"--source-backend-type",
37+
"model-artifact",
38+
"--compressor",
39+
"lz4_block",
40+
"--fs-version",
41+
"5",
42+
"--source",
43+
source,
44+
"--target",
45+
target,
46+
)
47+
48+
if err := cmd.Run(); err != nil {
49+
return "", err
50+
}
51+
52+
return target, nil
53+
}

pkg/config/build.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type Build struct {
3030
OutputRemote bool
3131
PlainHTTP bool
3232
Insecure bool
33+
Nydusify bool
3334
}
3435

3536
func NewBuild() *Build {
@@ -40,6 +41,7 @@ func NewBuild() *Build {
4041
OutputRemote: false,
4142
PlainHTTP: false,
4243
Insecure: false,
44+
Nydusify: false,
4345
}
4446
}
4547

@@ -56,5 +58,11 @@ func (b *Build) Validate() error {
5658
return fmt.Errorf("model file path is required")
5759
}
5860

61+
if b.Nydusify {
62+
if !b.OutputRemote {
63+
return fmt.Errorf("nydusify only works with output remote")
64+
}
65+
}
66+
5967
return nil
6068
}

pkg/config/push.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,14 @@ const (
2626
type Push struct {
2727
Concurrency int
2828
PlainHTTP bool
29+
Nydusify bool
2930
}
3031

3132
func NewPush() *Push {
3233
return &Push{
3334
Concurrency: defaultPushConcurrency,
3435
PlainHTTP: false,
36+
Nydusify: false,
3537
}
3638
}
3739

test/mocks/backend/backend.go

Lines changed: 57 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)