@@ -4,67 +4,124 @@ Copyright © 2024 Jozu.com
4
4
package models
5
5
6
6
import (
7
+ "context"
8
+ "encoding/json"
7
9
"fmt"
10
+ "io"
11
+ "jmm/pkg/artifact"
12
+ "os"
13
+ "text/tabwriter"
8
14
9
- "github.com/spf13/cobra"
15
+ "github.com/opencontainers/go-digest"
16
+ ocispec "github.com/opencontainers/image-spec/specs-go/v1"
10
17
)
11
18
12
- type ModelsFlags struct {
19
+ const (
20
+ ModelsTableHeader = "DIGEST\t MAINTAINER\t MODEL FORMAT\t SIZE"
21
+ ModelsTableFmt = "%s\t %s\t %s\t %s\t "
22
+ )
23
+
24
+ func listModels (opts * ModelsOptions ) error {
25
+ store := artifact .NewArtifactStore (opts .configHome )
26
+ index , err := store .ParseIndexJson ()
27
+ if err != nil {
28
+ return err
29
+ }
30
+
31
+ manifests , err := manifestsFromIndex (index , store )
32
+ if err != nil {
33
+ return err
34
+ }
35
+
36
+ if err := printManifestsSummary (manifests , store ); err != nil {
37
+ return err
38
+ }
39
+
40
+ return nil
13
41
}
14
- type ModelsOptions struct {
42
+
43
+ func manifestsFromIndex (index * ocispec.Index , store * artifact.Store ) (map [digest.Digest ]ocispec.Manifest , error ) {
44
+ manifests := map [digest.Digest ]ocispec.Manifest {}
45
+ for _ , manifestDesc := range index .Manifests {
46
+ manifestReader , err := store .Storage .Fetch (context .Background (), manifestDesc )
47
+ if err != nil {
48
+ return nil , fmt .Errorf ("failed to get manifest %s: %w" , manifestDesc .Digest , err )
49
+ }
50
+ manifestBytes , err := io .ReadAll (manifestReader )
51
+ if err != nil {
52
+ return nil , fmt .Errorf ("failed to read manifest %s: %w" , manifestDesc .Digest , err )
53
+ }
54
+ manifest := ocispec.Manifest {}
55
+ if err := json .Unmarshal (manifestBytes , & manifest ); err != nil {
56
+ return nil , fmt .Errorf ("failed to parse manifest %s: %w" , manifestDesc .Digest , err )
57
+ }
58
+ manifests [manifestDesc .Digest ] = manifest
59
+ }
60
+ return manifests , nil
15
61
}
16
62
17
- // modelsCmd represents the models command
18
- func NewCmdModels () * cobra.Command {
19
- modelsFlags := NewModelsFlags ()
20
-
21
- cmd := & cobra.Command {
22
- Use : "models" ,
23
- Short : "A brief description of your command" ,
24
- Long : `A longer description that spans multiple lines and likely contains examples
25
- and usage of using your command. For example:
26
-
27
- Cobra is a CLI library for Go that empowers applications.
28
- This application is a tool to generate the needed files
29
- to quickly create a Cobra application.` ,
30
- Run : func (cmd * cobra.Command , args []string ) {
31
- options , err := modelsFlags .ToOptions ()
32
- if err != nil {
33
- fmt .Println (err )
34
- return
35
- }
36
- err = options .Validate ()
37
- if err != nil {
38
- fmt .Println (err )
39
- return
40
- }
41
- options .RunModels ()
42
- if err != nil {
43
- fmt .Println (err )
44
- return
45
- }
46
- },
63
+ func readManifestConfig (manifest * ocispec.Manifest , store * artifact.Store ) (* artifact.JozuFile , error ) {
64
+ configReader , err := store .Storage .Fetch (context .Background (), manifest .Config )
65
+ if err != nil {
66
+ return nil , fmt .Errorf ("failed to get config: %w" , err )
67
+ }
68
+ configBytes , err := io .ReadAll (configReader )
69
+ if err != nil {
70
+ return nil , fmt .Errorf ("failed to read config: %w" , err )
47
71
}
48
- modelsFlags .AddFlags (cmd )
49
- return cmd
72
+ config := & artifact.JozuFile {}
73
+ if err := json .Unmarshal (configBytes , config ); err != nil {
74
+ return nil , fmt .Errorf ("failed to parse config: %w" , err )
75
+ }
76
+ return config , nil
50
77
}
51
78
52
- func NewModelsFlags () * ModelsFlags {
53
- return & ModelsFlags {}
79
+ func printManifestsSummary (manifests map [digest.Digest ]ocispec.Manifest , store * artifact.Store ) error {
80
+ tw := tabwriter .NewWriter (os .Stdout , 0 , 2 , 3 , ' ' , 0 )
81
+ fmt .Fprintln (tw , ModelsTableHeader )
82
+ for digest , manifest := range manifests {
83
+ // TODO: filter this list for manifests we're interested in (build needs to set a manifest mediaType/artifactType)
84
+ line , err := getManifestInfoLine (digest , & manifest , store )
85
+ if err != nil {
86
+ return err
87
+ }
88
+ fmt .Fprintln (tw , line )
89
+ }
90
+ tw .Flush ()
91
+ return nil
54
92
}
55
93
56
- func (f * ModelsFlags ) AddFlags (cmd * cobra.Command ) {
94
+ func getManifestInfoLine (digest digest.Digest , manifest * ocispec.Manifest , store * artifact.Store ) (string , error ) {
95
+ config , err := readManifestConfig (manifest , store )
96
+ if err != nil {
97
+ return "" , err
98
+ }
99
+ var size int64
100
+ for _ , layer := range manifest .Layers {
101
+ size += layer .Size
102
+ }
103
+ sizeStr := formatBytes (size )
57
104
105
+ info := fmt .Sprintf (ModelsTableFmt , digest , config .Maintainer , config .ModelFormat , sizeStr )
106
+ return info , nil
58
107
}
59
108
60
- func (f * ModelsFlags ) ToOptions () (* ModelsOptions , error ) {
61
- return & ModelsOptions {}, nil
62
- }
109
+ func formatBytes (i int64 ) string {
110
+ if i == 0 {
111
+ return "0 B"
112
+ }
63
113
64
- func (o * ModelsOptions ) Validate () error {
65
- return nil
66
- }
114
+ suffixes := []string {"B" , "KiB" , "MiB" , "GiB" , "TiB" , "PiB" }
115
+ unit := float64 (1024 )
67
116
68
- func (o * ModelsOptions ) RunModels () error {
69
- return nil
117
+ size := float64 (i )
118
+ for _ , suffix := range suffixes {
119
+ if size < unit {
120
+ return fmt .Sprintf ("%.1f %s" , size , suffix )
121
+ }
122
+ size = size / unit
123
+ }
124
+
125
+ // Fall back to printing 1000's of PiB
126
+ return fmt .Sprintf ("%.1f PiB" , size )
70
127
}
0 commit comments