@@ -2,11 +2,12 @@ package store
22
33import (
44 "context"
5+ "fmt"
56 "os"
7+ "strings"
68
79 "github.com/google/go-containerregistry/pkg/name"
8- "helm.sh/helm/v3/pkg/action"
9-
10+ ocispec "github.com/opencontainers/image-spec/specs-go/v1"
1011 "hauler.dev/go/hauler/internal/flags"
1112 v1 "hauler.dev/go/hauler/pkg/apis/hauler.cattle.io/v1"
1213 "hauler.dev/go/hauler/pkg/artifacts/file"
@@ -17,6 +18,7 @@ import (
1718 "hauler.dev/go/hauler/pkg/log"
1819 "hauler.dev/go/hauler/pkg/reference"
1920 "hauler.dev/go/hauler/pkg/store"
21+ "helm.sh/helm/v3/pkg/action"
2022)
2123
2224func AddFileCmd (ctx context.Context , o * flags.AddFileOpts , s * store.Layout , reference string ) error {
@@ -57,7 +59,8 @@ func AddImageCmd(ctx context.Context, o *flags.AddImageOpts, s *store.Layout, re
5759 l := log .FromContext (ctx )
5860
5961 cfg := v1.Image {
60- Name : reference ,
62+ Name : reference ,
63+ Rewrite : o .Rewrite ,
6164 }
6265
6366 // Check if the user provided a key.
@@ -78,10 +81,10 @@ func AddImageCmd(ctx context.Context, o *flags.AddImageOpts, s *store.Layout, re
7881 l .Infof ("keyless signature verified for image [%s]" , cfg .Name )
7982 }
8083
81- return storeImage (ctx , s , cfg , o .Platform , rso , ro )
84+ return storeImage (ctx , s , cfg , o .Platform , rso , ro , o . Rewrite )
8285}
8386
84- func storeImage (ctx context.Context , s * store.Layout , i v1.Image , platform string , rso * flags.StoreRootOpts , ro * flags.CliRootOpts ) error {
87+ func storeImage (ctx context.Context , s * store.Layout , i v1.Image , platform string , rso * flags.StoreRootOpts , ro * flags.CliRootOpts , rewrite string ) error {
8588 l := log .FromContext (ctx )
8689
8790 if ! ro .IgnoreErrors {
@@ -104,6 +107,7 @@ func storeImage(ctx context.Context, s *store.Layout, i v1.Image, platform strin
104107 }
105108 }
106109
110+ // copy and sig verification
107111 err = cosign .SaveImage (ctx , s , r .Name (), platform , rso , ro )
108112 if err != nil {
109113 if ro .IgnoreErrors {
@@ -115,21 +119,82 @@ func storeImage(ctx context.Context, s *store.Layout, i v1.Image, platform strin
115119 }
116120 }
117121
122+ if rewrite != "" {
123+ rewrite = strings .TrimPrefix (rewrite , "/" )
124+ if ! strings .Contains (rewrite , ":" ) {
125+ rewrite = strings .Join ([]string {rewrite , r .(name.Tag ).TagStr ()}, ":" )
126+ }
127+ // rename image name in store
128+ newRef , err := name .ParseReference (rewrite )
129+ if err != nil {
130+ l .Errorf ("unable to parse rewrite name: %w" , err )
131+ }
132+ rewriteReference (ctx , s , r , newRef )
133+ }
134+
118135 l .Infof ("successfully added image [%s]" , r .Name ())
119136 return nil
120137}
121138
139+ func rewriteReference (ctx context.Context , s * store.Layout , oldRef name.Reference , newRef name.Reference ) error {
140+ l := log .FromContext (ctx )
141+
142+ l .Infof ("rewriting [%s] to [%s]" , oldRef .Name (), newRef .Name ())
143+
144+ s .OCI .LoadIndex ()
145+
146+ //TODO: improve string manipulation
147+ oldRefContext := oldRef .Context ()
148+ newRefContext := newRef .Context ()
149+
150+ oldRepo := oldRefContext .RepositoryStr ()
151+ newRepo := newRefContext .RepositoryStr ()
152+ oldTag := oldRef .(name.Tag ).TagStr ()
153+ newTag := newRef .(name.Tag ).TagStr ()
154+ oldRegistry := strings .TrimPrefix (oldRefContext .RegistryStr (), "index." )
155+ newRegistry := strings .TrimPrefix (newRefContext .RegistryStr (), "index." )
156+
157+ oldTotal := oldRepo + ":" + oldTag
158+ newTotal := newRepo + ":" + newTag
159+ oldTotalReg := oldRegistry + "/" + oldTotal
160+ newTotalReg := newRegistry + "/" + newTotal
161+
162+ //find and update reference
163+ found := false
164+ if err := s .OCI .Walk (func (k string , d ocispec.Descriptor ) error {
165+ if d .Annotations [ocispec .AnnotationRefName ] == oldTotal && d .Annotations [consts .ContainerdImageNameKey ] == oldTotalReg {
166+ d .Annotations [ocispec .AnnotationRefName ] = newTotal
167+ d .Annotations [consts .ContainerdImageNameKey ] = newTotalReg
168+ found = true
169+ }
170+ return nil
171+ }); err != nil {
172+ return err
173+ }
174+
175+ if ! found {
176+ return fmt .Errorf ("could not find image [%s] in store" , oldRef .Name ())
177+ }
178+
179+ return s .OCI .SaveIndex ()
180+
181+ }
182+
122183func AddChartCmd (ctx context.Context , o * flags.AddChartOpts , s * store.Layout , chartName string ) error {
123184 cfg := v1.Chart {
124185 Name : chartName ,
125186 RepoURL : o .ChartOpts .RepoURL ,
126187 Version : o .ChartOpts .Version ,
127188 }
128189
129- return storeChart (ctx , s , cfg , o .ChartOpts )
190+ rewrite := ""
191+ if o .Rewrite != "" {
192+ rewrite = o .Rewrite
193+ }
194+ return storeChart (ctx , s , cfg , o .ChartOpts , rewrite )
130195}
131196
132- func storeChart (ctx context.Context , s * store.Layout , cfg v1.Chart , opts * action.ChartPathOptions ) error {
197+ func storeChart (ctx context.Context , s * store.Layout , cfg v1.Chart , opts * action.ChartPathOptions , rewrite string ) error {
133198 l := log .FromContext (ctx )
134199
135200 l .Infof ("adding chart [%s] to the store" , cfg .Name )
@@ -152,11 +217,60 @@ func storeChart(ctx context.Context, s *store.Layout, cfg v1.Chart, opts *action
152217 if err != nil {
153218 return err
154219 }
220+
155221 _ , err = s .AddOCI (ctx , chrt , ref .Name ())
156222 if err != nil {
157223 return err
224+ } else {
225+ s .OCI .SaveIndex ()
158226 }
159227
228+ if rewrite != "" {
229+ rewrite = strings .TrimPrefix (rewrite , "/" )
230+ newRef , err := name .ParseReference (rewrite )
231+ if err != nil {
232+ l .Errorf ("unable to parse rewrite name: %w" , err )
233+ }
234+
235+ s .OCI .LoadIndex ()
236+
237+ oldRefContext := ref .Context ()
238+ newRefContext := newRef .Context ()
239+
240+ oldRepo := oldRefContext .RepositoryStr ()
241+ newRepo := newRefContext .RepositoryStr ()
242+ oldTag := ref .(name.Tag ).TagStr ()
243+
244+ var newTag string
245+ if strings .Contains (rewrite , ":" ) {
246+ newTag = newRef .(name.Tag ).TagStr ()
247+ } else {
248+ newTag = oldTag
249+ }
250+
251+ oldTotal := oldRepo + ":" + oldTag
252+ newTotal := newRepo + ":" + newTag
253+
254+ found := false
255+ if err := s .OCI .Walk (func (k string , d ocispec.Descriptor ) error {
256+ if d .Annotations [ocispec .AnnotationRefName ] == oldTotal {
257+ d .Annotations [ocispec .AnnotationRefName ] = newTotal
258+ found = true
259+ }
260+ return nil
261+ }); err != nil {
262+ return err
263+ }
264+
265+ if ! found {
266+ return fmt .Errorf ("could not find chart [%s] in store" , ref .Name ())
267+ }
268+
269+ cfg .Name = newRef .Name ()
270+ fmt .Println ("chart name (new): " , cfg .Name )
271+
272+ s .OCI .SaveIndex ()
273+ }
160274 l .Infof ("successfully added chart [%s]" , ref .Name ())
161275 return nil
162276}
0 commit comments