fleet/server/datastore/s3/bootstrap_package_test.go
Lucas Manuel Rodriguez 404f0d3ac0
Migrate from aws-sdk-go v1 to v2 (#30308)
#29482

[Migrate to the AWS SDK for Go
v2](https://docs.aws.amazon.com/sdk-for-go/v2/developer-guide/migrate-gosdk.html)
documents how to migrate codebases.

QA on features that use AWS SDK Go:
- Bootstrap package:
  - upload:  
  - download: 
  - cleanup: 
- Software (upload, download, installation, etc.) 
  - Cloudfront: Luckly, this feature was already using aws-sdk-go-v2.
- Carves 
- Logging:
	- Firehose 
	- Kinesis 
- Lambda  (tested result logs to a lambda function on our AWS Dogfood
account)
- Email:
	- Amazon SES TODO ⚠️ (this is what Dogfood uses and a few customers)
- We cannot easily test locally, we can use dogfood or load testing
(AWS) environments.

---

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
- [ ] Manual QA for all new/changed functionality
2025-06-30 17:45:39 -03:00

149 lines
3.8 KiB
Go

package s3
import (
"bytes"
"context"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"path"
"testing"
"time"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
)
func TestBootstrapPackage(t *testing.T) {
ctx := context.Background()
store := SetupTestBootstrapPackageStore(t, "bootstrap-packages-unit-test", "prefix")
// get a non-existing package
blob, length, err := store.Get(ctx, "no-such-package")
require.Error(t, err)
require.True(t, fleet.IsNotFound(err))
require.Nil(t, blob)
require.Zero(t, length)
exists, err := store.Exists(ctx, "no-such-package")
require.NoError(t, err)
require.False(t, exists)
createPackageAndHash := func() ([]byte, string) {
b := make([]byte, 1024)
_, err = rand.Read(b)
require.NoError(t, err)
h := sha256.New()
_, err = h.Write(b)
require.NoError(t, err)
fileID := hex.EncodeToString(h.Sum(nil))
return b, fileID
}
getAndCheck := func(fileID string, expected []byte) {
rc, sz, err := store.Get(ctx, fileID)
require.NoError(t, err)
require.EqualValues(t, len(expected), sz)
defer rc.Close()
got, err := io.ReadAll(rc)
require.NoError(t, err)
require.Equal(t, expected, got)
exists, err := store.Exists(ctx, fileID)
require.NoError(t, err)
require.True(t, exists)
}
// store a package
b0, id0 := createPackageAndHash()
err = store.Put(ctx, id0, bytes.NewReader(b0))
require.NoError(t, err)
// read it back, it should match
getAndCheck(id0, b0)
// store another one
b1, id1 := createPackageAndHash()
err = store.Put(ctx, id1, bytes.NewReader(b1))
require.NoError(t, err)
// read it back, it should match
getAndCheck(id1, b1)
// replace the first one
err = store.Put(ctx, id0, bytes.NewReader(b0))
require.NoError(t, err)
// read it back, it should still match
getAndCheck(id0, b0)
}
func TestBootstrapPackageCleanup(t *testing.T) {
ctx := context.Background()
store := SetupTestBootstrapPackageStore(t, "bootstrap-packages-unit-test", "prefix")
assertExisting := func(want []string) {
prefix := path.Join(store.prefix, bootstrapPackagePrefix)
page, err := store.s3Client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{
Bucket: &store.bucket,
Prefix: &prefix,
})
require.NoError(t, err)
got := make([]string, 0, len(page.Contents))
for _, item := range page.Contents {
got = append(got, path.Base(*item.Key))
}
require.ElementsMatch(t, want, got)
}
// cleanup an empty store
n, err := store.Cleanup(ctx, nil, time.Now())
require.NoError(t, err)
require.Equal(t, 0, n)
// put a package
ins0 := uuid.NewString()
err = store.Put(ctx, ins0, bytes.NewReader([]byte("package0")))
require.NoError(t, err)
// cleanup but mark it as used
n, err = store.Cleanup(ctx, []string{ins0}, time.Now())
require.NoError(t, err)
require.Equal(t, 0, n)
assertExisting([]string{ins0})
// cleanup but mark it as unused
n, err = store.Cleanup(ctx, []string{}, time.Now())
require.NoError(t, err)
require.Equal(t, 1, n)
assertExisting(nil)
// put a few packages
packages := []string{uuid.NewString(), uuid.NewString(), uuid.NewString(), uuid.NewString()}
for i, ins := range packages {
err = store.Put(ctx, ins, bytes.NewReader([]byte("package"+fmt.Sprint(i))))
require.NoError(t, err)
}
// cleanup with a time in the past, nothing gets removed
n, err = store.Cleanup(ctx, []string{}, time.Now().Add(-time.Minute))
require.NoError(t, err)
require.Equal(t, 0, n)
assertExisting([]string{packages[0], packages[1], packages[2], packages[3]})
// cleanup in the future, all unused get removed
n, err = store.Cleanup(ctx, []string{packages[0], packages[2]}, time.Now().Add(time.Minute))
require.NoError(t, err)
require.Equal(t, 2, n)
assertExisting([]string{packages[0], packages[2]})
}