@@ -28,6 +28,7 @@ import (
2828 "github.com/aws/aws-sdk-go/aws/awserr"
2929 "github.com/coreos/coreos-assembler/mantle/platform/api/aws"
3030 "github.com/coreos/stream-metadata-go/release"
31+ "github.com/pkg/errors"
3132 "github.com/spf13/cobra"
3233)
3334
4142
4243 specBucketPrefix string
4344
45+ // This is useful for testing `update-release-index` locally. The command is
46+ // then expected to be run in a cosa workdir with the release metadata and
47+ // release index available, hosted at the same levels they would be in S3. For
48+ // reference:
49+ // ```
50+ // $ tree -L 3
51+ // .
52+ // ├── builds
53+ // │ ├── 40.20241019.3.0
54+ // │ │ ├── aarch64
55+ // │ │ ├── ppc64le
56+ // │ │ ├── release.json
57+ // │ │ ├── s390x
58+ // │ │ └── x86_64
59+ // │ ├── builds.json
60+ // │ └── latest -> 40.20241019.3.0
61+ // ...
62+ // ├── releases.json
63+ // ├── src
64+ // ...
65+ // └── tmp
66+ // ```
67+ releaseIndexLocal bool
68+
4469 cmdMakeAmisPublic = & cobra.Command {
4570 Use : "make-amis-public [options]" ,
4671 Short : "Make the AMIs of a CoreOS release public." ,
@@ -71,6 +96,7 @@ func init() {
7196 cmdUpdateReleaseIndex .Flags ().StringVar (& specRegion , "region" , "us-east-1" , "S3 bucket region" )
7297 cmdUpdateReleaseIndex .Flags ().StringVarP (& specStream , "stream" , "" , "" , "target stream" )
7398 cmdUpdateReleaseIndex .Flags ().StringVarP (& specVersion , "version" , "" , "" , "release version" )
99+ cmdUpdateReleaseIndex .Flags ().BoolVarP (& releaseIndexLocal , "local-mode" , "" , false , "operate on local files" )
74100 root .AddCommand (cmdUpdateReleaseIndex )
75101
76102}
@@ -85,10 +111,10 @@ func validateArgs(args []string) {
85111 if specStream == "" {
86112 plog .Fatal ("--stream is required" )
87113 }
88- if specBucketPrefix == "" {
114+ if specBucketPrefix == "" && ! releaseIndexLocal {
89115 plog .Fatal ("--bucket-prefix is required" )
90116 }
91- if specRegion == "" {
117+ if specRegion == "" && ! releaseIndexLocal {
92118 plog .Fatal ("--region is required" )
93119 }
94120}
@@ -105,8 +131,20 @@ func runMakeAmisPublic(cmd *cobra.Command, args []string) {
105131
106132func runUpdateReleaseIndex (cmd * cobra.Command , args []string ) {
107133 validateArgs (args )
108- api := getAWSApi ()
109- rel := getReleaseMetadata (api )
134+ var api * aws.API
135+ var rel release.Release
136+ if ! releaseIndexLocal {
137+ api = getAWSApi ()
138+ rel = getReleaseMetadata (api )
139+ } else {
140+ localRelease := fmt .Sprintf ("builds/%s/release.json" , specVersion )
141+ if releaseData , err := os .ReadFile (localRelease ); err != nil {
142+ plog .Fatalf ("reading release metadata at %s: %v" , localRelease , err )
143+ } else if err := json .Unmarshal (releaseData , & rel ); err != nil {
144+ plog .Fatalf ("unmarshaling release metadata at %s: %v" , localRelease , err )
145+ }
146+ }
147+
110148 modifyReleaseMetadataIndex (api , rel )
111149}
112150
@@ -209,25 +247,38 @@ func modifyReleaseMetadataIndex(api *aws.API, rel release.Release) {
209247 // version. Plus we need S3 creds anyway later on to push the modified
210248 // release index back.
211249
212- bucket , prefix := getBucketAndStreamPrefix ()
213- path := filepath .Join (prefix , "releases.json" )
214- data , err := func () ([]byte , error ) {
215- f , err := api .DownloadFile (bucket , path )
216- if err != nil {
217- if awsErr , ok := err .(awserr.Error ); ok {
218- if awsErr .Code () == "NoSuchKey" {
219- return []byte ("{}" ), nil
250+ var bucket , prefix , path string
251+ if ! releaseIndexLocal {
252+ bucket , prefix = getBucketAndStreamPrefix ()
253+ path = filepath .Join (prefix , "releases.json" )
254+ } else {
255+ path = "releases.json"
256+ }
257+ var data []byte
258+ var err error
259+ if ! releaseIndexLocal {
260+ data , err = func () ([]byte , error ) {
261+ f , err := api .DownloadFile (bucket , path )
262+ if err != nil {
263+ if awsErr , ok := err .(awserr.Error ); ok {
264+ if awsErr .Code () == "NoSuchKey" {
265+ return []byte ("{}" ), nil
266+ }
220267 }
268+ return []byte {}, fmt .Errorf ("downloading release metadata index: %v" , err )
221269 }
222- return []byte {}, fmt .Errorf ("downloading release metadata index: %v" , err )
223- }
224- defer f .Close ()
225- d , err := io .ReadAll (f )
226- if err != nil {
227- return []byte {}, fmt .Errorf ("reading release metadata index: %v" , err )
270+ defer f .Close ()
271+ d , err := io .ReadAll (f )
272+ if err != nil {
273+ return []byte {}, fmt .Errorf ("reading release metadata index: %v" , err )
274+ }
275+ return d , nil
276+ }()
277+ } else {
278+ if data , err = os .ReadFile (path ); err != nil {
279+ err = errors .Wrapf (err , "reading release metadata index from %s" , path )
228280 }
229- return d , nil
230- }()
281+ }
231282 if err != nil {
232283 plog .Fatal (err )
233284 }
@@ -293,11 +344,17 @@ func modifyReleaseMetadataIndex(api *aws.API, rel release.Release) {
293344 plog .Fatalf ("marshalling release metadata json: %v" , err )
294345 }
295346
296- // we don't want this to be cached for very long so that e.g. Cincinnati picks it up quickly
297- var releases_max_age = 60 * 5
298- err = api .UploadObjectExt (bytes .NewReader (out ), bucket , path , true , "public-read" , aws .ContentTypeJSON , releases_max_age )
299- if err != nil {
300- plog .Fatalf ("uploading release metadata json: %v" , err )
347+ if ! releaseIndexLocal {
348+ // we don't want this to be cached for very long so that e.g. Cincinnati picks it up quickly
349+ var releases_max_age = 60 * 5
350+ err = api .UploadObjectExt (bytes .NewReader (out ), bucket , path , true , "public-read" , aws .ContentTypeJSON , releases_max_age )
351+ if err != nil {
352+ plog .Fatalf ("uploading release metadata json: %v" , err )
353+ }
354+ } else {
355+ if err := os .WriteFile (path , out , 0644 ); err != nil {
356+ plog .Fatalf ("writing release metadata json to %s: %v" , path , err )
357+ }
301358 }
302359}
303360
0 commit comments