diff --git a/core/server/api_container/main.go b/core/server/api_container/main.go index 0f3c383a4d..da5560488e 100644 --- a/core/server/api_container/main.go +++ b/core/server/api_container/main.go @@ -162,7 +162,11 @@ func runMain() error { return stacktrace.Propagate(err, "An error occurred creating the service network") } - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + if err != nil { + return stacktrace.Propagate(err, "An error occurred creating the runtime value store") + } + // TODO: Consolidate Interpreter, Validator and Executor into a single interface startosisRunner := startosis_engine.NewStartosisRunner( startosis_engine.NewStartosisInterpreter(serviceNetwork, gitPackageContentProvider, runtimeValueStore, serverArgs.EnclaveEnvVars), diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service.go index 27e23ab1e2..8683dea56d 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service.go @@ -152,7 +152,9 @@ func (builtin *AddServiceCapabilities) Execute(ctx context.Context, _ *builtin_a return "", stacktrace.Propagate(err, "An error occurred while checking if service '%v' is ready", replacedServiceName) } - fillAddServiceReturnValueWithRuntimeValues(startedService, builtin.resultUuid, builtin.runtimeValueStore) + if err := fillAddServiceReturnValueWithRuntimeValues(startedService, builtin.resultUuid, builtin.runtimeValueStore); err != nil { + return "", stacktrace.Propagate(err, "An error occurred while adding service return values with result key UUID '%s'", builtin.resultUuid) + } instructionResult := fmt.Sprintf("Service '%s' added with service UUID '%s'", replacedServiceName, startedService.GetRegistration().GetUUID()) return instructionResult, nil } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service_shared.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service_shared.go index 4887b6656a..d6fb1510b7 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service_shared.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service_shared.go @@ -24,11 +24,14 @@ const ( hostnameRuntimeValue = "hostname" ) -func fillAddServiceReturnValueWithRuntimeValues(service *service.Service, resultUuid string, runtimeValueStore *runtime_value_store.RuntimeValueStore) { - runtimeValueStore.SetValue(resultUuid, map[string]starlark.Comparable{ +func fillAddServiceReturnValueWithRuntimeValues(service *service.Service, resultUuid string, runtimeValueStore *runtime_value_store.RuntimeValueStore) error { + if err := runtimeValueStore.SetValue(resultUuid, map[string]starlark.Comparable{ ipAddressRuntimeValue: starlark.String(service.GetRegistration().GetPrivateIP().String()), hostnameRuntimeValue: starlark.String(service.GetRegistration().GetHostname()), - }) + }); err != nil { + return stacktrace.Propagate(err, "An error occurred setting value with key '%s' in the runtime value store", resultUuid) + } + return nil } func makeAddServiceInterpretationReturnValue(serviceName starlark.String, serviceConfig *service.ServiceConfig, resultUuid string) (*kurtosis_types.Service, *startosis_errors.InterpretationError) { diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service_shared_test.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service_shared_test.go index 17ba702467..db696d12b8 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service_shared_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_service_shared_test.go @@ -3,10 +3,13 @@ package add_service import ( "fmt" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/shared_helpers/magic_string_helper" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store" "github.com/stretchr/testify/require" + bolt "go.etcd.io/bbolt" "go.starlark.net/starlark" + "os" "testing" ) @@ -15,13 +18,17 @@ const ( ) func TestAddServiceShared_EntryPointArgsRuntimeValueAreReplaced(t *testing.T) { - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) + stringValueUuid, err := runtimeValueStore.CreateValue() require.Nil(t, err, "error creating a runtime value UUID") runtimeValueName := "value" - runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{ + err = runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{ runtimeValueName: starlark.MakeInt(8765), }) + require.NoError(t, err) runtimeValue := fmt.Sprintf(magic_string_helper.RuntimeValueReplacementPlaceholderFormat, stringValueUuid, runtimeValueName) serviceName := service.ServiceName("example-datastore-server-2") @@ -48,13 +55,16 @@ func TestAddServiceShared_EntryPointArgsRuntimeValueAreReplaced(t *testing.T) { } func TestAddServiceShared_CmdArgsRuntimeValueAreReplaced(t *testing.T) { - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) stringValueUuid, err := runtimeValueStore.CreateValue() require.Nil(t, err, "error creating a runtime value UUID") runtimeValueName := "value" - runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{ + err = runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{ runtimeValueName: starlark.MakeInt(999999), }) + require.NoError(t, err) runtimeValue := fmt.Sprintf(magic_string_helper.RuntimeValueReplacementPlaceholderFormat, stringValueUuid, runtimeValueName) serviceName := service.ServiceName("example-datastore-server-2") @@ -81,13 +91,16 @@ func TestAddServiceShared_CmdArgsRuntimeValueAreReplaced(t *testing.T) { } func TestAddServiceShared_EnvVarsWithRuntimeValueAreReplaced(t *testing.T) { - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) stringValueUuid, err := runtimeValueStore.CreateValue() require.Nil(t, err, "error creating a runtime value UUID") runtimeValueName := "value" - runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{ + err = runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{ runtimeValueName: starlark.MakeInt(8765), }) + require.NoError(t, err) runtimeValue := fmt.Sprintf(magic_string_helper.RuntimeValueReplacementPlaceholderFormat, stringValueUuid, runtimeValueName) serviceName := service.ServiceName("example-datastore-server-2") @@ -119,13 +132,16 @@ func TestAddServiceShared_EnvVarsWithRuntimeValueAreReplaced(t *testing.T) { } func TestAddServiceShared_ServiceNameWithRuntimeValuesAreReplaced(t *testing.T) { - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) stringValueUuid, err := runtimeValueStore.CreateValue() require.Nil(t, err, "error creating a runtime value UUID") valueName := "value" - runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{ + err = runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{ "value": starlark.String("database-1"), }) + require.NoError(t, err) stringRuntimeValue := fmt.Sprintf(magic_string_helper.RuntimeValueReplacementPlaceholderFormat, stringValueUuid, valueName) serviceName := service.ServiceName(stringRuntimeValue) @@ -149,3 +165,20 @@ func TestAddServiceShared_ServiceNameWithRuntimeValuesAreReplaced(t *testing.T) require.Nil(t, err) require.Equal(t, service.ServiceName("database-1"), replacedServiceName) } + +func getEnclaveDBForTest(t *testing.T) *enclave_db.EnclaveDB { + file, err := os.CreateTemp("/tmp", "*.db") + defer func() { + err = os.Remove(file.Name()) + require.NoError(t, err) + }() + + require.NoError(t, err) + db, err := bolt.Open(file.Name(), 0666, nil) + require.NoError(t, err) + enclaveDb := &enclave_db.EnclaveDB{ + DB: db, + } + + return enclaveDb +} diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_services.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_services.go index d06c3d157f..3b295a34ab 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_services.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service/add_services.go @@ -194,7 +194,9 @@ func (builtin *AddServicesCapabilities) Execute(ctx context.Context, _ *builtin_ instructionResult := strings.Builder{} instructionResult.WriteString(fmt.Sprintf("Successfully added the following '%d' services:", len(startedServices))) for serviceName, serviceObj := range startedAndUpdatedService { - fillAddServiceReturnValueWithRuntimeValues(serviceObj, builtin.resultUuids[serviceName], builtin.runtimeValueStore) + if err := fillAddServiceReturnValueWithRuntimeValues(serviceObj, builtin.resultUuids[serviceName], builtin.runtimeValueStore); err != nil { + return "", stacktrace.Propagate(err, "An error occurred while adding service return values with result key UUID '%s'", builtin.resultUuids[serviceName]) + } instructionResult.WriteString(fmt.Sprintf("\n Service '%s' added with UUID '%s'", serviceName, serviceObj.GetRegistration().GetUUID())) } shouldDeleteAllStartedServices = false diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/exec/exec.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/exec/exec.go index c1fdd2f39f..67fc13fd4b 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/exec/exec.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/exec/exec.go @@ -168,7 +168,9 @@ func (builtin *ExecCapabilities) Execute(ctx context.Context, _ *builtin_argumen return "", stacktrace.NewError(formatErrorMessage(errorMessage, result["output"].String())) } - builtin.runtimeValueStore.SetValue(builtin.resultUuid, result) + if err := builtin.runtimeValueStore.SetValue(builtin.resultUuid, result); err != nil { + return "", stacktrace.Propagate(err, "An error occurred setting value '%+v' using key UUID '%s' in the runtime value store", result, builtin.resultUuid) + } instructionResult := builtin.execRecipe.ResultMapToString(result) return instructionResult, err } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/request/request.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/request/request.go index 3d0745f215..635ec478c9 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/request/request.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/request/request.go @@ -179,7 +179,10 @@ func (builtin *RequestCapabilities) Execute(ctx context.Context, _ *builtin_argu if !builtin.skipCodeCheck && !builtin.isAcceptableCode(result) { return "", stacktrace.NewError("Request returned status code '%v' that is not part of the acceptable status codes '%v'", result["code"], builtin.acceptableCodes) } - builtin.runtimeValueStore.SetValue(builtin.resultUuid, result) + if err := builtin.runtimeValueStore.SetValue(builtin.resultUuid, result); err != nil { + return "", stacktrace.Propagate(err, "An error occurred setting value '%+v' using key UUID '%s' in the runtime value store", result, builtin.resultUuid) + } + instructionResult := builtin.httpRequestRecipe.ResultMapToString(result) return instructionResult, err } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/shared_helpers/magic_string_helper/magic_string_helper_test.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/shared_helpers/magic_string_helper/magic_string_helper_test.go index 75f91a234e..9f075c093a 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/shared_helpers/magic_string_helper/magic_string_helper_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/shared_helpers/magic_string_helper/magic_string_helper_test.go @@ -2,9 +2,12 @@ package magic_string_helper import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store" "github.com/stretchr/testify/require" + bolt "go.etcd.io/bbolt" "go.starlark.net/starlark" + "os" "testing" ) @@ -17,13 +20,17 @@ const ( var testIntRuntimeValue = starlark.MakeInt(0) func TestGetOrReplaceRuntimeValueFromString_BasicFetch(t *testing.T) { - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) stringValueUuid, err := runtimeValueStore.CreateValue() require.Nil(t, err) - runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{testRuntimeValueField: testStringRuntimeValue}) + err = runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{testRuntimeValueField: testStringRuntimeValue}) + require.NoError(t, err) intValueUuid, err := runtimeValueStore.CreateValue() require.Nil(t, err) - runtimeValueStore.SetValue(intValueUuid, map[string]starlark.Comparable{testRuntimeValueField: testIntRuntimeValue}) + err = runtimeValueStore.SetValue(intValueUuid, map[string]starlark.Comparable{testRuntimeValueField: testIntRuntimeValue}) + require.NoError(t, err) fetchedStringValue, err := GetOrReplaceRuntimeValueFromString(fmt.Sprintf(RuntimeValueReplacementPlaceholderFormat, stringValueUuid, testRuntimeValueField), runtimeValueStore) require.Nil(t, err) require.Equal(t, fetchedStringValue, testStringRuntimeValue) @@ -33,13 +40,17 @@ func TestGetOrReplaceRuntimeValueFromString_BasicFetch(t *testing.T) { } func TestGetOrReplaceRuntimeValueFromString_Interpolated(t *testing.T) { - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) stringValueUuid, err := runtimeValueStore.CreateValue() require.Nil(t, err) - runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{testRuntimeValueField: testStringRuntimeValue}) + err = runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{testRuntimeValueField: testStringRuntimeValue}) + require.NoError(t, err) intValueUuid, err := runtimeValueStore.CreateValue() require.Nil(t, err) - runtimeValueStore.SetValue(intValueUuid, map[string]starlark.Comparable{testRuntimeValueField: testIntRuntimeValue}) + err = runtimeValueStore.SetValue(intValueUuid, map[string]starlark.Comparable{testRuntimeValueField: testIntRuntimeValue}) + require.NoError(t, err) stringRuntimeValue := fmt.Sprintf(RuntimeValueReplacementPlaceholderFormat, stringValueUuid, testRuntimeValueField) intRuntimeValue := fmt.Sprintf(RuntimeValueReplacementPlaceholderFormat, intValueUuid, testRuntimeValueField) interpolatedString := fmt.Sprintf("%v is not %v", stringRuntimeValue, intRuntimeValue) @@ -49,13 +60,17 @@ func TestGetOrReplaceRuntimeValueFromString_Interpolated(t *testing.T) { } func TestReplaceRuntimeValueFromString(t *testing.T) { - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) stringValueUuid, err := runtimeValueStore.CreateValue() require.Nil(t, err) - runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{testRuntimeValueField: testStringRuntimeValue}) + err = runtimeValueStore.SetValue(stringValueUuid, map[string]starlark.Comparable{testRuntimeValueField: testStringRuntimeValue}) + require.NoError(t, err) intValueUuid, err := runtimeValueStore.CreateValue() require.Nil(t, err) - runtimeValueStore.SetValue(intValueUuid, map[string]starlark.Comparable{testRuntimeValueField: testIntRuntimeValue}) + err = runtimeValueStore.SetValue(intValueUuid, map[string]starlark.Comparable{testRuntimeValueField: testIntRuntimeValue}) + require.NoError(t, err) stringRuntimeValue := fmt.Sprintf(RuntimeValueReplacementPlaceholderFormat, stringValueUuid, testRuntimeValueField) intRuntimeValue := fmt.Sprintf(RuntimeValueReplacementPlaceholderFormat, intValueUuid, testRuntimeValueField) interpolatedString := fmt.Sprintf("%v is not %v", stringRuntimeValue, intRuntimeValue) @@ -63,3 +78,20 @@ func TestReplaceRuntimeValueFromString(t *testing.T) { require.Nil(t, err) require.Equal(t, resolvedInterpolatedString, testExpectedInterpolatedString.GoString()) } + +func getEnclaveDBForTest(t *testing.T) *enclave_db.EnclaveDB { + file, err := os.CreateTemp("/tmp", "*.db") + defer func() { + err = os.Remove(file.Name()) + require.NoError(t, err) + }() + + require.NoError(t, err) + db, err := bolt.Open(file.Name(), 0666, nil) + require.NoError(t, err) + enclaveDb := &enclave_db.EnclaveDB{ + DB: db, + } + + return enclaveDb +} diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/tasks/run_python.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/tasks/run_python.go index 9a17176623..6ce2e29c2c 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/tasks/run_python.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/tasks/run_python.go @@ -310,7 +310,9 @@ func (builtin *RunPythonCapabilities) Execute(ctx context.Context, _ *builtin_ar runResultCodeKey: starlark.MakeInt(int(runPythonExecutionResult.GetExitCode())), } - builtin.runtimeValueStore.SetValue(builtin.resultUuid, result) + if err := builtin.runtimeValueStore.SetValue(builtin.resultUuid, result); err != nil { + return "", stacktrace.Propagate(err, "An error occurred setting value '%+v' using key UUID '%s' in the runtime value store", result, builtin.resultUuid) + } instructionResult := resultMapToString(result, RunPythonBuiltinName) // throw an error as execution of the command failed diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/tasks/run_sh.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/tasks/run_sh.go index 468b1f643d..2b5c56c219 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/tasks/run_sh.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/tasks/run_sh.go @@ -214,7 +214,9 @@ func (builtin *RunShCapabilities) Execute(ctx context.Context, _ *builtin_argume runResultCodeKey: starlark.MakeInt(int(createDefaultDirectoryResult.GetExitCode())), } - builtin.runtimeValueStore.SetValue(builtin.resultUuid, result) + if err := builtin.runtimeValueStore.SetValue(builtin.resultUuid, result); err != nil { + return "", stacktrace.Propagate(err, "An error occurred setting value '%+v' using key UUID '%s' in the runtime value store", result, builtin.resultUuid) + } instructionResult := resultMapToString(result, RunShBuiltinName) // throw an error as execution of the command failed diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/wait/wait.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/wait/wait.go index 946f4a8c0b..18d7a250a0 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/wait/wait.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/wait/wait.go @@ -261,7 +261,9 @@ func (builtin *WaitCapabilities) Execute(ctx context.Context, _ *builtin_argumen ) } - builtin.runtimeValueStore.SetValue(builtin.resultUuid, lastResult) + if err := builtin.runtimeValueStore.SetValue(builtin.resultUuid, lastResult); err != nil { + return "", stacktrace.Propagate(err, "An error occurred setting value '%+v' using key UUID '%s' in the runtime value store", lastResult, builtin.resultUuid) + } instructionResult := fmt.Sprintf( "Wait took %d tries (%v in total). Assertion passed with following:\n%s", diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_service_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_service_framework_test.go index 497a4b9dff..c6d38f411b 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_service_framework_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_service_framework_test.go @@ -5,6 +5,7 @@ import ( "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/container_status" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/port_spec" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/add_service" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" @@ -14,7 +15,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + bolt "go.etcd.io/bbolt" "go.starlark.net/starlark" + "os" "testing" ) @@ -34,7 +37,9 @@ func (t *addServiceTestCase) GetId() string { func (t *addServiceTestCase) GetInstruction() *kurtosis_plan_instruction.KurtosisPlanInstruction { serviceNetwork := service_network.NewMockServiceNetwork(t) - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t.T) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) serviceNetwork.EXPECT().ExistServiceRegistration(TestServiceName).Times(1).Return(false, nil) serviceNetwork.EXPECT().AddService( @@ -88,3 +93,20 @@ func (t *addServiceTestCase) Assert(interpretationResult starlark.Value, executi expectedExecutionResult := fmt.Sprintf("Service '%s' added with service UUID '%s'", TestServiceName, TestServiceUuid) require.Equal(t, expectedExecutionResult, *executionResult) } + +func getEnclaveDBForTest(t *testing.T) *enclave_db.EnclaveDB { + file, err := os.CreateTemp("/tmp", "*.db") + defer func() { + err = os.Remove(file.Name()) + require.NoError(t, err) + }() + + require.NoError(t, err) + db, err := bolt.Open(file.Name(), 0666, nil) + require.NoError(t, err) + enclaveDb := &enclave_db.EnclaveDB{ + DB: db, + } + + return enclaveDb +} diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_services_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_services_framework_test.go index 1eaef41d64..ab98a87da6 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_services_framework_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/add_services_framework_test.go @@ -37,7 +37,9 @@ func (t *addServicesTestCase) GetId() string { func (t *addServicesTestCase) GetInstruction() *kurtosis_plan_instruction.KurtosisPlanInstruction { serviceNetwork := service_network.NewMockServiceNetwork(t) - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t.T) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) serviceNetwork.EXPECT().ExistServiceRegistration(TestServiceName).Times(1).Return(false, nil) serviceNetwork.EXPECT().ExistServiceRegistration(TestServiceName2).Times(1).Return(false, nil) diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/assert_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/assert_framework_test.go index 76edd14c8e..819550a2e7 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/assert_framework_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/assert_framework_test.go @@ -35,10 +35,13 @@ func (t assertTestCase) GetId() string { } func (t assertTestCase) GetInstruction() *kurtosis_plan_instruction.KurtosisPlanInstruction { - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() - runtimeValueStore.SetValue(t.runtimeValueUuid, map[string]starlark.Comparable{ + enclaveDb := getEnclaveDBForTest(t.T) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) + err = runtimeValueStore.SetValue(t.runtimeValueUuid, map[string]starlark.Comparable{ "value": starlark.String(runtimeValueValue), }) + require.NoError(t, err) return assert.NewAssert(runtimeValueStore) } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/exec_framework_test_case_1_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/exec_framework_test_case_1_test.go index 867da81f3d..0a70df0cbf 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/exec_framework_test_case_1_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/exec_framework_test_case_1_test.go @@ -34,7 +34,9 @@ func (t execTestCase1) GetId() string { func (t execTestCase1) GetInstruction() *kurtosis_plan_instruction.KurtosisPlanInstruction { serviceNetwork := service_network.NewMockServiceNetwork(t) - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t.T) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) serviceNetwork.EXPECT().RunExec( mock.Anything, diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/exec_framework_test_case_2_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/exec_framework_test_case_2_test.go index 26cfac6d03..fd04bb2dfc 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/exec_framework_test_case_2_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/exec_framework_test_case_2_test.go @@ -30,7 +30,9 @@ func (t execTestCase2) GetId() string { func (t execTestCase2) GetInstruction() *kurtosis_plan_instruction.KurtosisPlanInstruction { serviceNetwork := service_network.NewMockServiceNetwork(t) - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t.T) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) serviceNetwork.EXPECT().RunExec( mock.Anything, diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/exec_recipe_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/exec_recipe_framework_test.go index 9b1cdb2152..195a2035f4 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/exec_recipe_framework_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/exec_recipe_framework_test.go @@ -21,7 +21,9 @@ type execRecipeTestCase struct { } func newExecRecipeTestCase(t *testing.T) *execRecipeTestCase { - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) serviceNetwork := service_network.NewMockServiceNetwork(t) serviceNetwork.EXPECT().RunExec( mock.Anything, diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_no_extractor_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_no_extractor_test.go index 454fbf8c9f..ff8948545a 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_no_extractor_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_no_extractor_test.go @@ -22,7 +22,9 @@ type getHttpRequestRecipeNoExtractorTestCase struct { } func newGetHttpRequestRecipeNoExtractorTestCase(t *testing.T) *getHttpRequestRecipeNoExtractorTestCase { - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) serviceNetwork := service_network.NewMockServiceNetwork(t) serviceNetwork.EXPECT().HttpRequestService( diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_test.go index b1ebef2466..cba9784a09 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_test.go @@ -26,7 +26,9 @@ type getHttpRequestRecipeTestCase struct { } func newGetHttpRequestRecipeTestCase(t *testing.T) *getHttpRequestRecipeTestCase { - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) serviceNetwork := service_network.NewMockServiceNetwork(t) serviceNetwork.EXPECT().HttpRequestService( diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/kurtosis_print_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/kurtosis_print_framework_test.go index a285418ecc..49107afcd8 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/kurtosis_print_framework_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/kurtosis_print_framework_test.go @@ -31,7 +31,9 @@ func (t *printTestCase) GetId() string { func (t *printTestCase) GetInstruction() *kurtosis_plan_instruction.KurtosisPlanInstruction { serviceNetwork := service_network.NewMockServiceNetwork(t) - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t.T) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) return kurtosis_print.NewPrint(serviceNetwork, runtimeValueStore) } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_minimal_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_minimal_test.go index d42821f270..e856d35589 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_minimal_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_minimal_test.go @@ -22,7 +22,9 @@ type postHttpRequestRecipeMinimalTestCase struct { } func newPostHttpRequestRecipeMinimalTestCase(t *testing.T) *postHttpRequestRecipeMinimalTestCase { - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) serviceNetwork := service_network.NewMockServiceNetwork(t) serviceNetwork.EXPECT().HttpRequestService( diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_test.go index 109fe82f5e..47d5c6fa1c 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_test.go @@ -26,7 +26,9 @@ type postHttpRequestRecipeTestCase struct { } func newPostHttpRequestRecipeTestCase(t *testing.T) *postHttpRequestRecipeTestCase { - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) serviceNetwork := service_network.NewMockServiceNetwork(t) serviceNetwork.EXPECT().HttpRequestService( diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/render_multiple_templates_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/render_multiple_templates_framework_test.go index 929100ed08..e0e8665e3d 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/render_multiple_templates_framework_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/render_multiple_templates_framework_test.go @@ -61,7 +61,11 @@ func (t renderMultipleTemplatesTestCase) GetId() string { } func (t renderMultipleTemplatesTestCase) GetInstruction() *kurtosis_plan_instruction.KurtosisPlanInstruction { - return render_templates.NewRenderTemplatesInstruction(t.serviceNetwork, runtime_value_store.NewRuntimeValueStore()) + enclaveDb := getEnclaveDBForTest(t.T) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) + + return render_templates.NewRenderTemplatesInstruction(t.serviceNetwork, runtimeValueStore) } func (t renderMultipleTemplatesTestCase) GetStarlarkCode() string { diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/render_single_templates_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/render_single_templates_framework_test.go index c308378dbe..e3f5ebcb5b 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/render_single_templates_framework_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/render_single_templates_framework_test.go @@ -46,7 +46,10 @@ func (t renderSingleTemplateTestCase) GetId() string { } func (t renderSingleTemplateTestCase) GetInstruction() *kurtosis_plan_instruction.KurtosisPlanInstruction { - return render_templates.NewRenderTemplatesInstruction(t.serviceNetwork, runtime_value_store.NewRuntimeValueStore()) + enclaveDb := getEnclaveDBForTest(t.T) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) + return render_templates.NewRenderTemplatesInstruction(t.serviceNetwork, runtimeValueStore) } func (t renderSingleTemplateTestCase) GetStarlarkCode() string { diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/request_framework_test_case_1_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/request_framework_test_case_1_test.go index 18b507feed..f8344e78d0 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/request_framework_test_case_1_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/request_framework_test_case_1_test.go @@ -43,7 +43,9 @@ func (t *requestTestCase1) GetId() string { func (t *requestTestCase1) GetInstruction() *kurtosis_plan_instruction.KurtosisPlanInstruction { serviceNetwork := service_network.NewMockServiceNetwork(t) - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t.T) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) serviceNetwork.EXPECT().HttpRequestService( mock.Anything, diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/request_framework_test_case_2_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/request_framework_test_case_2_test.go index f609383e66..a66ddf7131 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/request_framework_test_case_2_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/request_framework_test_case_2_test.go @@ -32,7 +32,9 @@ func (t *requestTestCase2) GetId() string { func (t *requestTestCase2) GetInstruction() *kurtosis_plan_instruction.KurtosisPlanInstruction { serviceNetwork := service_network.NewMockServiceNetwork(t) - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t.T) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) serviceNetwork.EXPECT().HttpRequestService( mock.Anything, diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/wait_framework_test_case_1_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/wait_framework_test_case_1_test.go index 16dc8a2662..1e288fb984 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/wait_framework_test_case_1_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/wait_framework_test_case_1_test.go @@ -49,7 +49,9 @@ func (t *waitTestCase1) GetId() string { func (t *waitTestCase1) GetInstruction() *kurtosis_plan_instruction.KurtosisPlanInstruction { serviceNetwork := service_network.NewMockServiceNetwork(t) - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t.T) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) serviceNetwork.EXPECT().HttpRequestService( mock.Anything, diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/wait_framework_test_case_2_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/wait_framework_test_case_2_test.go index 6bad6ce25b..40aa8b7d06 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/wait_framework_test_case_2_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/wait_framework_test_case_2_test.go @@ -33,7 +33,9 @@ func (t *waitTestCase2) GetId() string { func (t *waitTestCase2) GetInstruction() *kurtosis_plan_instruction.KurtosisPlanInstruction { serviceNetwork := service_network.NewMockServiceNetwork(t) - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(t.T) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) serviceNetwork.EXPECT().HttpRequestService( mock.Anything, diff --git a/core/server/api_container/server/startosis_engine/runtime_value_store/recipe_result_repository.go b/core/server/api_container/server/startosis_engine/runtime_value_store/recipe_result_repository.go new file mode 100644 index 0000000000..3b48ab691f --- /dev/null +++ b/core/server/api_container/server/startosis_engine/runtime_value_store/recipe_result_repository.go @@ -0,0 +1,177 @@ +package runtime_value_store + +import ( + "encoding/json" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db" + "github.com/kurtosis-tech/stacktrace" + "github.com/sirupsen/logrus" + bolt "go.etcd.io/bbolt" + "go.starlark.net/starlark" + "strconv" +) + +var ( + recipeResultBucketName = []byte("recipe-result-repository") + emptyValue = []byte{} +) + +type recipeResultRepository struct { + enclaveDb *enclave_db.EnclaveDB +} + +func getOrCreateNewRecipeResultRepository(enclaveDb *enclave_db.EnclaveDB) (*recipeResultRepository, error) { + if err := enclaveDb.Update(func(tx *bolt.Tx) error { + bucket, err := tx.CreateBucketIfNotExists(recipeResultBucketName) + if err != nil { + return stacktrace.Propagate(err, "An error occurred while creating the recipe result database bucket") + } + logrus.Debugf("Recipe result bucket: '%+v'", bucket) + + return nil + }); err != nil { + return nil, stacktrace.Propagate(err, "An error occurred while building the recipe result repository") + } + + repository := &recipeResultRepository{ + enclaveDb: enclaveDb, + } + + return repository, nil +} + +func (repository *recipeResultRepository) SaveKey( + uuid string, +) error { + + if err := repository.enclaveDb.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket(recipeResultBucketName) + + uuidKey := getUuidKey(uuid) + + // save it to disk + if err := bucket.Put(uuidKey, emptyValue); err != nil { + return stacktrace.Propagate(err, "An error occurred while registering key UUID '%s' into the enclave db bucket", uuid) + } + return nil + }); err != nil { + return stacktrace.Propagate(err, "An error occurred while registering key UUID '%s' into the enclave db", uuid) + } + return nil +} + +// Save store recipe result values into the repository, and it only accepts comparables of +// starlark.String and starlark.Int so far +func (repository *recipeResultRepository) Save( + uuid string, + value map[string]starlark.Comparable, +) error { + + if err := repository.enclaveDb.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket(recipeResultBucketName) + + uuidKey := getUuidKey(uuid) + + stringifiedValue := map[string]string{} + + for key, comparableValue := range value { + //TODO add more kind of comparable types if we want to extend the support + //TODO now starlark.Int and starlark.String are enough so far + switch valueType := comparableValue.(type) { + case starlark.Int: + stringifiedValue[key] = comparableValue.String() + case starlark.String: + comparableStr, ok := comparableValue.(starlark.String) + if !ok { + return stacktrace.NewError("An error occurred casting comparable type '%v' to Starlark string", comparableValue) + } + stringifiedValue[key] = comparableStr.GoString() + default: + return stacktrace.NewError("Unexpected comparable type on recipe result repository, only 'starlark.String and slartark.Int' are allowed but '%v' was received.", valueType) + } + } + + jsonBytes, err := json.Marshal(stringifiedValue) + if err != nil { + return stacktrace.Propagate(err, "An error occurred marshalling value '%+v' in the recipe result repository", value) + } + + // save it to disk + if err := bucket.Put(uuidKey, jsonBytes); err != nil { + return stacktrace.Propagate(err, "An error occurred while saving recipe result value '%+v' with UUID '%s' into the enclave db bucket", value, uuid) + } + return nil + }); err != nil { + return stacktrace.Propagate(err, "An error occurred while saving recipe result value '%+v' with UUID '%s' into the enclave db", value, uuid) + } + return nil +} + +func (repository *recipeResultRepository) Get( + uuid string, +) (map[string]starlark.Comparable, error) { + + value := map[string]starlark.Comparable{} + + if err := repository.enclaveDb.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket(recipeResultBucketName) + + uuidKey := getUuidKey(uuid) + + // first get the bytes + jsonBytes := bucket.Get(uuidKey) + + // check for existence + if jsonBytes == nil { + return stacktrace.NewError("Recipe result value with keu UUID '%s' does not exist on the recipe result repository", uuid) + } + + isEmptyValue := len(jsonBytes) == len(emptyValue) + + // this will the case if the key was saved with an empty value + if isEmptyValue { + return nil + } + + stringifiedValue := map[string]string{} + + if err := json.Unmarshal(jsonBytes, &stringifiedValue); err != nil { + return stacktrace.Propagate(err, "An error occurred unmarshalling the recipe result value with UUID '%s' from the repository", uuid) + } + + for key, stringifiedComparable := range stringifiedValue { + var comparableValue starlark.Comparable + comparableInt, err := strconv.Atoi(stringifiedComparable) + if err != nil { + comparableValue = starlark.String(stringifiedComparable) + } else { + comparableValue = starlark.MakeInt(comparableInt) + } + value[key] = comparableValue + } + + return nil + }); err != nil { + return nil, stacktrace.Propagate(err, "An error occurred while getting the recipe result value with UUID '%s' from the enclave db", uuid) + } + return value, nil +} + +func (repository *recipeResultRepository) Delete(uuid string) error { + if err := repository.enclaveDb.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket(recipeResultBucketName) + + uuidKey := getUuidKey(uuid) + if err := bucket.Delete(uuidKey); err != nil { + return stacktrace.Propagate(err, "An error occurred deleting a recipe result with key '%v' from the recipe result bucket", uuidKey) + } + + return nil + }); err != nil { + return stacktrace.Propagate(err, "An error occurred while deleting a recipe result with key '%v' from the recipe result repository", uuid) + } + return nil +} + +func getUuidKey(uuid string) []byte { + return []byte(uuid) +} diff --git a/core/server/api_container/server/startosis_engine/runtime_value_store/recipe_result_repository_test.go b/core/server/api_container/server/startosis_engine/runtime_value_store/recipe_result_repository_test.go new file mode 100644 index 0000000000..b6942add35 --- /dev/null +++ b/core/server/api_container/server/startosis_engine/runtime_value_store/recipe_result_repository_test.go @@ -0,0 +1,146 @@ +package runtime_value_store + +import ( + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/directory" + "github.com/stretchr/testify/require" + bolt "go.etcd.io/bbolt" + "go.starlark.net/starlark" + "os" + "testing" +) + +const ( + randomUuid = "abcd12a3948149d9afa2ef93abb4ec52" + + notAcceptedComparableTypeErrorMsg = "Unexpected comparable type" + keyDoesNotExistOnRepositoryErrorMsg = "does not exist on the recipe result repository" + + firstKey = "mykey" + secondKey = "mySecondKey" + thirdKey = "myThirdKey" + starlarkStringValue = starlark.String("my-value") +) + +var ( + starlarkIntValue = starlark.MakeInt(30) +) + +func TestRecipeResultSaveKey_Success(t *testing.T) { + repository := getRecipeResultRepositoryForTest(t) + + err := repository.SaveKey(randomUuid) + require.NoError(t, err) + + value, err := repository.Get(randomUuid) + require.NoError(t, err) + require.Empty(t, value) +} + +func TestRecipeResultSaveAndGet_Success(t *testing.T) { + repository := getRecipeResultRepositoryForTest(t) + + resultValue := map[string]starlark.Comparable{ + firstKey: starlarkStringValue, + secondKey: starlarkIntValue, + } + + err := repository.Save(randomUuid, resultValue) + require.NoError(t, err) + + value, err := repository.Get(randomUuid) + require.NoError(t, err) + require.NotNil(t, value) + + require.Equal(t, resultValue, value) +} + +func TestRecipeResultGet_DoesNotExist(t *testing.T) { + repository := getRecipeResultRepositoryForTest(t) + + value, err := repository.Get(randomUuid) + require.Error(t, err) + require.ErrorContains(t, err, keyDoesNotExistOnRepositoryErrorMsg) + require.Empty(t, value) +} + +func TestRecipeResultSave_ErrorWhenUsingNotStarlarkStringOrInt(t *testing.T) { + repository := getRecipeResultRepositoryForTest(t) + + resultValue := map[string]starlark.Comparable{ + firstKey: starlark.Bool(true), + } + + err := repository.Save(randomUuid, resultValue) + require.Error(t, err) + require.ErrorContains(t, err, notAcceptedComparableTypeErrorMsg) + + resultValue2 := map[string]starlark.Comparable{ + secondKey: directory.Directory{}, // nolint: exhaustruct + } + + err = repository.Save(randomUuid, resultValue2) + require.Error(t, err) + require.ErrorContains(t, err, notAcceptedComparableTypeErrorMsg) + + resultValue3 := map[string]starlark.Comparable{ + thirdKey: &kurtosis_type_constructor.KurtosisValueTypeDefault{}, // nolint: exhaustruct + } + + err = repository.Save(randomUuid, resultValue3) + require.Error(t, err) + require.ErrorContains(t, err, notAcceptedComparableTypeErrorMsg) + + resultValue4 := map[string]starlark.Comparable{ + thirdKey: &starlark.Dict{}, + } + + err = repository.Save(randomUuid, resultValue4) + require.Error(t, err) + require.ErrorContains(t, err, notAcceptedComparableTypeErrorMsg) +} + +func TestDelete_Success(t *testing.T) { + repository := getRecipeResultRepositoryForTest(t) + + resultValue := map[string]starlark.Comparable{ + firstKey: starlarkStringValue, + secondKey: starlarkIntValue, + } + + err := repository.Save(randomUuid, resultValue) + require.NoError(t, err) + + value, err := repository.Get(randomUuid) + require.NoError(t, err) + require.NotNil(t, value) + + require.Equal(t, resultValue, value) + + err = repository.Delete(randomUuid) + require.NoError(t, err) + + value, err = repository.Get(randomUuid) + require.Error(t, err) + require.Empty(t, value) +} + +func getRecipeResultRepositoryForTest(t *testing.T) *recipeResultRepository { + file, err := os.CreateTemp("/tmp", "*.db") + defer func() { + err = os.Remove(file.Name()) + require.NoError(t, err) + }() + + require.NoError(t, err) + db, err := bolt.Open(file.Name(), 0666, nil) + require.NoError(t, err) + enclaveDb := &enclave_db.EnclaveDB{ + DB: db, + } + repository, err := getOrCreateNewRecipeResultRepository(enclaveDb) + require.NoError(t, err) + + return repository +} diff --git a/core/server/api_container/server/startosis_engine/runtime_value_store/runtime_value_store.go b/core/server/api_container/server/startosis_engine/runtime_value_store/runtime_value_store.go index 9bd2143512..1deae38269 100644 --- a/core/server/api_container/server/startosis_engine/runtime_value_store/runtime_value_store.go +++ b/core/server/api_container/server/startosis_engine/runtime_value_store/runtime_value_store.go @@ -2,21 +2,34 @@ package runtime_value_store import ( "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/uuid_generator" "github.com/kurtosis-tech/stacktrace" "go.starlark.net/starlark" ) type RuntimeValueStore struct { - recipeResultMap map[string]map[string]starlark.Comparable - serviceAssociatedValues map[service.ServiceName]string + recipeResultRepository *recipeResultRepository + serviceAssociatedValuesRepository *serviceAssociatedValuesRepository } -func NewRuntimeValueStore() *RuntimeValueStore { - return &RuntimeValueStore{ - recipeResultMap: make(map[string]map[string]starlark.Comparable), - serviceAssociatedValues: make(map[service.ServiceName]string), +func CreateRuntimeValueStore(enclaveDb *enclave_db.EnclaveDB) (*RuntimeValueStore, error) { + associatedValuesRepository, err := getOrCreateNewServiceAssociatedValuesRepository(enclaveDb) + if err != nil { + return nil, stacktrace.Propagate(err, "An error occurred getting or creating the service associated values repository") } + + recipeResultRepositoryObj, err := getOrCreateNewRecipeResultRepository(enclaveDb) + if err != nil { + return nil, stacktrace.Propagate(err, "An error occurred getting or creating the recipe result repository") + } + + runtimeValueStore := &RuntimeValueStore{ + recipeResultRepository: recipeResultRepositoryObj, + serviceAssociatedValuesRepository: associatedValuesRepository, + } + + return runtimeValueStore, nil } func (re *RuntimeValueStore) CreateValue() (string, error) { @@ -24,31 +37,59 @@ func (re *RuntimeValueStore) CreateValue() (string, error) { if err != nil { return "", stacktrace.Propagate(err, "An error occurred while generating uuid for runtime value") } - re.recipeResultMap[uuid] = nil + + if err = re.recipeResultRepository.SaveKey(uuid); err != nil { + return "", stacktrace.Propagate(err, "An error occurred saving key UUID '%s' on the recipe result repository", uuid) + } + return uuid, nil } func (re *RuntimeValueStore) GetOrCreateValueAssociatedWithService(serviceName service.ServiceName) (string, error) { - if uuid, found := re.serviceAssociatedValues[serviceName]; found { - delete(re.recipeResultMap, uuid) // deleting old values so that they do not interfere until that are set again - return uuid, nil + + exist, err := re.serviceAssociatedValuesRepository.Exist(serviceName) + if err != nil { + return "", stacktrace.Propagate(err, "An error occurred checking if there are associated values for service '%s' in the service associated values repository", serviceName) + } + if exist { + uuid, getErr := re.serviceAssociatedValuesRepository.Get(serviceName) + if getErr != nil { + return "", stacktrace.Propagate(err, "An error occurred getting associated values for service '%s'", serviceName) + } + if uuid != "" { + // deleting old values so that they do not interfere until that are set again + if err := re.recipeResultRepository.Delete(uuid); err != nil { + return "", stacktrace.Propagate(err, "An error occurred deleting recipe result with key '%s' from the repository", uuid) + } + return uuid, nil + } } uuid, err := re.CreateValue() if err != nil { return "", stacktrace.Propagate(err, "An error occurred creating a simple runtime value") } - re.serviceAssociatedValues[serviceName] = uuid + + if err := re.serviceAssociatedValuesRepository.Save(serviceName, uuid); err != nil { + return "", stacktrace.Propagate(err, "An error occurred saving associated values '%s' for service '%s' in the service associated values repository", uuid, serviceName) + } + return uuid, nil } -func (re *RuntimeValueStore) SetValue(uuid string, value map[string]starlark.Comparable) { - re.recipeResultMap[uuid] = value +// SetValue store recipe result values into the runtime value store, and it only accepts comparables of +// starlark.String and starlark.Int so far, make sure to upgrade the recipe result repository if you +// want to extend this capability supporting more comparable types +func (re *RuntimeValueStore) SetValue(uuid string, value map[string]starlark.Comparable) error { + if err := re.recipeResultRepository.Save(uuid, value); err != nil { + return stacktrace.Propagate(err, "An error occurred saving value '%+v' using UUID key '%s' into the recipe result repository", value, uuid) + } + return nil } func (re *RuntimeValueStore) GetValue(uuid string) (map[string]starlark.Comparable, error) { - value, found := re.recipeResultMap[uuid] - if !found { - return nil, stacktrace.NewError("Runtime UUID '%v' was not found", uuid) + value, err := re.recipeResultRepository.Get(uuid) + if err != nil { + return nil, stacktrace.Propagate(err, "An error occurred getting recipe result value with UUID key '%s'", uuid) } if value == nil { return nil, stacktrace.NewError("Runtime UUID '%v' was found, but not set", uuid) diff --git a/core/server/api_container/server/startosis_engine/runtime_value_store/service_associated_values_repository.go b/core/server/api_container/server/startosis_engine/runtime_value_store/service_associated_values_repository.go new file mode 100644 index 0000000000..f7e7e36860 --- /dev/null +++ b/core/server/api_container/server/startosis_engine/runtime_value_store/service_associated_values_repository.go @@ -0,0 +1,106 @@ +package runtime_value_store + +import ( + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db" + "github.com/kurtosis-tech/stacktrace" + "github.com/sirupsen/logrus" + bolt "go.etcd.io/bbolt" +) + +var ( + serviceAssociatedValuesBucketName = []byte("service-associated-values-repository") +) + +type serviceAssociatedValuesRepository struct { + enclaveDb *enclave_db.EnclaveDB +} + +func getOrCreateNewServiceAssociatedValuesRepository(enclaveDb *enclave_db.EnclaveDB) (*serviceAssociatedValuesRepository, error) { + if err := enclaveDb.Update(func(tx *bolt.Tx) error { + bucket, err := tx.CreateBucketIfNotExists(serviceAssociatedValuesBucketName) + if err != nil { + return stacktrace.Propagate(err, "An error occurred while creating the service associated values database bucket") + } + logrus.Debugf("Service associated values bucket: '%+v'", bucket) + + return nil + }); err != nil { + return nil, stacktrace.Propagate(err, "An error occurred while building the service associated values repository") + } + + serviceRuntimeValuesRepository := &serviceAssociatedValuesRepository{ + enclaveDb: enclaveDb, + } + + return serviceRuntimeValuesRepository, nil +} + +func (repository *serviceAssociatedValuesRepository) Save( + serviceName service.ServiceName, + uuid string, +) error { + + if err := repository.enclaveDb.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket(serviceAssociatedValuesBucketName) + + serviceNameKey := getServiceNameKey(serviceName) + + // save it to disk + if err := bucket.Put(serviceNameKey, []byte(uuid)); err != nil { + return stacktrace.Propagate(err, "An error occurred while saving service associated value '%s' for service '%s' into the enclave db bucket", uuid, serviceName) + } + return nil + }); err != nil { + return stacktrace.Propagate(err, "An error occurred while adding service associated value '%s' for service '%s' into the enclave db", uuid, serviceName) + } + return nil +} + +func (repository *serviceAssociatedValuesRepository) Get( + serviceName service.ServiceName, +) (string, error) { + var uuid string + + if err := repository.enclaveDb.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket(serviceAssociatedValuesBucketName) + + serviceNameKey := getServiceNameKey(serviceName) + + // first get the bytes + uuidBytes := bucket.Get(serviceNameKey) + + uuid = string(uuidBytes) + + return nil + }); err != nil { + return "", stacktrace.Propagate(err, "An error occurred while getting service associated values for service '%s' from the enclave db", serviceName) + } + return uuid, nil +} + +func (repository *serviceAssociatedValuesRepository) Exist( + serviceName service.ServiceName, +) (bool, error) { + + exist := false + + if err := repository.enclaveDb.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket(serviceAssociatedValuesBucketName) + + serviceNameKey := getServiceNameKey(serviceName) + bytes := bucket.Get(serviceNameKey) + if bytes != nil { + exist = true + } + return nil + }); err != nil { + return false, stacktrace.Propagate(err, "An error occurred while checking if there are associated values for service '%s' exist in service associated values repository", serviceName) + } + + return exist, nil +} + +func getServiceNameKey(serviceName service.ServiceName) []byte { + return []byte(serviceName) +} diff --git a/core/server/api_container/server/startosis_engine/runtime_value_store/service_associated_values_repository_test.go b/core/server/api_container/server/startosis_engine/runtime_value_store/service_associated_values_repository_test.go new file mode 100644 index 0000000000..7bd2344d7f --- /dev/null +++ b/core/server/api_container/server/startosis_engine/runtime_value_store/service_associated_values_repository_test.go @@ -0,0 +1,83 @@ +package runtime_value_store + +import ( + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db" + "github.com/stretchr/testify/require" + bolt "go.etcd.io/bbolt" + "os" + "testing" +) + +const ( + firstServiceName = service.ServiceName("first-service-name") + secondServiceName = service.ServiceName("second-service-name") + serviceWithoutAssociatedValues = service.ServiceName("no-values-service-name") + + firstServiceAssociatedValueUuid = "cddc2ea3948149d9afa2ef93abb4ec52" + secondServiceAssociatedValueUuid = "ae5c8bf2fbeb4de68f647280b1c79cbb" +) + +func TestSaveAndGet_Success(t *testing.T) { + repository := getAssociatedValuesRepositoryForTest(t) + + err := repository.Save(firstServiceName, firstServiceAssociatedValueUuid) + require.NoError(t, err) + + err = repository.Save(secondServiceName, secondServiceAssociatedValueUuid) + require.NoError(t, err) + + firstServiceAssociatedValues, err := repository.Get(firstServiceName) + require.NoError(t, err) + require.Equal(t, firstServiceAssociatedValueUuid, firstServiceAssociatedValues) + + secondServiceAssociatedValues, err := repository.Get(secondServiceName) + require.NoError(t, err) + require.Equal(t, secondServiceAssociatedValueUuid, secondServiceAssociatedValues) +} + +func TestGet_NotAssociateValues(t *testing.T) { + repository := getAssociatedValuesRepositoryForTest(t) + + serviceAssociatedValues, err := repository.Get(serviceWithoutAssociatedValues) + require.NoError(t, err) + require.Empty(t, serviceAssociatedValues) +} + +func TestExist_Success(t *testing.T) { + repository := getAssociatedValuesRepositoryForTest(t) + + err := repository.Save(firstServiceName, firstServiceAssociatedValueUuid) + require.NoError(t, err) + + exist, err := repository.Exist(firstServiceName) + require.NoError(t, err) + require.True(t, exist) +} + +func TestNotExist_Success(t *testing.T) { + repository := getAssociatedValuesRepositoryForTest(t) + + exist, err := repository.Exist(serviceWithoutAssociatedValues) + require.NoError(t, err) + require.False(t, exist) +} + +func getAssociatedValuesRepositoryForTest(t *testing.T) *serviceAssociatedValuesRepository { + file, err := os.CreateTemp("/tmp", "*.db") + defer func() { + err = os.Remove(file.Name()) + require.NoError(t, err) + }() + + require.NoError(t, err) + db, err := bolt.Open(file.Name(), 0666, nil) + require.NoError(t, err) + enclaveDb := &enclave_db.EnclaveDB{ + DB: db, + } + repository, err := getOrCreateNewServiceAssociatedValuesRepository(enclaveDb) + require.NoError(t, err) + + return repository +} diff --git a/core/server/api_container/server/startosis_engine/startosis_executor_test.go b/core/server/api_container/server/startosis_engine/startosis_executor_test.go index 19f9161666..dbb88a1299 100644 --- a/core/server/api_container/server/startosis_engine/startosis_executor_test.go +++ b/core/server/api_container/server/startosis_engine/startosis_executor_test.go @@ -5,13 +5,16 @@ import ( "errors" "github.com/kurtosis-tech/kurtosis/api/golang/core/kurtosis_core_rpc_api_bindings" "github.com/kurtosis-tech/kurtosis/api/golang/core/lib/binding_constructors" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/instructions_plan" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/mock_instruction" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + bolt "go.etcd.io/bbolt" "go.starlark.net/starlark" + "os" "strings" "testing" ) @@ -34,8 +37,11 @@ var ( ) func TestExecuteKurtosisInstructions_ExecuteForReal_Success(t *testing.T) { + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, createRuntimeValueStoreErr := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, createRuntimeValueStoreErr) - executor := NewStartosisExecutor(runtime_value_store.NewRuntimeValueStore()) + executor := NewStartosisExecutor(runtimeValueStore) instructionsPlan := instructions_plan.NewInstructionsPlan() instruction0 := createMockInstruction(t, "instruction0", executeSuccessfully) @@ -78,7 +84,11 @@ func TestExecuteKurtosisInstructions_ExecuteForReal_Success(t *testing.T) { } func TestExecuteKurtosisInstructions_ExecuteForReal_FailureHalfWay(t *testing.T) { - executor := NewStartosisExecutor(runtime_value_store.NewRuntimeValueStore()) + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, err) + + executor := NewStartosisExecutor(runtimeValueStore) instruction1 := createMockInstruction(t, "instruction1", executeSuccessfully) instruction2 := createMockInstruction(t, "instruction2", throwOnExecute) @@ -116,7 +126,11 @@ instruction2() } func TestExecuteKurtosisInstructions_DoDryRun(t *testing.T) { - executor := NewStartosisExecutor(runtime_value_store.NewRuntimeValueStore()) + enclaveDb := getEnclaveDBForTest(t) + runtimeValueStore, createRuntimeValueStoreErr := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(t, createRuntimeValueStoreErr) + + executor := NewStartosisExecutor(runtimeValueStore) instruction1 := createMockInstruction(t, "instruction1", executeSuccessfully) instruction2 := createMockInstruction(t, "instruction2", executeSuccessfully) @@ -185,3 +199,20 @@ func executeSynchronously(t *testing.T, executor *StartosisExecutor, dryRun bool } return scriptOutput.String(), serializedInstructions, nil } + +func getEnclaveDBForTest(t *testing.T) *enclave_db.EnclaveDB { + file, err := os.CreateTemp("/tmp", "*.db") + defer func() { + err = os.Remove(file.Name()) + require.NoError(t, err) + }() + + require.NoError(t, err) + db, err := bolt.Open(file.Name(), 0666, nil) + require.NoError(t, err) + enclaveDb := &enclave_db.EnclaveDB{ + DB: db, + } + + return enclaveDb +} diff --git a/core/server/api_container/server/startosis_engine/startosis_interpreter_idempotent_test.go b/core/server/api_container/server/startosis_engine/startosis_interpreter_idempotent_test.go index f79d8efbdb..9cc41ac873 100644 --- a/core/server/api_container/server/startosis_engine/startosis_interpreter_idempotent_test.go +++ b/core/server/api_container/server/startosis_engine/startosis_interpreter_idempotent_test.go @@ -26,7 +26,10 @@ type StartosisInterpreterIdempotentTestSuite struct { func (suite *StartosisInterpreterIdempotentTestSuite) SetupTest() { suite.packageContentProvider = mock_package_content_provider.NewMockPackageContentProvider() - runtimeValueStore := runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(suite.T()) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(suite.T(), err) + serviceNetwork := service_network.NewMockServiceNetwork(suite.T()) serviceNetwork.EXPECT().GetApiContainerInfo().Maybe().Return( service_network.NewApiContainerInfo(net.IPv4(0, 0, 0, 0), uint16(1234), "0.0.0"), diff --git a/core/server/api_container/server/startosis_engine/startosis_interpreter_test.go b/core/server/api_container/server/startosis_engine/startosis_interpreter_test.go index b321387fba..4086fd449a 100644 --- a/core/server/api_container/server/startosis_engine/startosis_interpreter_test.go +++ b/core/server/api_container/server/startosis_engine/startosis_interpreter_test.go @@ -59,7 +59,10 @@ type StartosisInterpreterTestSuite struct { func (suite *StartosisInterpreterTestSuite) SetupTest() { suite.packageContentProvider = mock_package_content_provider.NewMockPackageContentProvider() - suite.runtimeValueStore = runtime_value_store.NewRuntimeValueStore() + enclaveDb := getEnclaveDBForTest(suite.T()) + runtimeValueStore, err := runtime_value_store.CreateRuntimeValueStore(enclaveDb) + require.NoError(suite.T(), err) + suite.runtimeValueStore = runtimeValueStore suite.serviceNetwork = service_network.NewMockServiceNetwork(suite.T()) suite.interpreter = NewStartosisInterpreter(suite.serviceNetwork, suite.packageContentProvider, suite.runtimeValueStore, "")