Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Persist file artifacts (#1084)
## Description: <!-- Describe this change, how it works, and the motivation behind it. --> ## Is this change user facing? YES/NO <!-- If yes, please add the "user facing" label to the PR --> <!-- If yes, don't forget to include docs changes where relevant --> ## References (if applicable): <!-- Add relevant Github Issues, Discord threads, or other helpful information. --> --------- Co-authored-by: leoporoli <leandroporoli@gmail.com>
- Loading branch information
1 parent
1a2014d
commit c7b3590
Showing
8 changed files
with
320 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Error: Docker context switch for buildx failed |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
163 changes: 163 additions & 0 deletions
163
...ainer-engine-lib/lib/database_accessors/enclave_db/file_artifacts_db/file_artifacts_db.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
package file_artifacts_db | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/consts" | ||
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db" | ||
"github.com/kurtosis-tech/stacktrace" | ||
bolt "go.etcd.io/bbolt" | ||
) | ||
|
||
type FileArtifactPersisted struct { | ||
enclaveDb *enclave_db.EnclaveDB | ||
data *fileArtifactData | ||
} | ||
|
||
type fileArtifactData struct { | ||
ArtifactNameToArtifactUuid map[string]string | ||
ShortenedUuidToFullUuid map[string][]string | ||
ArtifactContentMd5 map[string][]byte | ||
} | ||
|
||
var ( | ||
fileArtifactBucketName = []byte("file-artifact") | ||
fileArtifactDataStructKey = []byte("file-artifact-data-struct") | ||
) | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) ListFiles() map[string]bool { | ||
artifactNameSet := make(map[string]bool) | ||
for artifactName := range fileArtifactDb.data.ArtifactNameToArtifactUuid { | ||
artifactNameSet[artifactName] = true | ||
} | ||
return artifactNameSet | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) Persist() error { | ||
err := fileArtifactDb.enclaveDb.Update(func(tx *bolt.Tx) error { | ||
jsonData, err := json.Marshal(fileArtifactDb.data) | ||
if err != nil { | ||
return stacktrace.Propagate(err, "An error occurred marshalling data '%v'", fileArtifactDb.data) | ||
} | ||
return tx.Bucket(fileArtifactBucketName).Put(fileArtifactDataStructKey, jsonData) | ||
}) | ||
if err != nil { | ||
return stacktrace.Propagate(err, "An error occurred during file artifact db update") | ||
} | ||
return nil | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) SetArtifactUuid(artifactName string, artifactUuid string) { | ||
fileArtifactDb.data.ArtifactNameToArtifactUuid[artifactName] = artifactUuid | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) GetArtifactUuid(artifactName string) (string, bool) { | ||
value, found := fileArtifactDb.data.ArtifactNameToArtifactUuid[artifactName] | ||
return value, found | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) GetArtifactUuidMap() map[string]string { | ||
return fileArtifactDb.data.ArtifactNameToArtifactUuid | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) DeleteArtifactUuid(artifactName string) { | ||
delete(fileArtifactDb.data.ArtifactNameToArtifactUuid, artifactName) | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) SetFullUuid(shortenedUuid string, fullUuid []string) { | ||
fileArtifactDb.data.ShortenedUuidToFullUuid[shortenedUuid] = fullUuid | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) GetFullUuid(shortenedUuid string) ([]string, bool) { | ||
value, found := fileArtifactDb.data.ShortenedUuidToFullUuid[shortenedUuid] | ||
return value, found | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) GetFullUuidMap() map[string][]string { | ||
return fileArtifactDb.data.ShortenedUuidToFullUuid | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) DeleteFullUuid(shortenedUuid string) { | ||
delete(fileArtifactDb.data.ShortenedUuidToFullUuid, shortenedUuid) | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) DeleteFullUuidIndex(shortenedUuid string, targetArtifactIdx int) { | ||
artifactUuids := fileArtifactDb.data.ShortenedUuidToFullUuid[shortenedUuid] | ||
fileArtifactDb.data.ShortenedUuidToFullUuid[shortenedUuid] = append(artifactUuids[0:targetArtifactIdx], artifactUuids[targetArtifactIdx+1:]...) | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) SetContentMd5(artifactName string, md5 []byte) { | ||
fileArtifactDb.data.ArtifactContentMd5[artifactName] = md5 | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) GetContentMd5(artifactName string) ([]byte, bool) { | ||
value, found := fileArtifactDb.data.ArtifactContentMd5[artifactName] | ||
return value, found | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) GetContentMd5Map() map[string][]byte { | ||
return fileArtifactDb.data.ArtifactContentMd5 | ||
} | ||
|
||
func (fileArtifactDb *FileArtifactPersisted) DeleteContentMd5(artifactName string) { | ||
delete(fileArtifactDb.data.ArtifactContentMd5, artifactName) | ||
} | ||
|
||
func GetOrCreateNewFileArtifactsDb() (*FileArtifactPersisted, error) { | ||
data := fileArtifactData{ | ||
map[string]string{}, | ||
map[string][]string{}, | ||
map[string][]byte{}, | ||
} | ||
db, err := enclave_db.GetOrCreateEnclaveDatabase() | ||
if err != nil { | ||
return nil, stacktrace.Propagate(err, "Failed to get enclave database") | ||
} | ||
fileArtifactPersisted, err := getFileArtifactsDbFromEnclaveDb(db, &data) | ||
if err != nil { | ||
return nil, stacktrace.Propagate(err, "Failed to hydrate pre-existing file artifacts") | ||
} | ||
return fileArtifactPersisted, nil | ||
} | ||
|
||
func getFileArtifactsDbFromEnclaveDb(db *enclave_db.EnclaveDB, data *fileArtifactData) (*FileArtifactPersisted, error) { | ||
err := db.Update(func(tx *bolt.Tx) error { | ||
bucket, bucketErr := tx.CreateBucket(fileArtifactBucketName) | ||
// New bucket was created | ||
if errors.Is(bucketErr, bolt.ErrBucketExists) { | ||
content := tx.Bucket(fileArtifactBucketName).Get(fileArtifactDataStructKey) | ||
if err := json.Unmarshal(content, data); err != nil { | ||
return stacktrace.Propagate(err, "An error occurred restoring previous file artifact db state from '%v'", content) | ||
} | ||
return nil | ||
} | ||
// No need to create new bucket | ||
if bucketErr == nil { | ||
if err := bucket.Put(fileArtifactDataStructKey, consts.EmptyValueForJsonSet); err != nil { | ||
return stacktrace.Propagate(err, "An error occurred while creating updating artifact bucket o '%v'", consts.EmptyValueForJsonSet) | ||
} | ||
return nil | ||
} | ||
// Unexpected error | ||
return stacktrace.Propagate(bucketErr, "An error occurred while creating file artifact bucket") | ||
}) | ||
if err == nil { | ||
return &FileArtifactPersisted{ | ||
db, | ||
data, | ||
}, nil | ||
} | ||
return nil, stacktrace.Propagate(err, "An error occurred while getting file artifact db") | ||
} | ||
|
||
func GetFileArtifactsDbForTesting(db *enclave_db.EnclaveDB, nameToUuid map[string]string) (*FileArtifactPersisted, error) { | ||
fileArtifactPersisted, err := getFileArtifactsDbFromEnclaveDb(db, &fileArtifactData{ | ||
nameToUuid, | ||
map[string][]string{}, | ||
map[string][]byte{}, | ||
}) | ||
if err != nil { | ||
return nil, stacktrace.Propagate(err, "Failed to hydrate pre-existing file artifacts") | ||
} | ||
return fileArtifactPersisted, nil | ||
} |
31 changes: 31 additions & 0 deletions
31
...-engine-lib/lib/database_accessors/enclave_db/file_artifacts_db/file_artifacts_db_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package file_artifacts_db | ||
|
||
import ( | ||
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/test_helpers" | ||
"github.com/stretchr/testify/require" | ||
"testing" | ||
) | ||
|
||
func TestFileArtifactPersistance(t *testing.T) { | ||
enclaveDb, cleaningFunction, err := test_helpers.CreateEnclaveDbForTesting() | ||
require.Nil(t, err) | ||
defer cleaningFunction() | ||
fileArtifactDb, err := GetFileArtifactsDbForTesting(enclaveDb, map[string]string{}) | ||
require.Nil(t, err) | ||
require.Empty(t, fileArtifactDb.data.ArtifactNameToArtifactUuid) | ||
require.Empty(t, fileArtifactDb.data.ArtifactContentMd5) | ||
require.Empty(t, fileArtifactDb.data.ShortenedUuidToFullUuid) | ||
fileArtifactDb.SetArtifactUuid("1", "1") | ||
fileArtifactDb.SetContentMd5("1", []byte("1")) | ||
fileArtifactDb.SetFullUuid("1", []string{"1"}) | ||
require.Nil(t, fileArtifactDb.Persist()) | ||
fileArtifactDb, err = getFileArtifactsDbFromEnclaveDb(enclaveDb, &fileArtifactData{ | ||
map[string]string{}, | ||
map[string][]string{}, | ||
map[string][]byte{}, | ||
}) | ||
require.Nil(t, err) | ||
require.Len(t, fileArtifactDb.GetArtifactUuidMap(), 1) | ||
require.Len(t, fileArtifactDb.GetFullUuidMap(), 1) | ||
require.Len(t, fileArtifactDb.GetContentMd5Map(), 1) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.