Skip to content

Commit 2bf148d

Browse files
jlebondustymabe
authored andcommitted
plume/release: support running update-release-index locally
Currently, that function operates directly on an S3 bucket. This makes it harder to test locally. Add a new `--local-mode` option in which we expect to be in a cosa workdir with release metadata present and a release index. This is mostly peppering conditionals in the code. Patch best viewed with whitespace ignored.
1 parent 21802b6 commit 2bf148d

File tree

1 file changed

+82
-25
lines changed

1 file changed

+82
-25
lines changed

mantle/cmd/plume/release.go

Lines changed: 82 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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

@@ -41,6 +42,30 @@ var (
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

106132
func 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

Comments
 (0)