Repository: k3s-io/k3s
File: pkg/etcd/s3.go (Go)

Code before:
		// skip metadata
		if path.Base(path.Dir(info.Key)) == metadataDir {
			continue
		}

		snapshotFiles = append(snapshotFiles, info)
	}

	if len(snapshotFiles) <= s.config.EtcdSnapshotRetention {
		return nil, nil
	}

	// sort newest-first so we can prune entries past the retention count
	sort.Slice(snapshotFiles, func(i, j int) bool {
		return snapshotFiles[j].LastModified.Before(snapshotFiles[i].LastModified)
	})

	deleted := []string{}
	for _, df := range snapshotFiles[s.config.EtcdSnapshotRetention:] {
		logrus.Infof("Removing S3 snapshot: s3://%s/%s", s.config.EtcdS3BucketName, df.Key)

		key := path.Base(df.Key)
		if err := s.deleteSnapshot(ctx, key); err != nil {
			return deleted, err
		}
		deleted = append(deleted, df.Key)
	}

	return deleted, nil
}

func (s *S3) deleteSnapshot(ctx context.Context, key string) error {
	ctx, cancel := context.WithTimeout(ctx, s.config.EtcdS3Timeout)
	defer cancel()

	key = path.Join(s.config.EtcdS3Folder, key)
	err := s.client.RemoveObject(ctx, s.config.EtcdS3BucketName, key, minio.RemoveObjectOptions{})
	if err == nil || isNotExist(err) {
		metadataKey := path.Join(path.Dir(key), metadataDir, path.Base(key))
		if merr := s.client.RemoveObject(ctx, s.config.EtcdS3BucketName, metadataKey, minio.RemoveObjectOptions{}); merr != nil && !isNotExist(merr) {
			err = merr
		}
	}

	return err
}

// listSnapshots provides a list of currently stored
// snapshots in S3 along with their relevant
// metadata.
func (s *S3) listSnapshots(ctx context.Context) (map[string]snapshotFile, error) {

Review comment (suggestion):
I think this should this also return just the snapshot name?
```suggestion
		deleted = append(deleted, key)
```

Code after:
		// skip metadata
		if path.Base(path.Dir(info.Key)) == metadataDir {
			continue
		}

		snapshotFiles = append(snapshotFiles, info)
	}

	if len(snapshotFiles) <= s.config.EtcdSnapshotRetention {
		return nil, nil
	}

	// sort newest-first so we can prune entries past the retention count
	sort.Slice(snapshotFiles, func(i, j int) bool {
		return snapshotFiles[j].LastModified.Before(snapshotFiles[i].LastModified)
	})

	deleted := []string{}
	for _, df := range snapshotFiles[s.config.EtcdSnapshotRetention:] {
		logrus.Infof("Removing S3 snapshot: s3://%s/%s", s.config.EtcdS3BucketName, df.Key)

		key := path.Base(df.Key)
		if err := s.deleteSnapshot(ctx, key); err != nil {
			return deleted, err
		}
		deleted = append(deleted, key)
	}

	return deleted, nil
}

func (s *S3) deleteSnapshot(ctx context.Context, key string) error {
	ctx, cancel := context.WithTimeout(ctx, s.config.EtcdS3Timeout)
	defer cancel()

	key = path.Join(s.config.EtcdS3Folder, key)
	err := s.client.RemoveObject(ctx, s.config.EtcdS3BucketName, key, minio.RemoveObjectOptions{})
	if err == nil || isNotExist(err) {
		metadataKey := path.Join(path.Dir(key), metadataDir, path.Base(key))
		if merr := s.client.RemoveObject(ctx, s.config.EtcdS3BucketName, metadataKey, minio.RemoveObjectOptions{}); merr != nil && !isNotExist(merr) {
			err = merr
		}
	}

	return err
}

// listSnapshots provides a list of currently stored
// snapshots in S3 along with their relevant
// metadata.
func (s *S3) listSnapshots(ctx context.Context) (map[string]snapshotFile, error) {