From a7b9f5ed20c6b5dbe2d9d0500ea5e06cb3a54945 Mon Sep 17 00:00:00 2001 From: Victor Colombo Date: Fri, 13 Oct 2023 13:56:35 -0300 Subject: [PATCH] feat: Add create enclave utils to SDK (#1550) ## Description: A very idiomatic pattern in Go is to use `defer` and closer functions to cleanup resources, instead of relying on memory to call the correct SDK calls when the test/setup is done. This is very common on our test suit that we have a util, that now is exposed to an external user. This PR also introduces a single SDK call to get from starlark to enclave, something that was not possible before. ## Is this change user facing? YES ## References (if applicable): https://github.com/kurtosis-tech/kurtosis/issues/1152 --- api/golang/util/create_enclave.go | 71 +++++++++++++++++++ .../golang/test_helpers/enclave_setup.go | 17 ++--- 2 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 api/golang/util/create_enclave.go diff --git a/api/golang/util/create_enclave.go b/api/golang/util/create_enclave.go new file mode 100644 index 0000000000..9a553c4ac1 --- /dev/null +++ b/api/golang/util/create_enclave.go @@ -0,0 +1,71 @@ +package util + +import ( + "context" + "github.com/kurtosis-tech/kurtosis/api/golang/core/lib/enclaves" + "github.com/kurtosis-tech/kurtosis/api/golang/core/lib/starlark_run_config" + "github.com/kurtosis-tech/kurtosis/api/golang/engine/lib/kurtosis_context" + "github.com/kurtosis-tech/stacktrace" +) + +func CreateEmptyEnclave(ctx context.Context, enclaveName string) (*enclaves.EnclaveContext, func() error, func() error, error) { + kurtosisCtx, err := kurtosis_context.NewKurtosisContextFromLocalEngine() + if err != nil { + return nil, nil, nil, stacktrace.Propagate(err, "Failed to get kurtosis context from local engine. Is the engine running? Try running 'kurtosis engine start'") + } + enclaveCtx, err := kurtosisCtx.CreateEnclave(ctx, enclaveName) + if err != nil { + return nil, nil, nil, stacktrace.Propagate(err, "Failed to create enclave.") + } + stopEnclaveFunc := func() error { + return kurtosisCtx.StopEnclave(ctx, enclaveName) + + } + destroyEnclaveFunc := func() error { + return kurtosisCtx.DestroyEnclave(ctx, enclaveName) + } + + return enclaveCtx, stopEnclaveFunc, destroyEnclaveFunc, nil +} + +func combineErrors(starlarkResult *enclaves.StarlarkRunResult, err error) error { + if err != nil { + return stacktrace.Propagate(err, "Failed to run Starlark during setup") + } + if starlarkResult.InterpretationError != nil { + return stacktrace.NewError("Failed to setup enclave using Starlark because of an interpretation error:\n%v", starlarkResult.InterpretationError) + } + if len(starlarkResult.ValidationErrors) > 0 { + return stacktrace.NewError("Failed to setup enclave using Starlark because of an interpretation error:\n%v", starlarkResult.ValidationErrors) + } + if starlarkResult.ExecutionError != nil { + return stacktrace.NewError("Failed to setup enclave using Starlark because of an execution error:\n%v", starlarkResult.ExecutionError) + } + return nil +} + +func CreateEnclaveFromStarlarkScript(ctx context.Context, enclaveName string, serializedScript string, runConfig *starlark_run_config.StarlarkRunConfig) (*enclaves.EnclaveContext, func() error, func() error, error) { + enclaveCtx, stopEnclaveFunc, destroyEnclaveFunc, err := CreateEmptyEnclave(ctx, enclaveName) + if err != nil { + return nil, nil, nil, stacktrace.Propagate(err, "Failed to create empty enclave") + } + starlarkResult, err := enclaveCtx.RunStarlarkScriptBlocking(ctx, serializedScript, runConfig) + err = combineErrors(starlarkResult, err) + if err != nil { + return nil, nil, nil, stacktrace.Propagate(err, "Failed to setup enclave using Starlark") + } + return enclaveCtx, stopEnclaveFunc, destroyEnclaveFunc, nil +} + +func CreateEnclaveFromStarlarkRemotePackage(ctx context.Context, enclaveName string, packageId string, runConfig *starlark_run_config.StarlarkRunConfig) (*enclaves.EnclaveContext, func() error, func() error, error) { + enclaveCtx, stopEnclaveFunc, destroyEnclaveFunc, err := CreateEmptyEnclave(ctx, enclaveName) + if err != nil { + return nil, nil, nil, stacktrace.Propagate(err, "Failed to create empty enclave") + } + starlarkResult, err := enclaveCtx.RunStarlarkRemotePackageBlocking(ctx, packageId, runConfig) + err = combineErrors(starlarkResult, err) + if err != nil { + return nil, nil, nil, stacktrace.Propagate(err, "Failed to setup enclave using Starlark") + } + return enclaveCtx, stopEnclaveFunc, destroyEnclaveFunc, nil +} diff --git a/internal_testsuites/golang/test_helpers/enclave_setup.go b/internal_testsuites/golang/test_helpers/enclave_setup.go index 66d24000ca..6da432a1c9 100644 --- a/internal_testsuites/golang/test_helpers/enclave_setup.go +++ b/internal_testsuites/golang/test_helpers/enclave_setup.go @@ -4,7 +4,7 @@ import ( "context" "fmt" "github.com/kurtosis-tech/kurtosis/api/golang/core/lib/enclaves" - "github.com/kurtosis-tech/kurtosis/api/golang/engine/lib/kurtosis_context" + "github.com/kurtosis-tech/kurtosis/api/golang/util" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" "testing" @@ -16,26 +16,23 @@ const ( ) func CreateEnclave(t *testing.T, ctx context.Context, testName string) (resultEnclaveCtx *enclaves.EnclaveContext, resultStopEnclaveFunc func(), resultDestroyEnclaveFunc func() error, resultErr error) { - kurtosisCtx, err := kurtosis_context.NewKurtosisContextFromLocalEngine() - require.NoError(t, err, "An error occurred connecting to the Kurtosis engine for running test '%v'", testName) enclaveName := fmt.Sprintf( "%v-%v-%v", testsuiteNameEnclaveIDFragment, testName, time.Now().Unix(), ) - enclaveCtx, err := kurtosisCtx.CreateEnclave(ctx, enclaveName) + enclaveCtx, stopEnclaveFunc, destroyEnclaveFunc, err := util.CreateEmptyEnclave(ctx, enclaveName) require.NoError(t, err, "An error occurred creating enclave '%v'", enclaveName) - stopEnclaveFunc := func() { - - if err := kurtosisCtx.StopEnclave(ctx, enclaveName); err != nil { + stopEnclaveFuncWrapped := func() { + if err := stopEnclaveFunc(); err != nil { logrus.Errorf("An error occurred stopping enclave '%v' that we created for this test:\n%v", enclaveName, err) logrus.Errorf("ACTION REQUIRED: You'll need to stop enclave '%v' manually!!!!", enclaveName) } } - destroyEnclaveFunc := func() error { - if err := kurtosisCtx.DestroyEnclave(ctx, enclaveName); err != nil { + destroyEnclaveFuncWrapped := func() error { + if err := destroyEnclaveFunc(); err != nil { logrus.Errorf("An error occurred destroying enclave '%v' that we created for this test:\n%v", enclaveName, err) logrus.Errorf("ACTION REQUIRED: You'll need to destroy enclave '%v' manually!!!!", enclaveName) return err @@ -43,5 +40,5 @@ func CreateEnclave(t *testing.T, ctx context.Context, testName string) (resultEn return nil } - return enclaveCtx, stopEnclaveFunc, destroyEnclaveFunc, nil + return enclaveCtx, stopEnclaveFuncWrapped, destroyEnclaveFuncWrapped, nil }