Skip to content

Commit 045d16a

Browse files
committed
docs(snapshot s3): trim code comments to what the code does not say
Keep each comment to the one fact a reader could not get from the code, stated once, where it applies. Several facts were repeated across files: that S3 returns a stored checksum only when asked appeared four times, that unusable checksums are collected rather than fatal three, and that the shared pipeline keeps the sources from disagreeing three. Each now lives in one place -- the interface, the error type and the digest source respectively -- and the copies are gone. Test comments that restated their own assertions or case names are dropped, and the rest are cut to their load-bearing sentence. Godoc on exported identifiers stays. No code changes; gofmt re-aligned two structs whose field comments were removed.
1 parent 21721c6 commit 045d16a

8 files changed

Lines changed: 68 additions & 150 deletions

File tree

‎cmd/kosli/snapshotS3.go‎

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ kosli snapshot s3 yourEnvironmentName \
8484
--org yourOrgName
8585
`
8686

87-
// fingerprint sources accepted by --fingerprint-source
8887
const (
8988
fingerprintSourceContent = "content"
9089
fingerprintSourceMetadata = "metadata"
@@ -138,6 +137,7 @@ func newSnapshotS3Cmd(out io.Writer) *cobra.Command {
138137
o.fingerprintSource, validS3FingerprintSources))
139138
}
140139

140+
// Changed covers env vars and config too: bindFlags applies them with Flags().Set.
141141
return o.resolveDownloadLimits(cmd.Flags().Changed("download-concurrency"))
142142
},
143143
RunE: func(cmd *cobra.Command, args []string) error {
@@ -207,10 +207,6 @@ func (o *snapshotS3Options) run(args []string) error {
207207
// spells it; a test keeps the two equal.
208208
const defaultDownloadBudget = "512M"
209209

210-
// resolveDownloadLimits validates the download flags into o.downloadLimits.
211-
// concurrencySet reports whether --download-concurrency was given by flag,
212-
// environment or config file; bindFlags applies the latter two through
213-
// Flags().Set, so all three mark the flag changed.
214210
func (o *snapshotS3Options) resolveDownloadLimits(concurrencySet bool) error {
215211
if o.downloadConcurrency < 1 {
216212
return fmt.Errorf("--download-concurrency must be at least 1, got %d", o.downloadConcurrency)
@@ -220,8 +216,6 @@ func (o *snapshotS3Options) resolveDownloadLimits(concurrencySet bool) error {
220216
return fmt.Errorf("invalid --download-budget: %w", err)
221217
}
222218
concurrency := o.downloadConcurrency
223-
// The flag's default is sized for download buffers, which reading stored
224-
// checksums does not use.
225219
if o.fingerprintSource == fingerprintSourceMetadata && !concurrencySet {
226220
concurrency = aws.DefaultMetadataConcurrency
227221
}

‎cmd/kosli/snapshotS3Limits_test.go‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ import (
88
"github.com/stretchr/testify/require"
99
)
1010

11-
// The download defaults are sized for download buffers and temp disk, which a
12-
// source that reads stored checksums never uses, so metadata mode takes its own
13-
// concurrency default. An explicit --download-concurrency, from the flag, the
14-
// environment or the config file, still decides in either mode.
1511
func TestResolveDownloadLimitsPicksTheConcurrencyForTheSource(t *testing.T) {
1612
for _, tc := range []struct {
1713
name string
@@ -44,8 +40,7 @@ func TestDefaultMetadataConcurrencyIsWiderThanTheDownloadDefault(t *testing.T) {
4440
"a source that holds no buffers should not be throttled below the download default")
4541
}
4642

47-
// cobra prints only the flag's own default, so the metadata default is spelt
48-
// out in the help text, and has to keep matching the constant.
43+
// cobra shows only the flag's own default, so the help text spells out the metadata one.
4944
func TestDownloadConcurrencyHelpStatesTheMetadataDefault(t *testing.T) {
5045
require.Contains(t, downloadConcurrencyFlag, fmt.Sprintf("defaults to %d", aws.DefaultMetadataConcurrency))
5146
}

‎cmd/kosli/snapshotS3_test.go‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ func (suite *SnapshotS3TestSuite) SetupTest() {
4040
"README.md": []byte("# kosli cli public\n"),
4141
"dummy/dummy_2/template.yml": []byte("key: value\n"),
4242
}
43-
// Only README.md carries a stored checksum, so the metadata cases cover both
44-
// an object that can be fingerprinted from metadata and one that cannot.
43+
// Only README.md has a stored checksum, so the metadata cases can cover both outcomes.
4544
readmeSum := sha256.Sum256(objects["README.md"])
4645
aws.NewS3ClientFunc = func(_ *aws.AWSStaticCreds) (aws.S3API, error) {
4746
return &aws.FakeS3Client{

‎internal/aws/aws.go‎

Lines changed: 27 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,9 @@ type S3DownloadAPI interface {
151151
DownloadObject(ctx context.Context, params *transfermanager.DownloadObjectInput, optFns ...func(*transfermanager.Options)) (*transfermanager.DownloadObjectOutput, error)
152152
}
153153

154-
// S3HeadAPI reads an object's metadata without reading the object itself,
155-
// including the checksum S3 stores for it. The real *s3.Client satisfies this
156-
// implicitly.
157-
//
158-
// The stored checksum is only returned when the request sets ChecksumMode to
159-
// ChecksumModeEnabled.
154+
// S3HeadAPI reads an object's metadata, including the checksum S3 stores for
155+
// it, which is returned only when the request sets ChecksumMode to
156+
// ChecksumModeEnabled. The real *s3.Client satisfies this implicitly.
160157
type S3HeadAPI interface {
161158
HeadObject(ctx context.Context, params *s3.HeadObjectInput, optFns ...func(*s3.Options)) (*s3.HeadObjectOutput, error)
162159
}
@@ -400,9 +397,8 @@ func formatLambdaLastModified(lastModified string) (time.Time, error) {
400397
return time.Parse(layout, lastModified)
401398
}
402399

403-
// decodeBase64Sha256 converts a Base64-encoded SHA256 digest into the hex form
404-
// Kosli fingerprints use. AWS reports stored digests in Base64: Lambda's
405-
// CodeSha256 and an S3 object's checksum both arrive this way.
400+
// decodeBase64Sha256 converts a Base64 SHA256 digest, the form AWS reports
401+
// stored digests in, into the hex form Kosli fingerprints use.
406402
func decodeBase64Sha256(fingerprint string) (string, error) {
407403
sha256base64, err := base64.StdEncoding.DecodeString(fingerprint)
408404
if err != nil {
@@ -479,8 +475,7 @@ func getS3DataFromClient(client S3API, bucket string, includePaths, includeRegex
479475
}
480476

481477
// getS3DataWithSource lists and filters the bucket, then fingerprints what is
482-
// left with digests from source. Everything but the digest source is shared, so
483-
// the sources cannot disagree on which objects a snapshot covers.
478+
// left with digests from source.
484479
func getS3DataWithSource(client S3API, source s3DigestSource, bucket string, includePaths, includeRegex, excludePaths, excludeRegex []string, limits DownloadLimits, logger *logger.Logger) ([]*S3Data, error) {
485480
s3Data := []*S3Data{}
486481

@@ -545,12 +540,10 @@ type DownloadLimits struct {
545540
// Lambda's default /tmp, and part buffers near 320 MiB of memory.
546541
var DefaultDownloadLimits = DownloadLimits{Concurrency: 8, BytesInFlight: 512 << 20}
547542

548-
// DefaultMetadataConcurrency is how many checksum reads run at once when a
549-
// bucket is fingerprinted from S3 metadata. A HeadObject holds no part buffers
550-
// and no temp disk, so the download default says nothing about it. At a 30 ms
551-
// round trip, 32 in flight is around a thousand objects a second: a million in
552-
// under twenty minutes, and still well under the 5,500 reads a second S3
553-
// supports per prefix. The adaptive retryer absorbs throttling beyond that.
543+
// DefaultMetadataConcurrency is how many checksum reads run at once when
544+
// fingerprinting from S3 metadata. A HeadObject holds no part buffers or temp
545+
// disk, so it is sized against S3's request rate instead: 32 at a 30 ms round
546+
// trip is about 1,000 reads a second, well under the 5,500 S3 allows per prefix.
554547
const DefaultMetadataConcurrency = 32
555548

556549
// listMatchingS3Objects lists the bucket, dropping folder markers and keys the
@@ -602,18 +595,15 @@ func listMatchingS3Objects(client S3ListAPI, bucket string, includePaths []strin
602595
return objects, nil
603596
}
604597

605-
// s3DigestSource is where the fingerprint pipeline gets each object's content
606-
// sha256 once the tree is known. Content mode downloads the object into the
607-
// pipeline's temp dir and hashes it; a source that reads S3's stored checksum
608-
// never touches the disk. Everything else -- key rule, .kosli_ignore, the tree
609-
// walk -- is shared, so the two sources cannot fingerprint the same bucket
610-
// differently.
598+
// s3DigestSource supplies each object's content sha256 to the fingerprint
599+
// pipeline. It is the only part that varies by source, so two sources cannot
600+
// fingerprint the same bucket differently.
611601
type s3DigestSource struct {
612-
// sha256 returns the hex digest of one object's content. tempDir is scratch
613-
// space the pipeline owns and removes when it is done.
602+
// sha256 returns the hex digest of an object's content. tempDir is scratch
603+
// space the pipeline removes afterwards.
614604
sha256 func(ctx context.Context, tempDir string, object s3Object) (string, error)
615-
// usesDisk reports whether an object's listed size occupies temp disk while
616-
// sha256 runs, and so counts against DownloadLimits.BytesInFlight.
605+
// usesDisk means an object's listed size occupies temp disk while sha256
606+
// runs, so it counts against DownloadLimits.BytesInFlight.
617607
usesDisk bool
618608
}
619609

@@ -627,24 +617,19 @@ func downloadDigests(downloader S3DownloadAPI, bucket string, logger *logger.Log
627617
}
628618
}
629619

630-
// fingerprintS3Objects fingerprints the objects as the directory their keys
631-
// describe, downloading each one to an anonymous temp file, hashing it and
632-
// removing it. See fingerprintS3Tree for the pipeline.
620+
// fingerprintS3Objects fingerprints the objects with the download source.
633621
func fingerprintS3Objects(downloader S3DownloadAPI, bucket string, objects []s3Object, limits DownloadLimits, logger *logger.Logger) (string, string, error) {
634622
return fingerprintS3Tree(downloader, downloadDigests(downloader, bucket, logger), bucket, objects, limits, logger)
635623
}
636624

637625
// fingerprintS3Tree fingerprints the objects as the directory their keys
638-
// describe, without ever using a key as a local file name. Each object's
639-
// content sha256 comes from source; the fingerprint is then computed from the
640-
// (key, sha256) pairs by digest.VirtualDirSha256, which reproduces what
641-
// digest.DirSha256 gives the same tree on disk. A single object is
642-
// fingerprinted as that file and named after it, as before.
626+
// describe, without using a key as a local file name: digest.VirtualDirSha256
627+
// combines the (key, sha256) pairs from source exactly as digest.DirSha256
628+
// would on disk. A single object is fingerprinted as that file and named
629+
// after it.
643630
//
644-
// A root .kosli_ignore is always downloaded first, whatever the source, because
645-
// its rules decide which other objects take part; objects the rules exclude are
646-
// not fetched at all. The remaining objects are fetched in parallel within
647-
// limits, and the first failure cancels the rest.
631+
// The root .kosli_ignore is always downloaded, whatever the source, because its
632+
// rules decide which other objects are fetched at all.
648633
func fingerprintS3Tree(downloader S3DownloadAPI, source s3DigestSource, bucket string, objects []s3Object, limits DownloadLimits, logger *logger.Logger) (string, string, error) {
649634
keys := make([]string, len(objects))
650635
for i, object := range objects {
@@ -675,8 +660,7 @@ func fingerprintS3Tree(downloader S3DownloadAPI, source s3DigestSource, bucket s
675660
// when the objects were laid out on disk.
676661
if file, ok := digest.SingleVirtualFile(files); ok {
677662
fetch := source
678-
// The root ignore file is always downloaded, so no source ever asks it
679-
// for a checksum -- even alone, when its rules have nothing to decide.
663+
// The ignore file is downloaded even when alone, so no source needs its checksum.
680664
if file.Path == digest.IgnoreFileName {
681665
fetch = downloadDigests(downloader, bucket, logger)
682666
}
@@ -755,9 +739,8 @@ func ignoreRuleError(err error) error {
755739
// source and writes each into files at the same index. A fixed worker pool
756740
// bounds fetches and goroutines alike, a weighted semaphore bounds the listed
757741
// bytes of sources that use the disk, and the first transport error cancels the
758-
// context so nothing further starts. An unusableChecksumError is about one
759-
// object rather than the connection, so those are collected and reported
760-
// together once the rest have run.
742+
// context so nothing further starts. unusableChecksumErrors are collected
743+
// and reported together instead.
761744
func fetchS3DigestsInParallel(source s3DigestSource, tempDir string, objects []s3Object, indexes []int,
762745
files []digest.VirtualFile, limits DownloadLimits, logger *logger.Logger) error {
763746
ctx, cancel := context.WithCancel(context.Background())
@@ -786,7 +769,6 @@ func fetchS3DigestsInParallel(source s3DigestSource, tempDir string, objects []s
786769
for i := range work {
787770
object := objects[i]
788771
// An object larger than the budget takes all of it and so runs alone.
789-
// A source that never touches the disk owes the budget nothing.
790772
var weight int64
791773
if source.usesDisk {
792774
weight = max(min(object.size, limits.BytesInFlight), 1)

‎internal/aws/fake_s3.go‎

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,10 @@ import (
1818
var fakeS3LastModified = time.Date(2024, 1, 15, 10, 30, 0, 0, time.UTC)
1919

2020
// FakeS3Checksum is the additional checksum S3 has stored for an object.
21-
// Objects uploaded without an explicit checksum algorithm have none, which is
22-
// why FakeS3Client.Checksums is keyed sparsely rather than derived from content.
2321
type FakeS3Checksum struct {
24-
// SHA256 is Base64-encoded, as S3 returns it. A composite (multipart)
25-
// checksum carries a "-N" part-count suffix and is a hash of the part
26-
// hashes, not of the object content.
22+
// SHA256 is Base64, as S3 returns it; a composite one ends in a "-N" part count.
2723
SHA256 string
28-
// Type is COMPOSITE for multipart uploads and FULL_OBJECT for whole-object
29-
// checksums.
30-
Type s3Types.ChecksumType
24+
Type s3Types.ChecksumType
3125
}
3226

3327
// FakeS3Client is an in-memory implementation of S3API for testing.
@@ -46,9 +40,8 @@ type FakeS3Client struct {
4640
// NoLastModified lists keys whose listing entry carries no LastModified at
4741
// all, as some S3-compatible stores return.
4842
NoLastModified map[string]bool
49-
// Checksums maps object key to the additional checksum S3 has stored for
50-
// it. A key with no entry has no additional checksum, as objects uploaded
51-
// without --checksum-algorithm do, and HeadObject returns none for it.
43+
// Checksums maps object key to its stored checksum. A key with no entry has
44+
// none, like an object uploaded without --checksum-algorithm.
5245
Checksums map[string]FakeS3Checksum
5346
// PageSize controls how many objects are returned per ListObjectsV2 call.
5447
// Defaults to 1000 (matching the AWS default) if zero.
@@ -183,8 +176,8 @@ func (f *FakeS3Client) HeadObject(_ context.Context, params *s3.HeadObjectInput,
183176
LastModified: aws.Time(f.lastModified(*params.Key)),
184177
}
185178

186-
// S3 only returns a stored checksum when the request asks for it. Returning
187-
// it unconditionally would hide a caller that forgets to set ChecksumMode.
179+
// Withhold the checksum unless asked, as S3 does, so a caller that forgets
180+
// ChecksumMode fails here too.
188181
if params.ChecksumMode != s3Types.ChecksumModeEnabled {
189182
return out, nil
190183
}

‎internal/aws/s3_contract_test.go‎

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ import (
2121
// errInjected is the error tests inject into FakeS3Client to exercise error paths.
2222
var errInjected = errors.New("injected error")
2323

24-
// base64Sha256 returns the Base64-encoded SHA256 of content, the form S3
25-
// reports a stored full-object checksum in.
24+
// base64Sha256 is content's SHA256 in the Base64 form S3 reports checksums in.
2625
func base64Sha256(content []byte) string {
2726
sum := sha256.Sum256(content)
2827
return base64.StdEncoding.EncodeToString(sum[:])
@@ -37,9 +36,9 @@ func base64Sha256(content []byte) string {
3736
//
3837
// bucket must name a bucket the client can see, holding at least two objects.
3938
// existingKey must name an object in that bucket with a non-empty body.
40-
// sha256ChecksumKey must name an object stored with an SHA256 checksum, or be
41-
// empty to skip the checksum sub-tests -- kosli-cli-public holds no such object
42-
// yet, and adding one would change the golden fingerprints TestGetS3Data pins.
39+
// sha256ChecksumKey names an object with a stored SHA256 checksum, or is empty
40+
// to skip those sub-tests: kosli-cli-public has none, and adding one would move
41+
// the fingerprints TestGetS3Data pins.
4342
func runS3ContractTests(t *testing.T, client S3API, bucket, existingKey, sha256ChecksumKey string) {
4443
t.Helper()
4544

@@ -169,8 +168,6 @@ func runS3ContractTests(t *testing.T, client S3API, bucket, existingKey, sha256C
169168
if sha256ChecksumKey == "" {
170169
t.Skip("no object with an SHA256 checksum available in this bucket")
171170
}
172-
// S3 only returns stored checksums when asked. A fake that always
173-
// returned them would hide a caller that forgets to set ChecksumMode.
174171
out, err := client.HeadObject(context.TODO(), &s3.HeadObjectInput{
175172
Bucket: aws.String(bucket),
176173
Key: aws.String(sha256ChecksumKey),
@@ -192,9 +189,6 @@ func runS3ContractTests(t *testing.T, client S3API, bucket, existingKey, sha256C
192189
require.NoError(t, err)
193190
require.NotNil(t, out.ChecksumSHA256, "ChecksumSHA256 should be present")
194191
require.NotEmpty(t, *out.ChecksumSHA256)
195-
// A full-object checksum is plain Base64. A composite (multipart) one
196-
// carries a "-N" part-count suffix, which is how both this codebase and
197-
// the SDK's own response validation tell them apart.
198192
require.NotContains(t, *out.ChecksumSHA256, "-",
199193
"a single-part upload should carry a full-object checksum")
200194
require.Equal(t, s3Types.ChecksumTypeFullObject, out.ChecksumType)

0 commit comments

Comments
 (0)