From 96f67712d83d9d89b1575b32f256522220a8ed94 Mon Sep 17 00:00:00 2001 From: Gyanendra Mishra Date: Tue, 12 Mar 2024 13:14:24 +0000 Subject: [PATCH 01/16] feat: add an add to GitHub button on an encalve (#2256) First frontend PR, please review properly Note that the instance id and api key should fill up when in cloud! --- .../modals/AddGithubActionModal.tsx | 50 +++++++++++++++++ .../widgets/AddGithubActionButton.tsx | 54 +++++++++++++++++++ .../app/src/emui/enclaves/enclave/Enclave.tsx | 2 + 3 files changed, 106 insertions(+) create mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/modals/AddGithubActionModal.tsx create mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/widgets/AddGithubActionButton.tsx diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/modals/AddGithubActionModal.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/modals/AddGithubActionModal.tsx new file mode 100644 index 0000000000..e0ee6609b1 --- /dev/null +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/modals/AddGithubActionModal.tsx @@ -0,0 +1,50 @@ +import { + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, +} from "@chakra-ui/react"; +import { FileDisplay } from "kurtosis-ui-components"; +import { apiKey, instanceUUID } from "../../../../cookies"; + +export type AddGithubActionModalProps = { + packageId: string; + isOpen: boolean; + onClose: () => void; +}; + +export const AddGithubActionModal = ({ isOpen, onClose, packageId }: AddGithubActionModalProps) => { + const commands = ` +name: CI +on: + pull_request: + +jobs: + run_kurtosis: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + - name: Run Kurtosis + uses: kurtosis-tech/kurtosis-github-action@v1 + with: + path: ${packageId} + cloud_instance_id: ${instanceUUID} + cloud_api_key: ${apiKey} # We recommend placing this in repository secrets;`; + return ( + + + + Run this enclave from GitHub + + + + + The GitHub Action allows you to run this package directly in CI + + + ); +}; diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/widgets/AddGithubActionButton.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/widgets/AddGithubActionButton.tsx new file mode 100644 index 0000000000..d827b2e56e --- /dev/null +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/widgets/AddGithubActionButton.tsx @@ -0,0 +1,54 @@ +import { Button, ButtonProps, Tooltip } from "@chakra-ui/react"; +import { isDefined } from "kurtosis-ui-components"; +import { useState } from "react"; +import { FiGithub } from "react-icons/fi"; +import { EnclaveFullInfo } from "../../types"; +import { AddGithubActionModal } from "../modals/AddGithubActionModal"; + +type AddGithubActionButtonProps = ButtonProps & { + enclave: EnclaveFullInfo; +}; + +export const AddGithubActionButton = ({ enclave, ...buttonProps }: AddGithubActionButtonProps) => { + const [showModal, setShowModal] = useState(false); + + if (!isDefined(enclave.starlarkRun)) { + return ( + + ); + } + + if (enclave.starlarkRun.isErr) { + return ( + + + + ); + } + + return ( + <> + + + + setShowModal(false)} + /> + + ); +}; diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/enclave/Enclave.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/enclave/Enclave.tsx index c13856c970..1ffbfd1820 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/enclave/Enclave.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/enclave/Enclave.tsx @@ -4,6 +4,7 @@ import { useNavigate, useParams } from "react-router-dom"; import { AppPageLayout, HoverLineTabList, KurtosisAlert, PageTitle } from "kurtosis-ui-components"; import { FunctionComponent } from "react"; import { EditEnclaveButton } from "../components/EditEnclaveButton"; +import { AddGithubActionButton } from "../components/widgets/AddGithubActionButton"; import { ConnectEnclaveButton } from "../components/widgets/ConnectEnclaveButton"; import { DeleteEnclavesButton } from "../components/widgets/DeleteEnclavesButton"; import { useFullEnclave } from "../EnclavesContext"; @@ -56,6 +57,7 @@ const EnclaveImpl = ({ enclave }: EnclaveImplProps) => { + From 2e90c672abe576c0ccfa385e95af59980678a395 Mon Sep 17 00:00:00 2001 From: Gyanendra Mishra Date: Tue, 12 Mar 2024 13:27:04 +0000 Subject: [PATCH 02/16] fix: image download mode always applies to k8s as well (#2271) Earlier this flag was limited to Docker but now it works on k8s too Closes #2246 Earlier `latest` defaulted to `Always` but now it will depend on the flag sent https://github.com/kubernetes/api/blob/master/core/v1/types.go#L2764-L2771 --- .../start_user_services.go | 23 +++-- .../objects/service/service_config.go | 9 ++ .../objects/service/service_config_test.go | 6 ++ .../service_registration/repository_test.go | 2 + .../default_service_network_test.go | 2 + .../startosis_engine/kurtosis_builtins.go | 6 +- .../add_service/add_service.go | 12 ++- .../add_service/add_service_shared.go | 1 + .../add_service/add_service_shared_test.go | 5 ++ .../add_service/add_services.go | 17 ++-- .../kurtosis_instruction/tasks/run_sh.go | 1 + .../tasks/tasks_shared.go | 2 + .../test_engine/add_service_framework_test.go | 5 +- .../add_services_framework_test.go | 6 +- ...full_framework_backward_compatible_test.go | 4 +- .../service_config_full_framework_test.go | 4 +- .../service_config_image_build_spec_test.go | 5 +- .../service_config_image_spec_minimal_test.go | 5 +- .../service_config_image_spec_test.go | 5 +- .../service_config_minimal_framework_test.go | 5 +- ...nfig_multiple_files_in_same_folder_test.go | 4 +- .../service_config_toleration_test.go | 4 +- .../service_config/service_config.go | 3 + .../startosis_engine/startosis_interpreter.go | 9 +- .../startosis_interpreter_idempotent_test.go | 25 ++++-- .../startosis_interpreter_test.go | 83 ++++++++++--------- .../startosis_engine/startosis_runner.go | 2 + 27 files changed, 181 insertions(+), 74 deletions(-) diff --git a/container-engine-lib/lib/backend_impls/kubernetes/kubernetes_kurtosis_backend/user_services_functions/start_user_services.go b/container-engine-lib/lib/backend_impls/kubernetes/kubernetes_kurtosis_backend/user_services_functions/start_user_services.go index 5c4a2c97a2..7521d2307a 100644 --- a/container-engine-lib/lib/backend_impls/kubernetes/kubernetes_kurtosis_backend/user_services_functions/start_user_services.go +++ b/container-engine-lib/lib/backend_impls/kubernetes/kubernetes_kurtosis_backend/user_services_functions/start_user_services.go @@ -3,6 +3,7 @@ package user_services_functions import ( "context" "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "strings" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service_user" @@ -311,6 +312,7 @@ func createStartServiceOperation( user := serviceConfig.GetUser() tolerations := serviceConfig.GetTolerations() nodeSelectors := serviceConfig.GetNodeSelectors() + imageDownloadMode := serviceConfig.GetImageDownloadMode() matchingObjectAndResources, found := servicesObjectsAndResources[serviceUuid] if !found { @@ -401,6 +403,7 @@ func createStartServiceOperation( minCpuAllocationMilliCpus, minMemoryAllocationMegabytes, user, + imageDownloadMode, ) if err != nil { return nil, stacktrace.Propagate(err, "An error occurred creating the container specs for the user service pod with image '%v'", containerImageName) @@ -640,6 +643,7 @@ func getUserServicePodContainerSpecs( minCpuAllocationMilliCpus uint64, minMemoryAllocationMegabytes uint64, user *service_user.ServiceUser, + imageDownloadMode image_download_mode.ImageDownloadMode, ) ([]apiv1.Container, error) { var containerEnvVars []apiv1.EnvVar @@ -682,18 +686,25 @@ func getUserServicePodContainerSpecs( Limits: resourceLimitsList, Requests: resourceRequestsList, } + + imagePullPolicy := apiv1.PullIfNotPresent + if imageDownloadMode == image_download_mode.ImageDownloadMode_Always { + imagePullPolicy = apiv1.PullAlways + } + // nolint: exhaustruct containers := []apiv1.Container{ { Name: userServiceContainerName, Image: image, // Yes, even though this is called "command" it actually corresponds to the Docker ENTRYPOINT - Command: entrypointArgs, - Args: cmdArgs, - Ports: kubernetesContainerPorts, - Env: containerEnvVars, - VolumeMounts: containerMounts, - Resources: resourceRequirements, + Command: entrypointArgs, + Args: cmdArgs, + Ports: kubernetesContainerPorts, + Env: containerEnvVars, + VolumeMounts: containerMounts, + Resources: resourceRequirements, + ImagePullPolicy: imagePullPolicy, // NOTE: There are a bunch of other interesting Container options that we omitted for now but might // want to specify in the future diff --git a/container-engine-lib/lib/backend_interface/objects/service/service_config.go b/container-engine-lib/lib/backend_interface/objects/service/service_config.go index 000aec8676..e2b3d75f41 100644 --- a/container-engine-lib/lib/backend_interface/objects/service/service_config.go +++ b/container-engine-lib/lib/backend_interface/objects/service/service_config.go @@ -2,6 +2,7 @@ package service import ( "encoding/json" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_build_spec" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_registry_spec" @@ -67,6 +68,8 @@ type privateServiceConfig struct { Tolerations []v1.Toleration NodeSelectors map[string]string + + ImageDownloadMode image_download_mode.ImageDownloadMode } func CreateServiceConfig( @@ -90,6 +93,7 @@ func CreateServiceConfig( user *service_user.ServiceUser, tolerations []v1.Toleration, nodeSelectors map[string]string, + imageDownloadMode image_download_mode.ImageDownloadMode, ) (*ServiceConfig, error) { if err := ValidateServiceConfigLabels(labels); err != nil { @@ -118,6 +122,7 @@ func CreateServiceConfig( User: user, Tolerations: tolerations, NodeSelectors: nodeSelectors, + ImageDownloadMode: imageDownloadMode, } return &ServiceConfig{internalServiceConfig}, nil } @@ -200,6 +205,10 @@ func (serviceConfig *ServiceConfig) GetTolerations() []v1.Toleration { return serviceConfig.privateServiceConfig.Tolerations } +func (serviceConfig *ServiceConfig) GetImageDownloadMode() image_download_mode.ImageDownloadMode { + return serviceConfig.privateServiceConfig.ImageDownloadMode +} + func (serviceConfig *ServiceConfig) MarshalJSON() ([]byte, error) { return json.Marshal(serviceConfig.privateServiceConfig) } diff --git a/container-engine-lib/lib/backend_interface/objects/service/service_config_test.go b/container-engine-lib/lib/backend_interface/objects/service/service_config_test.go index bd04e45709..b98a1a38ed 100644 --- a/container-engine-lib/lib/backend_interface/objects/service/service_config_test.go +++ b/container-engine-lib/lib/backend_interface/objects/service/service_config_test.go @@ -2,6 +2,7 @@ package service import ( "encoding/json" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_registry_spec" "testing" "time" @@ -88,6 +89,7 @@ func getServiceConfigForTest(t *testing.T, imageName string) *ServiceConfig { testServiceUser(), testToleration(), testNodeSelectors(), + testImageDownloadMode(), ) require.NoError(t, err) return serviceConfig @@ -216,3 +218,7 @@ func testNodeSelectors() map[string]string { "disktype": "ssd", } } + +func testImageDownloadMode() image_download_mode.ImageDownloadMode { + return image_download_mode.ImageDownloadMode_Missing +} diff --git a/container-engine-lib/lib/database_accessors/enclave_db/service_registration/repository_test.go b/container-engine-lib/lib/database_accessors/enclave_db/service_registration/repository_test.go index 5789167904..bd3e445137 100644 --- a/container-engine-lib/lib/database_accessors/enclave_db/service_registration/repository_test.go +++ b/container-engine-lib/lib/database_accessors/enclave_db/service_registration/repository_test.go @@ -2,6 +2,7 @@ package service_registration import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "math/rand" "net" "os" @@ -329,6 +330,7 @@ func getServiceConfigForTest(t *testing.T, imageName string) *service.ServiceCon map[string]string{ "disktype": "ssd", }, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(t, err) return serviceConfig diff --git a/core/server/api_container/server/service_network/default_service_network_test.go b/core/server/api_container/server/service_network/default_service_network_test.go index edafc21907..c3be34646a 100644 --- a/core/server/api_container/server/service_network/default_service_network_test.go +++ b/core/server/api_container/server/service_network/default_service_network_test.go @@ -8,6 +8,7 @@ package service_network import ( "context" "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "net" "net/netip" "os" @@ -1225,6 +1226,7 @@ func testServiceConfig(t *testing.T, imageName string) *service.ServiceConfig { nil, nil, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(t, err) return serviceConfig diff --git a/core/server/api_container/server/startosis_engine/kurtosis_builtins.go b/core/server/api_container/server/startosis_engine/kurtosis_builtins.go index 3152a6feb2..fff8ac7756 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_builtins.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_builtins.go @@ -1,6 +1,7 @@ package startosis_engine import ( + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/builtins" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/builtins/import_module" @@ -63,10 +64,11 @@ func KurtosisPlanInstructions( packageReplaceOptions map[string]string, nonBlockingMode bool, interpretationTimeValueStore *interpretation_time_value_store.InterpretationTimeValueStore, + imageDownloadMode image_download_mode.ImageDownloadMode, ) []*kurtosis_plan_instruction.KurtosisPlanInstruction { return []*kurtosis_plan_instruction.KurtosisPlanInstruction{ - add_service.NewAddService(serviceNetwork, runtimeValueStore, packageId, packageContentProvider, packageReplaceOptions, interpretationTimeValueStore), - add_service.NewAddServices(serviceNetwork, runtimeValueStore, packageId, packageContentProvider, packageReplaceOptions, interpretationTimeValueStore), + add_service.NewAddService(serviceNetwork, runtimeValueStore, packageId, packageContentProvider, packageReplaceOptions, interpretationTimeValueStore, imageDownloadMode), + add_service.NewAddServices(serviceNetwork, runtimeValueStore, packageId, packageContentProvider, packageReplaceOptions, interpretationTimeValueStore, imageDownloadMode), get_service.NewGetService(interpretationTimeValueStore), verify.NewVerify(runtimeValueStore), exec.NewExec(serviceNetwork, runtimeValueStore), 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 5a10e1e47d..14c8c11d39 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 @@ -3,6 +3,7 @@ package add_service import ( "context" "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_plan_persistence" @@ -36,7 +37,8 @@ func NewAddService( packageId string, packageContentProvider startosis_packages.PackageContentProvider, packageReplaceOptions map[string]string, - interpretationTimeValueStore *interpretation_time_value_store.InterpretationTimeValueStore) *kurtosis_plan_instruction.KurtosisPlanInstruction { + interpretationTimeValueStore *interpretation_time_value_store.InterpretationTimeValueStore, + imageDownloadMode image_download_mode.ImageDownloadMode) *kurtosis_plan_instruction.KurtosisPlanInstruction { return &kurtosis_plan_instruction.KurtosisPlanInstruction{ KurtosisBaseBuiltin: &kurtosis_starlark_framework.KurtosisBaseBuiltin{ Name: AddServiceBuiltinName, @@ -81,6 +83,8 @@ func NewAddService( interpretationTimeValueStore: interpretationTimeValueStore, description: "", // populated at interpretation time + + imageDownloadMode: imageDownloadMode, } }, @@ -108,6 +112,8 @@ type AddServiceCapabilities struct { resultUuid string description string + + imageDownloadMode image_download_mode.ImageDownloadMode } func (builtin *AddServiceCapabilities) Interpret(locatorOfModuleInWhichThisBuiltInIsBeingCalled string, arguments *builtin_argument.ArgumentValuesSet) (starlark.Value, *startosis_errors.InterpretationError) { @@ -127,6 +133,7 @@ func (builtin *AddServiceCapabilities) Interpret(locatorOfModuleInWhichThisBuilt builtin.packageId, builtin.packageContentProvider, builtin.packageReplaceOptions, + builtin.imageDownloadMode, ) if interpretationErr != nil { return nil, interpretationErr @@ -259,6 +266,7 @@ func validateAndConvertConfigAndReadyCondition( packageId string, packageContentProvider startosis_packages.PackageContentProvider, packageReplaceOptions map[string]string, + imageDownloadMode image_download_mode.ImageDownloadMode, ) (*service.ServiceConfig, *service_config.ReadyCondition, *startosis_errors.InterpretationError) { config, ok := rawConfig.(*service_config.ServiceConfig) if !ok { @@ -269,7 +277,7 @@ func validateAndConvertConfigAndReadyCondition( locatorOfModuleInWhichThisBuiltInIsBeingCalled, packageId, packageContentProvider, - packageReplaceOptions) + packageReplaceOptions, imageDownloadMode) if interpretationErr != nil { return nil, nil, interpretationErr } 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 91f7c54744..72daad2547 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 @@ -217,6 +217,7 @@ func replaceMagicStrings( serviceConfig.GetUser(), serviceConfig.GetTolerations(), serviceConfig.GetNodeSelectors(), + serviceConfig.GetImageDownloadMode(), ) if err != nil { return "", nil, stacktrace.Propagate(err, "An error occurred creating a service config") 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 042c0bbe17..da5e93e38c 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 @@ -2,6 +2,7 @@ package add_service import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "os" "testing" @@ -58,6 +59,7 @@ func TestAddServiceShared_EntryPointArgsRuntimeValueAreReplaced(t *testing.T) { nil, nil, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(t, err) @@ -105,6 +107,7 @@ func TestAddServiceShared_CmdArgsRuntimeValueAreReplaced(t *testing.T) { nil, nil, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(t, err) @@ -154,6 +157,7 @@ func TestAddServiceShared_EnvVarsWithRuntimeValueAreReplaced(t *testing.T) { nil, nil, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(t, err) @@ -204,6 +208,7 @@ func TestAddServiceShared_ServiceNameWithRuntimeValuesAreReplaced(t *testing.T) nil, nil, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(t, err) 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 65cddd2b68..1fa9f3a4b1 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 @@ -3,6 +3,7 @@ package add_service import ( "context" "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_plan_persistence" @@ -39,7 +40,8 @@ func NewAddServices( packageId string, packageContentProvider startosis_packages.PackageContentProvider, packageReplaceOptions map[string]string, - interpretationTimeValueStore *interpretation_time_value_store.InterpretationTimeValueStore) *kurtosis_plan_instruction.KurtosisPlanInstruction { + interpretationTimeValueStore *interpretation_time_value_store.InterpretationTimeValueStore, + imageDownloadMode image_download_mode.ImageDownloadMode) *kurtosis_plan_instruction.KurtosisPlanInstruction { return &kurtosis_plan_instruction.KurtosisPlanInstruction{ KurtosisBaseBuiltin: &kurtosis_starlark_framework.KurtosisBaseBuiltin{ Name: AddServicesBuiltinName, @@ -71,9 +73,10 @@ func NewAddServices( serviceConfigs: nil, // populated at interpretation time interpretationTimeValueStore: interpretationTimeValueStore, - resultUuids: map[service.ServiceName]string{}, // populated at interpretation time - readyConditions: nil, // populated at interpretation time - description: "", // populated at interpretation time + resultUuids: map[service.ServiceName]string{}, // populated at interpretation time + readyConditions: nil, // populated at interpretation time + description: "", // populated at interpretation time + imageDownloadMode: imageDownloadMode, } }, @@ -99,6 +102,8 @@ type AddServicesCapabilities struct { resultUuids map[service.ServiceName]string description string + + imageDownloadMode image_download_mode.ImageDownloadMode } func (builtin *AddServicesCapabilities) Interpret(locatorOfModuleInWhichThisBuiltInIsBeingCalled string, arguments *builtin_argument.ArgumentValuesSet) (starlark.Value, *startosis_errors.InterpretationError) { @@ -113,6 +118,7 @@ func (builtin *AddServicesCapabilities) Interpret(locatorOfModuleInWhichThisBuil builtin.packageId, builtin.packageContentProvider, builtin.packageReplaceOptions, + builtin.imageDownloadMode, ) if interpretationErr != nil { return nil, interpretationErr @@ -416,6 +422,7 @@ func validateAndConvertConfigsAndReadyConditions( packageId string, packageContentProvider startosis_packages.PackageContentProvider, packageReplaceOptions map[string]string, + imageDownloadMode image_download_mode.ImageDownloadMode, ) ( map[service.ServiceName]*service.ServiceConfig, map[service.ServiceName]*service_config.ReadyCondition, @@ -444,7 +451,7 @@ func validateAndConvertConfigsAndReadyConditions( if !isDictValueAServiceConfig { return nil, nil, startosis_errors.NewInterpretationError("One value of the '%s' dictionary is not a ServiceConfig (was '%s'). Values of this argument should correspond to the config of the service to be added", ConfigsArgName, reflect.TypeOf(dictValue)) } - apiServiceConfig, interpretationErr := serviceConfig.ToKurtosisType(serviceNetwork, locatorOfModuleInWhichThisBuiltInIsBeingCalled, packageId, packageContentProvider, packageReplaceOptions) + apiServiceConfig, interpretationErr := serviceConfig.ToKurtosisType(serviceNetwork, locatorOfModuleInWhichThisBuiltInIsBeingCalled, packageId, packageContentProvider, packageReplaceOptions, imageDownloadMode) if interpretationErr != nil { return nil, nil, interpretationErr } 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 be32399c8f..e4d5f21eaa 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 @@ -338,6 +338,7 @@ func repacaeMagicStringsInEnvVars(runtimeValueStore *runtime_value_store.Runtime serviceConfig.GetUser(), serviceConfig.GetTolerations(), serviceConfig.GetNodeSelectors(), + serviceConfig.GetImageDownloadMode(), ) if err != nil { return nil, stacktrace.Propagate(err, "An error occurred creating a service config with env var magric strings replaced.") diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/tasks/tasks_shared.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/tasks/tasks_shared.go index 9e683100bf..d5d728b7fd 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/tasks/tasks_shared.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/tasks/tasks_shared.go @@ -3,6 +3,7 @@ package tasks import ( "context" "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "reflect" "strings" "time" @@ -281,6 +282,7 @@ func getServiceConfig( nil, nil, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) if err != nil { return nil, stacktrace.Propagate(err, "An error occurred creating service config") 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 774ace3ec0..f2acd9ebde 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 @@ -2,6 +2,7 @@ package test_engine import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/interpretation_time_value_store" "testing" @@ -56,6 +57,7 @@ func (suite *KurtosisPlanInstructionTestSuite) TestAddService() { nil, nil, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(suite.T(), err) @@ -84,7 +86,8 @@ func (t *addServiceTestCase) GetInstruction() *kurtosis_plan_instruction.Kurtosi testModulePackageId, t.packageContentProvider, testNoPackageReplaceOptions, - t.interpretationTimeValueStore) + t.interpretationTimeValueStore, + image_download_mode.ImageDownloadMode_Missing) } func (t *addServiceTestCase) GetStarlarkCode() string { 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 e70931009e..8ff41e63a5 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 @@ -2,6 +2,7 @@ package test_engine import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/interpretation_time_value_store" "io" "net/http" @@ -72,6 +73,7 @@ func (suite *KurtosisPlanInstructionTestSuite) TestAddServices() { nil, nil, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(suite.T(), err) @@ -99,6 +101,7 @@ func (suite *KurtosisPlanInstructionTestSuite) TestAddServices() { nil, nil, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(suite.T(), err) @@ -218,7 +221,8 @@ func (t *addServicesTestCase) GetInstruction() *kurtosis_plan_instruction.Kurtos testModulePackageId, t.packageContentProvider, testNoPackageReplaceOptions, - t.interpretationTimeValueStore) + t.interpretationTimeValueStore, + image_download_mode.ImageDownloadMode_Missing) } func (t *addServicesTestCase) GetStarlarkCode() string { diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_full_framework_backward_compatible_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_full_framework_backward_compatible_test.go index 865cef63e9..5fd85163e2 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_full_framework_backward_compatible_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_full_framework_backward_compatible_test.go @@ -2,6 +2,7 @@ package test_engine import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/port_spec" "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_starlark_framework/builtin_argument" @@ -59,7 +60,8 @@ func (t *serviceConfigFullTestCaseBackwardCompatible) Assert(typeValue builtin_a testModulePackageId, testModuleMainFileLocator, t.packageContentProvider, - map[string]string{}) + map[string]string{}, + image_download_mode.ImageDownloadMode_Missing) require.Nil(t, err) require.Equal(t, testContainerImageName, serviceConfig.GetContainerImageName()) diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_full_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_full_framework_test.go index 7cbc5dbebb..ad489f63b8 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_full_framework_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_full_framework_test.go @@ -2,6 +2,7 @@ package test_engine import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "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_directory" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network" @@ -68,7 +69,8 @@ func (t *serviceConfigFullTestCase) Assert(typeValue builtin_argument.KurtosisVa testModulePackageId, testModuleMainFileLocator, t.packageContentProvider, - testNoPackageReplaceOptions) + testNoPackageReplaceOptions, + image_download_mode.ImageDownloadMode_Missing) require.Nil(t, err) require.Equal(t, testContainerImageName, serviceConfig.GetContainerImageName()) diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_build_spec_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_build_spec_test.go index 64740547f7..9c5cab78e4 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_build_spec_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_build_spec_test.go @@ -2,6 +2,7 @@ package test_engine import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "testing" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_build_spec" @@ -61,7 +62,8 @@ func (t *serviceConfigImageBuildSpecTestCase) Assert(typeValue builtin_argument. testModuleMainFileLocator, testModulePackageId, t.packageContentProvider, - testNoPackageReplaceOptions) + testNoPackageReplaceOptions, + image_download_mode.ImageDownloadMode_Missing) require.Nil(t, interpretationErr) expectedImageBuildSpec := image_build_spec.NewImageBuildSpec( @@ -89,6 +91,7 @@ func (t *serviceConfigImageBuildSpecTestCase) Assert(typeValue builtin_argument. nil, nil, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(t, err) require.Equal(t, expectedServiceConfig, serviceConfig) diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_spec_minimal_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_spec_minimal_test.go index 13698b4ff8..27dd267f7b 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_spec_minimal_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_spec_minimal_test.go @@ -2,6 +2,7 @@ package test_engine import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_registry_spec" "testing" @@ -48,7 +49,8 @@ func (t *serviceConfigImageSpecMinimalTest) Assert(typeValue builtin_argument.Ku testModuleMainFileLocator, testModulePackageId, t.packageContentProvider, - testNoPackageReplaceOptions) + testNoPackageReplaceOptions, + image_download_mode.ImageDownloadMode_Missing) require.Nil(t, interpretationErr) expectedImageRegistrySpec := image_registry_spec.NewImageRegistrySpec(testContainerImageName, "", "", "") @@ -73,6 +75,7 @@ func (t *serviceConfigImageSpecMinimalTest) Assert(typeValue builtin_argument.Ku nil, nil, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(t, err) require.Equal(t, expectedServiceConfig, serviceConfig) diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_spec_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_spec_test.go index d07e6a1ff6..206ca1b935 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_spec_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_spec_test.go @@ -2,6 +2,7 @@ package test_engine import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_registry_spec" "testing" @@ -54,7 +55,8 @@ func (t *serviceConfigImageSpecTest) Assert(typeValue builtin_argument.KurtosisV testModuleMainFileLocator, testModulePackageId, t.packageContentProvider, - testNoPackageReplaceOptions) + testNoPackageReplaceOptions, + image_download_mode.ImageDownloadMode_Missing) require.Nil(t, interpretationErr) expectedImageRegistrySpec := image_registry_spec.NewImageRegistrySpec(testContainerImageName, testRegistryUsername, testRegistryPassword, testRegistryAddr) @@ -79,6 +81,7 @@ func (t *serviceConfigImageSpecTest) Assert(typeValue builtin_argument.KurtosisV nil, nil, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(t, err) require.Equal(t, expectedServiceConfig, serviceConfig) diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_minimal_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_minimal_framework_test.go index 1199948dc0..a91a9c6fbd 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_minimal_framework_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_minimal_framework_test.go @@ -2,6 +2,7 @@ package test_engine import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "testing" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/port_spec" @@ -42,7 +43,8 @@ func (t *serviceConfigMinimalTestCase) Assert(typeValue builtin_argument.Kurtosi testModulePackageId, testModuleMainFileLocator, t.packageContentProvider, - testNoPackageReplaceOptions) + testNoPackageReplaceOptions, + image_download_mode.ImageDownloadMode_Missing) require.Nil(t, interpretationErr) expectedServiceConfig, err := service.CreateServiceConfig( @@ -66,6 +68,7 @@ func (t *serviceConfigMinimalTestCase) Assert(typeValue builtin_argument.Kurtosi nil, nil, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(t, err) require.Equal(t, expectedServiceConfig, serviceConfig) diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_multiple_files_in_same_folder_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_multiple_files_in_same_folder_test.go index 02bac8a2bd..bdc28f9f4f 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_multiple_files_in_same_folder_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_multiple_files_in_same_folder_test.go @@ -2,6 +2,7 @@ package test_engine import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "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_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/directory" @@ -51,7 +52,8 @@ func (t *serviceConfigMultipleFilesInSameFolderTestCase) Assert(typeValue builti testModulePackageId, testModuleMainFileLocator, t.packageContentProvider, - testNoPackageReplaceOptions) + testNoPackageReplaceOptions, + image_download_mode.ImageDownloadMode_Missing) require.Nil(t, err) require.Equal(t, testContainerImageName, serviceConfig.GetContainerImageName()) diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_toleration_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_toleration_test.go index 09f32a09a5..6eb6fb421f 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_toleration_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_toleration_test.go @@ -2,6 +2,7 @@ package test_engine import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "testing" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/port_spec" @@ -57,7 +58,7 @@ func (t *serviceConfigTolerationTest) Assert(typeValue builtin_argument.Kurtosis testModuleMainFileLocator, testModulePackageId, t.packageContentProvider, - testNoPackageReplaceOptions) + testNoPackageReplaceOptions, image_download_mode.ImageDownloadMode_Missing) require.Nil(t, interpretationErr) expectedTolerations := []v1.Toleration{{Key: testTolerationKey, Operator: v1.TolerationOpEqual, Value: testTolerationValue, Effect: v1.TaintEffectNoSchedule, TolerationSeconds: &testTolerationSeconds}} expectedServiceConfig, err := service.CreateServiceConfig( @@ -81,6 +82,7 @@ func (t *serviceConfigTolerationTest) Assert(typeValue builtin_argument.Kurtosis nil, expectedTolerations, map[string]string{}, + image_download_mode.ImageDownloadMode_Missing, ) require.NoError(t, err) require.Equal(t, expectedServiceConfig, serviceConfig) diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/service_config.go b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/service_config.go index 00afb3c834..9eefb07312 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/service_config.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/service_config.go @@ -2,6 +2,7 @@ package service_config import ( "fmt" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_registry_spec" "math" "path" @@ -249,6 +250,7 @@ func (config *ServiceConfig) ToKurtosisType( packageId string, packageContentProvider startosis_packages.PackageContentProvider, packageReplaceOptions map[string]string, + imageDownloadMode image_download_mode.ImageDownloadMode, ) (*service.ServiceConfig, *startosis_errors.InterpretationError) { var ok bool @@ -522,6 +524,7 @@ func (config *ServiceConfig) ToKurtosisType( serviceUser, tolerations, nodeSelectors, + imageDownloadMode, ) if err != nil { return nil, startosis_errors.WrapWithInterpretationError(err, "An error occurred creating a service config") diff --git a/core/server/api_container/server/startosis_engine/startosis_interpreter.go b/core/server/api_container/server/startosis_engine/startosis_interpreter.go index 91740fe74d..6b37e26add 100644 --- a/core/server/api_container/server/startosis_engine/startosis_interpreter.go +++ b/core/server/api_container/server/startosis_engine/startosis_interpreter.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "github.com/kurtosis-tech/kurtosis/api/golang/core/kurtosis_core_rpc_api_bindings" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/builtins" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/builtins/print_builtin" @@ -95,6 +96,7 @@ func (interpreter *StartosisInterpreter) InterpretAndOptimizePlan( serializedJsonParams string, nonBlockingMode bool, currentEnclavePlan *enclave_plan_persistence.EnclavePlan, + imageDownloadMode image_download_mode.ImageDownloadMode, ) (string, *instructions_plan.InstructionsPlan, *kurtosis_core_rpc_api_bindings.StarlarkInterpretationError) { if interpretationErr := interpreter.packageContentProvider.CloneReplacedPackagesIfNeeded(packageReplaceOptions); interpretationErr != nil { @@ -104,7 +106,7 @@ func (interpreter *StartosisInterpreter) InterpretAndOptimizePlan( // run interpretation with no mask at all to generate the list of instructions as if the enclave was empty enclaveComponents := enclave_structure.NewEnclaveComponents() emptyPlanInstructionsMask := resolver.NewInstructionsPlanMask(0) - naiveInstructionsPlanSerializedScriptOutput, naiveInstructionsPlan, interpretationErrorApi := interpreter.Interpret(ctx, packageId, mainFunctionName, packageReplaceOptions, relativePathtoMainFile, serializedStarlark, serializedJsonParams, nonBlockingMode, enclaveComponents, emptyPlanInstructionsMask) + naiveInstructionsPlanSerializedScriptOutput, naiveInstructionsPlan, interpretationErrorApi := interpreter.Interpret(ctx, packageId, mainFunctionName, packageReplaceOptions, relativePathtoMainFile, serializedStarlark, serializedJsonParams, nonBlockingMode, enclaveComponents, emptyPlanInstructionsMask, imageDownloadMode) if interpretationErrorApi != nil { return startosis_constants.NoOutputObject, nil, interpretationErrorApi } @@ -174,7 +176,7 @@ func (interpreter *StartosisInterpreter) InterpretAndOptimizePlan( } // Now that we have a potential plan mask, try running interpretation again using this plan mask - attemptSerializedScriptOutput, attemptInstructionsPlan, interpretationErrorApi := interpreter.Interpret(ctx, packageId, mainFunctionName, packageReplaceOptions, relativePathtoMainFile, serializedStarlark, serializedJsonParams, nonBlockingMode, enclaveComponents, potentialMask) + attemptSerializedScriptOutput, attemptInstructionsPlan, interpretationErrorApi := interpreter.Interpret(ctx, packageId, mainFunctionName, packageReplaceOptions, relativePathtoMainFile, serializedStarlark, serializedJsonParams, nonBlockingMode, enclaveComponents, potentialMask, imageDownloadMode) if interpretationErrorApi != nil { // Note: there's no real reason why this interpretation would fail with an error, given that the package // has been interpreted once already (right above). But to be on the safe side, check the error @@ -225,6 +227,7 @@ func (interpreter *StartosisInterpreter) Interpret( nonBlockingMode bool, enclaveComponents *enclave_structure.EnclaveComponents, instructionsPlanMask *resolver.InstructionsPlanMask, + imageDownloadMode image_download_mode.ImageDownloadMode, ) (string, *instructions_plan.InstructionsPlan, *kurtosis_core_rpc_api_bindings.StarlarkInterpretationError) { interpreter.mutex.Lock() defer interpreter.mutex.Unlock() @@ -273,7 +276,7 @@ func (interpreter *StartosisInterpreter) Interpret( if mainFuncParamsNum >= minimumParamsRequiredForPlan { firstParamName, _ := mainFunction.Param(planParamIndex) if firstParamName == planParamName { - kurtosisPlanInstructions := KurtosisPlanInstructions(packageId, interpreter.serviceNetwork, interpreter.recipeExecutor, interpreter.packageContentProvider, packageReplaceOptions, nonBlockingMode, interpreter.interpretationTimeValueStore) + kurtosisPlanInstructions := KurtosisPlanInstructions(packageId, interpreter.serviceNetwork, interpreter.recipeExecutor, interpreter.packageContentProvider, packageReplaceOptions, nonBlockingMode, interpreter.interpretationTimeValueStore, imageDownloadMode) planModule := plan_module.PlanModule(newInstructionsPlan, enclaveComponents, interpreter.starlarkValueSerde, instructionsPlanMask, kurtosisPlanInstructions) argsTuple = append(argsTuple, planModule) } 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 f60f45a376..7aebb3e0cc 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 @@ -4,6 +4,7 @@ import ( "context" "github.com/google/uuid" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/enclave" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_plan_persistence" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_structure" @@ -103,7 +104,8 @@ func (suite *StartosisInterpreterIdempotentTestSuite) TestInterpretAndOptimize_I noInputParams, defaultNonBlockingMode, enclave_structure.NewEnclaveComponents(), - resolver.NewInstructionsPlanMask(0)) + resolver.NewInstructionsPlanMask(0), + image_download_mode.ImageDownloadMode_Missing) require.Nil(suite.T(), interpretationApiErr) require.Equal(suite.T(), 3, currentEnclavePlan.Size()) convertedEnclavePlan := suite.convertInstructionPlanToEnclavePlan(currentEnclavePlan) @@ -119,6 +121,7 @@ func (suite *StartosisInterpreterIdempotentTestSuite) TestInterpretAndOptimize_I noInputParams, defaultNonBlockingMode, convertedEnclavePlan, + image_download_mode.ImageDownloadMode_Missing, ) require.Nil(suite.T(), interpretationError) @@ -160,7 +163,8 @@ func (suite *StartosisInterpreterIdempotentTestSuite) TestInterpretAndOptimize_A noInputParams, defaultNonBlockingMode, enclave_structure.NewEnclaveComponents(), - resolver.NewInstructionsPlanMask(0)) + resolver.NewInstructionsPlanMask(0), + image_download_mode.ImageDownloadMode_Missing) require.Nil(suite.T(), interpretationApiErr) require.Equal(suite.T(), 2, currentEnclavePlan.Size()) convertedEnclavePlan := suite.convertInstructionPlanToEnclavePlan(currentEnclavePlan) @@ -181,6 +185,7 @@ func (suite *StartosisInterpreterIdempotentTestSuite) TestInterpretAndOptimize_A noInputParams, defaultNonBlockingMode, convertedEnclavePlan, + image_download_mode.ImageDownloadMode_Missing, ) require.Nil(suite.T(), interpretationError) @@ -223,7 +228,8 @@ func (suite *StartosisInterpreterIdempotentTestSuite) TestInterpretAndOptimize_D noInputParams, defaultNonBlockingMode, enclave_structure.NewEnclaveComponents(), - resolver.NewInstructionsPlanMask(0)) + resolver.NewInstructionsPlanMask(0), + image_download_mode.ImageDownloadMode_Missing) require.Nil(suite.T(), interpretationApiErr) require.Equal(suite.T(), 2, currentEnclavePlan.Size()) convertedEnclavePlan := suite.convertInstructionPlanToEnclavePlan(currentEnclavePlan) @@ -242,6 +248,7 @@ func (suite *StartosisInterpreterIdempotentTestSuite) TestInterpretAndOptimize_D noInputParams, defaultNonBlockingMode, convertedEnclavePlan, + image_download_mode.ImageDownloadMode_Missing, ) require.Nil(suite.T(), interpretationError) @@ -278,7 +285,8 @@ func (suite *StartosisInterpreterIdempotentTestSuite) TestInterpretAndOptimize_I noInputParams, defaultNonBlockingMode, enclave_structure.NewEnclaveComponents(), - resolver.NewInstructionsPlanMask(0)) + resolver.NewInstructionsPlanMask(0), + image_download_mode.ImageDownloadMode_Missing) require.Nil(suite.T(), interpretationApiErr) require.Equal(suite.T(), 3, currentEnclavePlan.Size()) convertedEnclavePlan := suite.convertInstructionPlanToEnclavePlan(currentEnclavePlan) @@ -299,6 +307,7 @@ func (suite *StartosisInterpreterIdempotentTestSuite) TestInterpretAndOptimize_I noInputParams, defaultNonBlockingMode, convertedEnclavePlan, + image_download_mode.ImageDownloadMode_Missing, ) require.Nil(suite.T(), interpretationError) @@ -341,7 +350,8 @@ func (suite *StartosisInterpreterIdempotentTestSuite) TestInterpretAndOptimize_A noInputParams, defaultNonBlockingMode, enclave_structure.NewEnclaveComponents(), - resolver.NewInstructionsPlanMask(0)) + resolver.NewInstructionsPlanMask(0), + image_download_mode.ImageDownloadMode_Missing) require.Nil(suite.T(), interpretationApiErr) require.Equal(suite.T(), 4, currentEnclavePlan.Size()) convertedEnclavePlan := suite.convertInstructionPlanToEnclavePlan(currentEnclavePlan) @@ -363,6 +373,7 @@ func (suite *StartosisInterpreterIdempotentTestSuite) TestInterpretAndOptimize_A noInputParams, defaultNonBlockingMode, convertedEnclavePlan, + image_download_mode.ImageDownloadMode_Missing, ) require.Nil(suite.T(), interpretationError) @@ -414,7 +425,8 @@ func (suite *StartosisInterpreterIdempotentTestSuite) TestInterpretAndOptimize_U noInputParams, defaultNonBlockingMode, enclave_structure.NewEnclaveComponents(), - resolver.NewInstructionsPlanMask(0)) + resolver.NewInstructionsPlanMask(0), + image_download_mode.ImageDownloadMode_Missing) require.Nil(suite.T(), interpretationApiErr) require.Equal(suite.T(), 4, currentEnclavePlan.Size()) convertedEnclavePlan := suite.convertInstructionPlanToEnclavePlan(currentEnclavePlan) @@ -441,6 +453,7 @@ func (suite *StartosisInterpreterIdempotentTestSuite) TestInterpretAndOptimize_U noInputParams, defaultNonBlockingMode, convertedEnclavePlan, + image_download_mode.ImageDownloadMode_Missing, ) require.Nil(suite.T(), interpretationError) 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 c585fc3717..108cb3f7b9 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 @@ -6,6 +6,7 @@ import ( "fmt" "github.com/kurtosis-tech/kurtosis/api/golang/core/lib/binding_constructors" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/enclave" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/builtins/print_builtin" @@ -50,6 +51,8 @@ const ( mockEnclaveUuid = "enclave-uuid" serviceUuidSuffix = "uuid" mockFileArtifactName = "mock-artifact-id" + + defaultImageDownloadMode = image_download_mode.ImageDownloadMode_Missing ) type StartosisInterpreterTestSuite struct { @@ -107,7 +110,7 @@ def run(plan): plan.print("` + testString + `") ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 1, instructionsPlan.Size()) // Only the print statement @@ -128,7 +131,7 @@ def deploy_contract(plan,service_name,contract_name,init_message,args): mainFunctionName := "deploy_contract" inputArgs := `{"service_name": "my-service", "contract_name": "my-contract", "init_message": "Init message", "args": {"arg1": "arg1-value", "arg2": "arg2-value"}}` - result, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, mainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, inputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + result, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, mainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, inputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 3, instructionsPlan.Size()) // The three print functions require.NotNil(suite.T(), result) @@ -149,7 +152,7 @@ def my_func(my_arg1, my_arg2, args): mainFunctionName := "my_func" inputArgs := `{"my_arg1": "foo", "my_arg2": "bar", "args": {"arg1": "arg1-value", "arg2": "arg2-value"}}` - result, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, mainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, inputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + result, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, mainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, inputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 0, instructionsPlan.Size()) // There are no instructions to execute require.NotNil(suite.T(), result) @@ -166,7 +169,7 @@ def run(plan): plan.print(my_dict) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 2, instructionsPlan.Size()) @@ -184,7 +187,7 @@ def run(plan): unknownInstruction() ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) expectedError := startosis_errors.NewInterpretationErrorWithCustomMsg( []startosis_errors.CallFrame{ @@ -205,7 +208,7 @@ unknownVariable unknownInstruction2() ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) expectedError := startosis_errors.NewInterpretationErrorWithCustomMsg( []startosis_errors.CallFrame{ @@ -227,7 +230,7 @@ def run(): load("otherScript.start") # fails b/c load takes in at least 2 args ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) expectedError := startosis_errors.NewInterpretationErrorFromStacktrace( []startosis_errors.CallFrame{ @@ -259,7 +262,7 @@ def run(plan): plan.print("The grpc transport protocol is " + datastore_service.ports["grpc"].transport_protocol) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, fmt.Sprintf(script, testServiceName), startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, fmt.Sprintf(script, testServiceName), startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 5, instructionsPlan.Size()) @@ -294,7 +297,7 @@ def run(plan): plan.print("The transport protocol is " + datastore_service.ports["grpc"].transport_protocol) plan.print("The application protocol is " + datastore_service.ports["grpc"].application_protocol) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, fmt.Sprintf(script, testServiceName), startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, fmt.Sprintf(script, testServiceName), startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 6, instructionsPlan.Size()) @@ -324,7 +327,7 @@ def run(plan): plan.add_service(name = service_name, config = config) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) expectedError := startosis_errors.NewInterpretationErrorWithCauseAndCustomMsg( errors.New("ServiceConfig: missing argument for image"), @@ -355,7 +358,7 @@ def run(plan): plan.add_service(name = service_name, config = config) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) expectedError := startosis_errors.NewInterpretationErrorWithCauseAndCustomMsg( startosis_errors.NewInterpretationError(`The following argument(s) could not be parsed or did not pass validation: {"transport_protocol":"Invalid argument value for 'transport_protocol': 'TCPK'. Valid values are TCP, SCTP, UDP"}`), []startosis_errors.CallFrame{ @@ -385,7 +388,7 @@ def run(plan): plan.add_service(name = service_name, config = config) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) expectedError := startosis_errors.NewInterpretationErrorWithCauseAndCustomMsg( startosis_errors.NewInterpretationError(`The following argument(s) could not be parsed or did not pass validation: {"number":"Value for 'number' was expected to be an integer between 1 and 65535, but it was 'starlark.String'"}`), []startosis_errors.CallFrame{ @@ -425,7 +428,7 @@ def run(plan): plan.print("Done!") ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 8, instructionsPlan.Size()) @@ -453,7 +456,7 @@ load("` + barModulePath + `", "a") def run(plan): plan.print("Hello " + a) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) expectedError := startosis_errors.NewInterpretationErrorWithCustomMsg( []startosis_errors.CallFrame{ *startosis_errors.NewCallFrame("", startosis_errors.NewScriptPosition(startosis_constants.PackageIdPlaceholderForStandaloneScript, 2, 1)), @@ -476,7 +479,7 @@ my_module = import_module("` + barModulePath + `") def run(plan): plan.print("Hello " + my_module.a) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 1, instructionsPlan.Size()) // Only the print statement @@ -500,7 +503,7 @@ def run(plan): plan.print(module_doo.b) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 1, instructionsPlan.Size()) @@ -524,7 +527,7 @@ def run(plan): plan.print(module_doo.b) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) expectedError := startosis_errors.NewInterpretationErrorWithCustomMsg( []startosis_errors.CallFrame{ *startosis_errors.NewCallFrame("", startosis_errors.NewScriptPosition(moduleBarLoadsModuleDoo, 1, 27)), @@ -545,7 +548,7 @@ def run(plan): plan.print(my_module.b) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) errorMsg := `Evaluation error: An error occurred while loading the module '` + nonExistentModule + `' Caused by: Package '` + nonExistentModule + `' not found` @@ -568,7 +571,7 @@ def run(plan): ` // assert that first load fails - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.NotNil(suite.T(), interpretationError) require.Nil(suite.T(), instructionsPlan) @@ -577,7 +580,7 @@ def run(plan): expectedOutput := `Hello World! ` // assert that second load succeeds - _, instructionsPlan, interpretationError = suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError = suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 1, instructionsPlan.Size()) validateScriptOutputFromPrintInstructions(suite.T(), instructionsPlan, expectedOutput) @@ -604,7 +607,7 @@ def run(plan): plan.add_service(name = module_bar.service_name, config = module_bar.config) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 3, instructionsPlan.Size()) @@ -648,7 +651,7 @@ def run(plan): plan.print("Done!") ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 8, instructionsPlan.Size()) @@ -677,7 +680,7 @@ def run(plan): plan.print("World!") ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 1, instructionsPlan.Size()) @@ -715,7 +718,7 @@ Adding service example-datastore-server Starting Startosis script! ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, scriptA, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, scriptA, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 4, instructionsPlan.Size()) assertInstructionTypeAndPosition(suite.T(), instructionsPlan, 2, add_service.AddServiceBuiltinName, moduleBar, 12, 18) @@ -740,7 +743,7 @@ def run(plan): Adding service example-datastore-server ` - _, instructionsPlan, interpretationError = suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, scriptB, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError = suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, scriptB, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 3, instructionsPlan.Size()) assertInstructionTypeAndPosition(suite.T(), instructionsPlan, 2, add_service.AddServiceBuiltinName, startosis_constants.PackageIdPlaceholderForStandaloneScript, 14, 18) @@ -760,7 +763,7 @@ def run(plan): plan.print(file_contents) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 2, instructionsPlan.Size()) @@ -794,7 +797,7 @@ def run(plan): plan.print(artifact_name) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 3, instructionsPlan.Size()) @@ -833,7 +836,7 @@ def run(plan): plan.print(uuid) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 4, instructionsPlan.Size()) @@ -855,7 +858,7 @@ def run(plan): plan.print("The service example-datastore-server has been removed") ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 3, instructionsPlan.Size()) @@ -873,7 +876,7 @@ func (suite *StartosisInterpreterTestSuite) TestStartosisInterpreter_NoPanicIfUp def run(plan): plan.upload_files("` + filePath + `") ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.NotNil(suite.T(), interpretationError) require.Nil(suite.T(), instructionsPlan) } @@ -884,7 +887,7 @@ def run(plan): plan.print("Hello World!") ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 1, instructionsPlan.Size()) @@ -899,7 +902,7 @@ def run(plan): plan.print("Hello World!") ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, `{"number": 4}`, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, `{"number": 4}`, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.NotNil(suite.T(), interpretationError) require.Nil(suite.T(), instructionsPlan) } @@ -910,7 +913,7 @@ def run(plan, args): plan.print("My favorite number is {0}".format(args["number"])) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, `{"number": 4}`, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, `{"number": 4}`, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 1, instructionsPlan.Size()) @@ -928,7 +931,7 @@ def run(plan, args): plan.print("Sorry no args!") ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 1, instructionsPlan.Size()) @@ -943,7 +946,7 @@ def run(plan, args, invalid_arg): plan.print("this wouldn't interpret so the text here doesnt matter") ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.NotNil(suite.T(), interpretationError) expectedError := "Evaluation error: function run missing 2 arguments (args, invalid_arg)" require.Contains(suite.T(), interpretationError.GetErrorMessage(), expectedError) @@ -957,7 +960,7 @@ def run(plan, a, b): ` missingArgumentCount := 1 missingArgument := "b" - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, `{"a": "x"}`, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, `{"a": "x"}`, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.NotNil(suite.T(), interpretationError) expectedError := fmt.Sprintf("Evaluation error: function run missing %d argument (%v)", missingArgumentCount, missingArgument) @@ -970,7 +973,7 @@ func (suite *StartosisInterpreterTestSuite) TestStartosisInterpreter_RunWithUnpa def run(plan, a, b=1): plan.print("My favorite number is {0}, but my favorite letter is {1}".format(b, a)) ` - _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, `{"a": "x"}`, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, instructionsPlan, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, `{"a": "x"}`, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) require.Equal(suite.T(), 1, instructionsPlan.Size()) expectedOutput := "My favorite number is 1, but my favorite letter is x\n" @@ -983,7 +986,7 @@ def run(plan): print("this doesnt matter") ` - _, _, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, _, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.NotNil(suite.T(), interpretationError) require.Equal(suite.T(), fmt.Sprintf("Evaluation error: %v\n\tat [3:7]: run\n\tat [0:0]: print", print_builtin.UsePlanFromKurtosisInstructionError), interpretationError.GetErrorMessage()) } @@ -994,7 +997,7 @@ def run(plan): time.now() ` - _, _, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, _, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.NotNil(suite.T(), interpretationError) require.Equal(suite.T(), fmt.Sprintf("Evaluation error: %v\n\tat [3:10]: run\n\tat [0:0]: now", time_now_builtin.UseRunPythonInsteadOfTimeNowError), interpretationError.GetErrorMessage()) } @@ -1005,7 +1008,7 @@ def run(plan): time.parse_duration("5s") ` - _, _, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask) + _, _, interpretationError := suite.interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, useDefaultMainFunctionName, noPackageReplaceOptions, startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, script, startosis_constants.EmptyInputArgs, defaultNonBlockingMode, emptyEnclaveComponents, emptyInstructionsPlanMask, defaultImageDownloadMode) require.Nil(suite.T(), interpretationError) } diff --git a/core/server/api_container/server/startosis_engine/startosis_runner.go b/core/server/api_container/server/startosis_engine/startosis_runner.go index dd13197c73..e3c66e62e7 100644 --- a/core/server/api_container/server/startosis_engine/startosis_runner.go +++ b/core/server/api_container/server/startosis_engine/startosis_runner.go @@ -114,6 +114,7 @@ func (runner *StartosisRunner) Run( nonBlockingMode, enclave_structure.NewEnclaveComponents(), resolver.NewInstructionsPlanMask(0), + imageDownloadMode, ) } else { serializedScriptOutput, instructionsPlan, interpretationError = runner.startosisInterpreter.InterpretAndOptimizePlan( @@ -126,6 +127,7 @@ func (runner *StartosisRunner) Run( serializedParams, nonBlockingMode, runner.startosisExecutor.enclavePlan, + imageDownloadMode, ) } From 9697eb98e2ab8e936122d8c887d652323b063cb3 Mon Sep 17 00:00:00 2001 From: kurtosisbot <89932784+kurtosisbot@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:16:01 -0400 Subject: [PATCH 03/16] chore(main): release 0.88.5 (#2277) :robot: I have created a release *beep* *boop* --- ## [0.88.5](https://github.com/kurtosis-tech/kurtosis/compare/0.88.4...0.88.5) (2024-03-12) ### Features * add an add to GitHub button on an encalve ([#2256](https://github.com/kurtosis-tech/kurtosis/issues/2256)) ([96f6771](https://github.com/kurtosis-tech/kurtosis/commit/96f67712d83d9d89b1575b32f256522220a8ed94)) ### Bug Fixes * image download mode always applies to k8s as well ([#2271](https://github.com/kurtosis-tech/kurtosis/issues/2271)) ([2e90c67](https://github.com/kurtosis-tech/kurtosis/commit/2e90c672abe576c0ccfa385e95af59980678a395)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: kurtosisbot --- CHANGELOG.md | 12 ++++++++++++ LICENSE.md | 4 ++-- api/golang/kurtosis_version/kurtosis_version.go | 2 +- api/rust/Cargo.toml | 2 +- api/typescript/package.json | 2 +- .../src/kurtosis_version/kurtosis_version.ts | 2 +- enclave-manager/web/lerna.json | 2 +- enclave-manager/web/packages/app/package.json | 4 ++-- enclave-manager/web/packages/components/package.json | 2 +- version.txt | 2 +- 10 files changed, 23 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5907249760..6845e0c417 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [0.88.5](https://github.com/kurtosis-tech/kurtosis/compare/0.88.4...0.88.5) (2024-03-12) + + +### Features + +* add an add to GitHub button on an encalve ([#2256](https://github.com/kurtosis-tech/kurtosis/issues/2256)) ([96f6771](https://github.com/kurtosis-tech/kurtosis/commit/96f67712d83d9d89b1575b32f256522220a8ed94)) + + +### Bug Fixes + +* image download mode always applies to k8s as well ([#2271](https://github.com/kurtosis-tech/kurtosis/issues/2271)) ([2e90c67](https://github.com/kurtosis-tech/kurtosis/commit/2e90c672abe576c0ccfa385e95af59980678a395)) + ## [0.88.4](https://github.com/kurtosis-tech/kurtosis/compare/0.88.3...0.88.4) (2024-03-11) diff --git a/LICENSE.md b/LICENSE.md index be06bcd818..e47b8fbdf4 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -3,7 +3,7 @@ Business Source License 1.1 Parameters Licensor: Kurtosis Technologies, Inc. -Licensed Work: Kurtosis 0.88.4 +Licensed Work: Kurtosis 0.88.5 The Licensed Work is (c) 2024 Kurtosis Technologies, Inc. Additional Use Grant: You may make use of the Licensed Work, provided that you may not use the Licensed Work for an Environment Orchestration Service. @@ -12,7 +12,7 @@ you may not use the Licensed Work for an Environment Orchestration Service. allows third parties (other than your employees and contractors) to create distributed system environments. -Change Date: 2028-03-11 +Change Date: 2028-03-12 Change License: Apache 2.0 (Apache License, Version 2.0) diff --git a/api/golang/kurtosis_version/kurtosis_version.go b/api/golang/kurtosis_version/kurtosis_version.go index 547c8fa365..3c52ace0b5 100644 --- a/api/golang/kurtosis_version/kurtosis_version.go +++ b/api/golang/kurtosis_version/kurtosis_version.go @@ -9,6 +9,6 @@ const ( // !!!!!!!!!!! DO NOT UPDATE! WILL BE MANUALLY UPDATED DURING THE RELEASE PROCESS !!!!!!!!!!!!!!!!!!!!!! // This is necessary so that Kurt Core consumers will know if they're compatible with the currently-running // API container - KurtosisVersion = "0.88.4" + KurtosisVersion = "0.88.5" // !!!!!!!!!!! DO NOT UPDATE! WILL BE MANUALLY UPDATED DURING THE RELEASE PROCESS !!!!!!!!!!!!!!!!!!!!!! ) diff --git a/api/rust/Cargo.toml b/api/rust/Cargo.toml index bed3824975..90784b4fab 100644 --- a/api/rust/Cargo.toml +++ b/api/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kurtosis-sdk" -version = "0.88.4" +version = "0.88.5" license = "BUSL-1.1" description = "Rust SDK for Kurtosis" edition = "2021" diff --git a/api/typescript/package.json b/api/typescript/package.json index 5f72faf2d5..89518ba835 100644 --- a/api/typescript/package.json +++ b/api/typescript/package.json @@ -1,7 +1,7 @@ { "name": "kurtosis-sdk", "//": "NOTE: DO NOT UPDATE THIS VERSION MANUALLY - IT WILL BE UPDATED DURING THE RELEASE PROCESS!", - "version": "0.88.4", + "version": "0.88.5", "main": "./build/index", "description": "This repo contains a Typescript client for communicating with the Kurtosis Engine server, which is responsible for creating, managing and destroying Kurtosis Enclaves.", "types": "./build/index", diff --git a/api/typescript/src/kurtosis_version/kurtosis_version.ts b/api/typescript/src/kurtosis_version/kurtosis_version.ts index 9f953ef3b4..754df9b3ac 100644 --- a/api/typescript/src/kurtosis_version/kurtosis_version.ts +++ b/api/typescript/src/kurtosis_version/kurtosis_version.ts @@ -1,5 +1,5 @@ // !!!!!!!!!!! DO NOT UPDATE! WILL BE MANUALLY UPDATED DURING THE RELEASE PROCESS !!!!!!!!!!!!!!!!!!!!!! // This is necessary so that Kurt Core consumers (e.g. modules) will know if they're compatible with the currently-running // API container -export const KURTOSIS_VERSION: string = "0.88.4" +export const KURTOSIS_VERSION: string = "0.88.5" // !!!!!!!!!!! DO NOT UPDATE! WILL BE MANUALLY UPDATED DURING THE RELEASE PROCESS !!!!!!!!!!!!!!!!!!!!!! diff --git a/enclave-manager/web/lerna.json b/enclave-manager/web/lerna.json index 44a7ae33a6..9f873441f5 100644 --- a/enclave-manager/web/lerna.json +++ b/enclave-manager/web/lerna.json @@ -1,6 +1,6 @@ { "packages": ["packages/*"], - "version": "0.88.4", + "version": "0.88.5", "npmClient": "yarn", "$schema": "node_modules/lerna/schemas/lerna-schema.json", "useNx": false, diff --git a/enclave-manager/web/packages/app/package.json b/enclave-manager/web/packages/app/package.json index ad63a4bb7a..7fd8b5daec 100644 --- a/enclave-manager/web/packages/app/package.json +++ b/enclave-manager/web/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@kurtosis/emui-app", - "version": "0.88.4", + "version": "0.88.5", "private": true, "homepage": ".", "dependencies": { @@ -10,7 +10,7 @@ "html-react-parser": "^4.2.2", "js-cookie": "^3.0.5", "kurtosis-cloud-indexer-sdk": "^0.0.2", - "kurtosis-ui-components": "0.88.4", + "kurtosis-ui-components": "0.88.5", "react-error-boundary": "^4.0.11", "react-hook-form": "^7.47.0", "react-mentions": "^4.4.10", diff --git a/enclave-manager/web/packages/components/package.json b/enclave-manager/web/packages/components/package.json index 3a50762502..638e81bf06 100644 --- a/enclave-manager/web/packages/components/package.json +++ b/enclave-manager/web/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "kurtosis-ui-components", - "version": "0.88.4", + "version": "0.88.5", "private": false, "main": "build/index", "description": "This repo contains components used by Kurtosis UI applications.", diff --git a/version.txt b/version.txt index 03e595378f..d4fd29afb5 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -0.88.4 +0.88.5 From 9812375f1258a2b15394b98a116741e3bfd366bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Vincent?= <28714795+leovct@users.noreply.github.com> Date: Tue, 12 Mar 2024 19:06:30 +0100 Subject: [PATCH 04/16] feat: define `build_args` in `ImageBuildSpec` (#2257) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description: - [x] Add a new parameter `build_args` in `ImageBuildSpec`. - [x] Update the logic of the image builder to take into accounts the build arguments. - [x] Implement tests (unit + e2e). - [x] Update docs. - [x] Test in a real scenario. ### Tests in a real scenario I updated the `Dockerfile` under `internal_testsuites/starlark_image-build-package` to expect a build argument called `BUILD_ARG` and equal to `VALUE`. ```Dockerfile FROM alpine:latest WORKDIR /app COPY . . # The idea is to test if the build argument has been provided. # The following commands would not work: # $ docker build -t image-build-package-test . # Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE # $ docker build -t image-build-package-test --build-arg "BUILD_ARG=WRONG_VALUE" . # Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE # But this command would work: # $ docker build -t image-build-package-test --build-arg "BUILD_ARG=VALUE" . ARG BUILD_ARG="DEFAULT_VALUE" RUN if [ "$BUILD_ARG" != "VALUE" ]; then \ echo "Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE"; \ exit 1; \ fi CMD ["echo", "Hello, Kurtosis!"] ``` I then performed three tests to check that the feature was implemented correctly: - Test without any build arguments defined. - Test with the correct build argument defined but with a wrong value. - Test with the correct build argument defined with the correct value. For the first two tests, as expected, they fail because the image can't be built. ```bash $ ktdebug run --enclave test internal_testsuites/starlark/image-build-package WARN[2024-03-08T12:48:16+01:00] An error occurred getting the running engine's version; you may be running an out-of-date engine version WARN[2024-03-08T12:48:16+01:00] We expected the running engine version to match format X.Y.Z, but instead got '386fd4-dirty'; this means that we can't verify the API library and engine versions match so you may encounter runtime errors INFO[2024-03-08T12:48:16+01:00] Creating a new enclave for Starlark to run inside... INFO[2024-03-08T12:48:18+01:00] Enclave 'test' created successfully INFO[2024-03-08T12:48:18+01:00] Executing Starlark package at '/Users/leovct/Documents/opensource/kurtosis/internal_testsuites/starlark/image-build-package' as the passed argument 'internal_testsuites/starlark/image-build-package' looks like a directory INFO[2024-03-08T12:48:18+01:00] Compressing package 'github.com/kurtosis-tech/kurtosis/internal_testsuites/starlark/image-build-package' at 'internal_testsuites/starlark/image-build-package' for upload INFO[2024-03-08T12:48:18+01:00] Uploading and executing package 'github.com/kurtosis-tech/kurtosis/internal_testsuites/starlark/image-build-package' There was an error validating Starlark code Error while validating final environment of script Caused by: Failed to build the required image 'kurtosistech/service'. Caused by: Image build for 'kurtosistech/service' failed with the following output: {"id":"moby.buildkit.trace","aux":"Cm8KR3NoYTI1NjpkYzExOGIxMmZmMmY2MTE4Y2EwNjY2NjhhNmNjOGQ3ZjQyYmYzZWEwYzg3YWY2YTNjZDExNmI4Y2UzMmNkY2ExGiRbaW50ZXJuYWxdIGxvYWQgcmVtb3RlIGJ1aWxkIGNvbnRleHQ="} {"id":"moby.buildkit.trace","aux":"Cn0KR3NoYTI1NjpkYzExOGIxMmZmMmY2MTE4Y2EwNjY2NjhhNmNjOGQ3ZjQyYmYzZWEwYzg3YWY2YTNjZDExNmI4Y2UzMmNkY2ExGiRbaW50ZXJuYWxdIGxvYWQgcmVtb3RlIGJ1aWxkIGNvbnRleHQqDAiE9quvBhD/qsaLAw=="} {"id":"moby.buildkit.trace","aux":"CosBCkdzaGEyNTY6ZGMxMThiMTJmZjJmNjExOGNhMDY2NjY4YTZjYzhkN2Y0MmJmM2VhMGM4N2FmNmEzY2QxMTZiOGNlMzJjZGNhMRokW2ludGVybmFsXSBsb2FkIHJlbW90ZSBidWlsZCBjb250ZXh0KgwIhParrwYQ/6rGiwMyDAiE9quvBhD6gMSPAw=="} {"id":"moby.buildkit.trace","aux":"CosBCkdzaGEyNTY6ZGMxMThiMTJmZjJmNjExOGNhMDY2NjY4YTZjYzhkN2Y0MmJmM2VhMGM4N2FmNmEzY2QxMTZiOGNlMzJjZGNhMRokW2ludGVybmFsXSBsb2FkIHJlbW90ZSBidWlsZCBjb250ZXh0KgwIhParrwYQyv7JjwMyDAiE9quvBhDF0MuPAw=="} {"id":"moby.buildkit.trace","aux":"CqMBCkdzaGEyNTY6MTY1ZDBjMTIwNmI3ZDMwMzRkYzllMzE2M2QwNmE5Y2UzYjE4NGI3ZTcxNmU1MzliM2UwZjY0ZTQwZTBkYTBmMxJHc2hhMjU2OmRjMTE4YjEyZmYyZjYxMThjYTA2NjY2OGE2Y2M4ZDdmNDJiZjNlYTBjODdhZjZhM2NkMTE2YjhjZTMyY2RjYTEaD2NvcHkgL2NvbnRleHQgLw=="} {"id":"moby.buildkit.trace","aux":"CrEBCkdzaGEyNTY6MTY1ZDBjMTIwNmI3ZDMwMzRkYzllMzE2M2QwNmE5Y2UzYjE4NGI3ZTcxNmU1MzliM2UwZjY0ZTQwZTBkYTBmMxJHc2hhMjU2OmRjMTE4YjEyZmYyZjYxMThjYTA2NjY2OGE2Y2M4ZDdmNDJiZjNlYTBjODdhZjZhM2NkMTE2YjhjZTMyY2RjYTEaD2NvcHkgL2NvbnRleHQgLyoMCIT2q68GEJXyjJED"} {"id":"moby.buildkit.trace","aux":"Cr8BCkdzaGEyNTY6MTY1ZDBjMTIwNmI3ZDMwMzRkYzllMzE2M2QwNmE5Y2UzYjE4NGI3ZTcxNmU1MzliM2UwZjY0ZTQwZTBkYTBmMxJHc2hhMjU2OmRjMTE4YjEyZmYyZjYxMThjYTA2NjY2OGE2Y2M4ZDdmNDJiZjNlYTBjODdhZjZhM2NkMTE2YjhjZTMyY2RjYTEaD2NvcHkgL2NvbnRleHQgLyoMCIT2q68GEJXyjJEDMgwIhParrwYQ6JOHlAM="} {"id":"moby.buildkit.trace","aux":"CpUBCkdzaGEyNTY6MTM1NDljNThhNzZiY2I1ZGFjOWQ1MmJjMzY4YThmYjZiNWNmNzY1OWY5NGUzZmE2Mjk0OTE3Yjg1NTQ2OTc4ZBo8W2ludGVybmFsXSBsb2FkIG1ldGFkYXRhIGZvciBkb2NrZXIuaW8vbGlicmFyeS9hbHBpbmU6bGF0ZXN0KgwIhParrwYQ25TglAM="} {"id":"moby.buildkit.trace","aux":"CqMBCkdzaGEyNTY6MTM1NDljNThhNzZiY2I1ZGFjOWQ1MmJjMzY4YThmYjZiNWNmNzY1OWY5NGUzZmE2Mjk0OTE3Yjg1NTQ2OTc4ZBo8W2ludGVybmFsXSBsb2FkIG1ldGFkYXRhIGZvciBkb2NrZXIuaW8vbGlicmFyeS9hbHBpbmU6bGF0ZXN0KgwIhParrwYQ25TglAMyDAiF9quvBhCl+4CKAQ=="} {"id":"moby.buildkit.trace","aux":"CrACCkdzaGEyNTY6MWFhZWYxZjViNTc0YzNhNmU3MzdhODFjZTMxZmI1YzRmOGNmYWZlNTg5ZDkwNWMwZWQ2YjYzMmZmYzMwNzM5NhJHc2hhMjU2OjE0MjBiNTM5NzFkODkzOTE2YzRlMGU4ZDVlZDRlMjRlNjlkMmE0ODFlNzRiNDcxM2M0NzBhYzczNDU1NDU4YTIamwFbNC80XSBSVU4gaWYgWyAiREVGQVVMVF9WQUxVRSIgIT0gIlZBTFVFIiBdOyB0aGVuICAgZWNobyAiRXJyb3I6IHRoZSBidWlsZCBhcmd1bWVudCBCVUlMRF9BUkcgaGFzIG5vdCBiZWVuIHByb3ZpZGVkIG9yIGlzIG5vdCBlcXVhbCB0byBWQUxVRSI7ICAgZXhpdCAxOyBmaQrrAQpHc2hhMjU2OjE0MjBiNTM5NzFkODkzOTE2YzRlMGU4ZDVlZDRlMjRlNjlkMmE0ODFlNzRiNDcxM2M0NzBhYzczNDU1NDU4YTISR3NoYTI1Njo0M2Q4OWU2YzU4NGQyM2U1YjM1ODU2MzQ5ODQxZDBmN2M1NmRlMTA3NDQ3YjNhZjdiY2I4ODEwNjBlMGM1ZjNlEkdzaGEyNTY6MTY1ZDBjMTIwNmI3ZDMwMzRkYzllMzE2M2QwNmE5Y2UzYjE4NGI3ZTcxNmU1MzliM2UwZjY0ZTQwZTBkYTBmMxoOWzMvNF0gQ09QWSAuIC4KpgEKR3NoYTI1Njo0M2Q4OWU2YzU4NGQyM2U1YjM1ODU2MzQ5ODQxZDBmN2M1NmRlMTA3NDQ3YjNhZjdiY2I4ODEwNjBlMGM1ZjNlEkdzaGEyNTY6OWVmN2JlYWVhMDQ3MzA5MTg1MDQ3NzY0ZTNhYTBkNGYyOTk3OWRhY2M4OGU1NzNkYWE5ZDBmODIwNTBiNGFiMRoSWzIvNF0gV09SS0RJUiAvYXBwCr0BCkdzaGEyNTY6OWVmN2JlYWVhMDQ3MzA5MTg1MDQ3NzY0ZTNhYTBkNGYyOTk3OWRhY2M4OGU1NzNkYWE5ZDBmODIwNTBiNGFiMRpyWzEvNF0gRlJPTSBkb2NrZXIuaW8vbGlicmFyeS9hbHBpbmU6bGF0ZXN0QHNoYTI1NjpjNWIxMjYxZDZkM2U0MzA3MTYyNjkzMWZjMDA0ZjcwMTQ5YmFlYmEyYzhlYzY3MmJkNGYyNzc2MWY4ZTFhZDZiCtkBCkdzaGEyNTY6OWVmN2JlYWVhMDQ3MzA5MTg1MDQ3NzY0ZTNhYTBkNGYyOTk3OWRhY2M4OGU1NzNkYWE5ZDBmODIwNTBiNGFiMRpyWzEvNF0gRlJPTSBkb2NrZXIuaW8vbGlicmFyeS9hbHBpbmU6bGF0ZXN0QHNoYTI1NjpjNWIxMjYxZDZkM2U0MzA3MTYyNjkzMWZjMDA0ZjcwMTQ5YmFlYmEyYzhlYzY3MmJkNGYyNzc2MWY4ZTFhZDZiKgwIhfarrwYQ0v3JigEyDAiF9quvBhDz1teKAQ=="} {"id":"moby.buildkit.trace","aux":"CsQBCkdzaGEyNTY6NDNkODllNmM1ODRkMjNlNWIzNTg1NjM0OTg0MWQwZjdjNTZkZTEwNzQ0N2IzYWY3YmNiODgxMDYwZTBjNWYzZRJHc2hhMjU2OjllZjdiZWFlYTA0NzMwOTE4NTA0Nzc2NGUzYWEwZDRmMjk5NzlkYWNjODhlNTczZGFhOWQwZjgyMDUwYjRhYjEaElsyLzRdIFdPUktESVIgL2FwcCABKgwIhfarrwYQ7PyxiwEyDAiF9quvBhDAsLiLAQ=="} {"id":"moby.buildkit.trace","aux":"CvkBCkdzaGEyNTY6MTQyMGI1Mzk3MWQ4OTM5MTZjNGUwZThkNWVkNGUyNGU2OWQyYTQ4MWU3NGI0NzEzYzQ3MGFjNzM0NTU0NThhMhJHc2hhMjU2OjQzZDg5ZTZjNTg0ZDIzZTViMzU4NTYzNDk4NDFkMGY3YzU2ZGUxMDc0NDdiM2FmN2JjYjg4MTA2MGUwYzVmM2USR3NoYTI1NjoxNjVkMGMxMjA2YjdkMzAzNGRjOWUzMTYzZDA2YTljZTNiMTg0YjdlNzE2ZTUzOWIzZTBmNjRlNDBlMGRhMGYzGg5bMy80XSBDT1BZIC4gLioMCIX2q68GEN6wvosB"} {"id":"moby.buildkit.trace","aux":"CocCCkdzaGEyNTY6MTQyMGI1Mzk3MWQ4OTM5MTZjNGUwZThkNWVkNGUyNGU2OWQyYTQ4MWU3NGI0NzEzYzQ3MGFjNzM0NTU0NThhMhJHc2hhMjU2OjQzZDg5ZTZjNTg0ZDIzZTViMzU4NTYzNDk4NDFkMGY3YzU2ZGUxMDc0NDdiM2FmN2JjYjg4MTA2MGUwYzVmM2USR3NoYTI1NjoxNjVkMGMxMjA2YjdkMzAzNGRjOWUzMTYzZDA2YTljZTNiMTg0YjdlNzE2ZTUzOWIzZTBmNjRlNDBlMGRhMGYzGg5bMy80XSBDT1BZIC4gLioMCIX2q68GEN6wvosBMgwIhfarrwYQyOfrlAE="} {"id":"moby.buildkit.trace","aux":"Cr4CCkdzaGEyNTY6MWFhZWYxZjViNTc0YzNhNmU3MzdhODFjZTMxZmI1YzRmOGNmYWZlNTg5ZDkwNWMwZWQ2YjYzMmZmYzMwNzM5NhJHc2hhMjU2OjE0MjBiNTM5NzFkODkzOTE2YzRlMGU4ZDVlZDRlMjRlNjlkMmE0ODFlNzRiNDcxM2M0NzBhYzczNDU1NDU4YTIamwFbNC80XSBSVU4gaWYgWyAiREVGQVVMVF9WQUxVRSIgIT0gIlZBTFVFIiBdOyB0aGVuICAgZWNobyAiRXJyb3I6IHRoZSBidWlsZCBhcmd1bWVudCBCVUlMRF9BUkcgaGFzIG5vdCBiZWVuIHByb3ZpZGVkIG9yIGlzIG5vdCBlcXVhbCB0byBWQUxVRSI7ICAgZXhpdCAxOyBmaSoMCIX2q68GEPmv7JUB"} {"id":"moby.buildkit.trace","aux":"Gq4BCkdzaGEyNTY6MWFhZWYxZjViNTc0YzNhNmU3MzdhODFjZTMxZmI1YzRmOGNmYWZlNTg5ZDkwNWMwZWQ2YjYzMmZmYzMwNzM5NhIMCIX2q68GEI710M8BGAEiU0Vycm9yOiB0aGUgYnVpbGQgYXJndW1lbnQgQlVJTERfQVJHIGhhcyBub3QgYmVlbiBwcm92aWRlZCBvciBpcyBub3QgZXF1YWwgdG8gVkFMVUUK"} {"id":"moby.buildkit.trace","aux":"CqQECkdzaGEyNTY6MWFhZWYxZjViNTc0YzNhNmU3MzdhODFjZTMxZmI1YzRmOGNmYWZlNTg5ZDkwNWMwZWQ2YjYzMmZmYzMwNzM5NhJHc2hhMjU2OjE0MjBiNTM5NzFkODkzOTE2YzRlMGU4ZDVlZDRlMjRlNjlkMmE0ODFlNzRiNDcxM2M0NzBhYzczNDU1NDU4YTIamwFbNC80XSBSVU4gaWYgWyAiREVGQVVMVF9WQUxVRSIgIT0gIlZBTFVFIiBdOyB0aGVuICAgZWNobyAiRXJyb3I6IHRoZSBidWlsZCBhcmd1bWVudCBCVUlMRF9BUkcgaGFzIG5vdCBiZWVuIHByb3ZpZGVkIG9yIGlzIG5vdCBlcXVhbCB0byBWQUxVRSI7ICAgZXhpdCAxOyBmaSoMCIX2q68GEPmv7JUBMgwIhfarrwYQn6i91AE61QFwcm9jZXNzICIvYmluL3NoIC1jIGlmIFsgXCIkQlVJTERfQVJHXCIgIT0gXCJWQUxVRVwiIF07IHRoZW4gICBlY2hvIFwiRXJyb3I6IHRoZSBidWlsZCBhcmd1bWVudCBCVUlMRF9BUkcgaGFzIG5vdCBiZWVuIHByb3ZpZGVkIG9yIGlzIG5vdCBlcXVhbCB0byBWQUxVRVwiOyAgIGV4aXQgMTsgZmkiIGRpZCBub3QgY29tcGxldGUgc3VjY2Vzc2Z1bGx5OiBleGl0IGNvZGU6IDE="} {"errorDetail":{"message":"process \"/bin/sh -c if [ \\\"$BUILD_ARG\\\" != \\\"VALUE\\\" ]; then echo \\\"Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE\\\"; exit 1; fi\" did not complete successfully: exit code: 1"},"error":"process \"/bin/sh -c if [ \\\"$BUILD_ARG\\\" != \\\"VALUE\\\" ]; then echo \\\"Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE\\\"; exit 1; fi\" did not complete successfully: exit code: 1"} --- at /Users/leovct/Documents/opensource/kurtosis/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go:1479 (DockerManager.BuildImage) --- Container images used in this run: > kurtosistech/service - locally built Error encountered running Starlark code. Made with Kurtosis - https://kurtosis.com INFO[2024-03-08T12:48:21+01:00] ============================================= INFO[2024-03-08T12:48:21+01:00] || Created enclave: test || INFO[2024-03-08T12:48:21+01:00] ============================================= Name: test UUID: fc14d605d775 Status: RUNNING Creation Time: Fri, 08 Mar 2024 12:48:16 CET Flags: ========================================= Files Artifacts ========================================= UUID Name ========================================== User Services ========================================== UUID Name Ports Status ``` For the last test, it succeeds, meaning the feature has been correctly implemented! 🥳 ```bash $ ktdebug run --enclave test internal_testsuites/starlark/image-build-package WARN[2024-03-08T12:49:39+01:00] An error occurred getting the running engine's version; you may be running an out-of-date engine version WARN[2024-03-08T12:49:39+01:00] We expected the running engine version to match format X.Y.Z, but instead got '386fd4-dirty'; this means that we can't verify the API library and engine versions match so you may encounter runtime errors INFO[2024-03-08T12:49:39+01:00] Executing Starlark package at '/Users/leovct/Documents/opensource/kurtosis/internal_testsuites/starlark/image-build-package' as the passed argument 'internal_testsuites/starlark/image-build-package' looks like a directory INFO[2024-03-08T12:49:39+01:00] Compressing package 'github.com/kurtosis-tech/kurtosis/internal_testsuites/starlark/image-build-package' at 'internal_testsuites/starlark/image-build-package' for upload INFO[2024-03-08T12:49:39+01:00] Uploading and executing package 'github.com/kurtosis-tech/kurtosis/internal_testsuites/starlark/image-build-package' Container images used in this run: > kurtosistech/service - locally built WARNING: Container images with different architecture than expected(amd64): > kurtosistech/service - arm64 Adding service with name 'service' and image 'kurtosistech/service' Service 'service' added with service UUID '30bd3754ec864729bf11e2ed9154b4f6' Starlark code successfully run. No output was returned. Made with Kurtosis - https://kurtosis.com Name: test UUID: fc14d605d775 Status: RUNNING Creation Time: Fri, 08 Mar 2024 12:48:16 CET Flags: ========================================= Files Artifacts ========================================= UUID Name ========================================== User Services ========================================== UUID Name Ports Status 30bd3754ec86 service STOPPED ``` ## Is this change user facing? YES ## References (if applicable): Resolves #2214 --------- Co-authored-by: Tedi Mitiku --- .../docker/docker_manager/docker_manager.go | 8 ++- .../image_build_spec/image_build_spec.go | 11 +++- .../objects/service/service_config_test.go | 7 +- ...ild_spec_framework_with_build_args_test.go | 65 +++++++++++++++++++ .../service_config_image_build_spec_test.go | 13 +++- .../test_engine/static_constants.go | 4 ++ .../kurtosis_types/arg_shared_helpers.go | 3 +- .../service_config/image_build_spec.go | 31 ++++++++- .../starlark-reference/image-build-spec.md | 7 ++ .../starlark-reference/service-config.md | 7 ++ .../starlark/image-build-package/Dockerfile | 19 ++++++ .../starlark/image-build-package/main.star | 3 + 12 files changed, 168 insertions(+), 10 deletions(-) create mode 100644 core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/image_build_spec_framework_with_build_args_test.go diff --git a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go index d5f1563328..8e571c46f6 100644 --- a/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go +++ b/container-engine-lib/lib/backend_impls/docker/docker_manager/docker_manager.go @@ -1408,6 +1408,12 @@ func (manager *DockerManager) BuildImage(ctx context.Context, imageName string, }() defer buildkitSession.Close() //nolint + buildArgs := imageBuildSpec.GetBuildArgs() + buildArgsMapStringStringPtr := map[string]*string{} + for k, v := range buildArgs { + value := v // Go uses a single variable for loop iterations which lead to unexpected behaviours. + buildArgsMapStringStringPtr[k] = &value + } imageBuildOpts := types.ImageBuildOptions{ Tags: []string{imageName}, SuppressOutput: false, @@ -1429,7 +1435,7 @@ func (manager *DockerManager) BuildImage(ctx context.Context, imageName string, ShmSize: 0, Dockerfile: defaultContainerImageFile, Ulimits: []*units.Ulimit{}, - BuildArgs: map[string]*string{}, + BuildArgs: buildArgsMapStringStringPtr, AuthConfigs: map[string]registry.AuthConfig{}, Context: buildContextTarReader, // 0.0.0 label is a hack so that images by internal testsuite are cleaned up by kurtosis clean/PruneUnusedImages diff --git a/container-engine-lib/lib/backend_interface/objects/image_build_spec/image_build_spec.go b/container-engine-lib/lib/backend_interface/objects/image_build_spec/image_build_spec.go index a894cde36e..b22f01bc7d 100644 --- a/container-engine-lib/lib/backend_interface/objects/image_build_spec/image_build_spec.go +++ b/container-engine-lib/lib/backend_interface/objects/image_build_spec/image_build_spec.go @@ -2,6 +2,7 @@ package image_build_spec import ( "encoding/json" + "github.com/kurtosis-tech/stacktrace" ) @@ -37,13 +38,17 @@ type privateImageBuildSpec struct { // Default value is the empty string if the image build is not multi-stage. // TargetStage string + + // Dockerfile build args + BuildArgs map[string]string } -func NewImageBuildSpec(contextDirPath string, containerImageFilePath string, targetStage string) *ImageBuildSpec { +func NewImageBuildSpec(contextDirPath string, containerImageFilePath string, targetStage string, buildArgs map[string]string) *ImageBuildSpec { internalImageBuildSpec := &privateImageBuildSpec{ ContainerImageFilePath: containerImageFilePath, ContextDirPath: contextDirPath, TargetStage: targetStage, + BuildArgs: buildArgs, } return &ImageBuildSpec{internalImageBuildSpec} } @@ -60,6 +65,10 @@ func (imageBuildSpec *ImageBuildSpec) GetTargetStage() string { return imageBuildSpec.privateImageBuildSpec.TargetStage } +func (imageBuildSpec *ImageBuildSpec) GetBuildArgs() map[string]string { + return imageBuildSpec.privateImageBuildSpec.BuildArgs +} + func (imageBuildSpec *ImageBuildSpec) MarshalJSON() ([]byte, error) { return json.Marshal(imageBuildSpec.privateImageBuildSpec) } diff --git a/container-engine-lib/lib/backend_interface/objects/service/service_config_test.go b/container-engine-lib/lib/backend_interface/objects/service/service_config_test.go index b98a1a38ed..acce5f6529 100644 --- a/container-engine-lib/lib/backend_interface/objects/service/service_config_test.go +++ b/container-engine-lib/lib/backend_interface/objects/service/service_config_test.go @@ -2,12 +2,12 @@ package service import ( "encoding/json" - "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" - "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_registry_spec" "testing" "time" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_build_spec" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_registry_spec" "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/nix_build_spec" "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_directory" @@ -185,7 +185,8 @@ func testImageBuildSpec() *image_build_spec.ImageBuildSpec { return image_build_spec.NewImageBuildSpec( "test-image", "path", - "") + "", + nil) } func testImageRegistrySpec() *image_registry_spec.ImageRegistrySpec { diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/image_build_spec_framework_with_build_args_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/image_build_spec_framework_with_build_args_test.go new file mode 100644 index 0000000000..3adaa5092b --- /dev/null +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/image_build_spec_framework_with_build_args_test.go @@ -0,0 +1,65 @@ +package test_engine + +import ( + "fmt" + "testing" + + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/service_config" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_packages" + "github.com/stretchr/testify/require" +) + +type imageBuildSpecWithBuildArgsTest struct { + *testing.T + + packageContentProvider *startosis_packages.MockPackageContentProvider +} + +func (suite *KurtosisTypeConstructorTestSuite) TestImageBuildSpecWithBuildArgsTest() { + suite.packageContentProvider.EXPECT(). + GetAbsoluteLocator(testModulePackageId, testModuleMainFileLocator, testBuildContextDir, testNoPackageReplaceOptions). + Times(1). + Return(testBuildContextLocator, nil) + + suite.packageContentProvider.EXPECT(). + GetOnDiskAbsolutePackageFilePath(testContainerImageLocator). + Times(1). + Return(testOnDiskContainerImagePath, nil) + + suite.run(&imageBuildSpecWithBuildArgsTest{ + T: suite.T(), + packageContentProvider: suite.packageContentProvider, + }) +} + +func (t *imageBuildSpecWithBuildArgsTest) GetStarlarkCode() string { + return fmt.Sprintf("%s(%s=%q, %s=%q, %s=%s)", + service_config.ImageBuildSpecTypeName, + service_config.BuiltImageNameAttr, + testContainerImageName, + service_config.BuildContextAttr, + testBuildContextDir, + service_config.BuildArgsAttr, + fmt.Sprintf("{%q: %q, %q: %q}", testBuildArgName1, testBuildArgValue1, testBuildArgName2, testBuildArgValue2)) +} + +func (t *imageBuildSpecWithBuildArgsTest) Assert(typeValue builtin_argument.KurtosisValueType) { + imageBuildSpecStarlark, ok := typeValue.(*service_config.ImageBuildSpec) + require.True(t, ok) + + imageBuildSpec, err := imageBuildSpecStarlark.ToKurtosisType( + testModuleMainFileLocator, + testModulePackageId, + t.packageContentProvider, + testNoPackageReplaceOptions) + require.Nil(t, err) + require.Equal(t, testOnDiskContainerImagePath, imageBuildSpec.GetContainerImageFilePath()) + require.Equal(t, testOnDiskContextDirPath, imageBuildSpec.GetBuildContextDir()) + + expectedBuildArgs := map[string]string{ + testBuildArgName1: testBuildArgValue1, + testBuildArgName2: testBuildArgValue2, + } + require.Equal(t, expectedBuildArgs, imageBuildSpec.GetBuildArgs()) +} diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_build_spec_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_build_spec_test.go index 9c5cab78e4..d5f3a13bfc 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_build_spec_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_image_build_spec_test.go @@ -40,14 +40,16 @@ func (suite *KurtosisTypeConstructorTestSuite) TestServiceConfigWithImageBuildSp } func (t *serviceConfigImageBuildSpecTestCase) GetStarlarkCode() string { - imageBuildSpec := fmt.Sprintf("%s(%s=%q, %s=%q, %s=%q)", + imageBuildSpec := fmt.Sprintf("%s(%s=%q, %s=%q, %s=%q, %s=%s)", service_config.ImageBuildSpecTypeName, service_config.BuiltImageNameAttr, testContainerImageName, service_config.BuildContextAttr, testBuildContextDir, service_config.TargetStageAttr, - testTargetStage) + testTargetStage, + service_config.BuildArgsAttr, + fmt.Sprintf("{%q: %q, %q: %q}", testBuildArgName1, testBuildArgValue1, testBuildArgName2, testBuildArgValue2)) return fmt.Sprintf("%s(%s=%s)", service_config.ServiceConfigTypeName, service_config.ImageAttr, imageBuildSpec) @@ -66,10 +68,15 @@ func (t *serviceConfigImageBuildSpecTestCase) Assert(typeValue builtin_argument. image_download_mode.ImageDownloadMode_Missing) require.Nil(t, interpretationErr) + expectedBuildArgs := map[string]string{ + testBuildArgName1: testBuildArgValue1, + testBuildArgName2: testBuildArgValue2, + } expectedImageBuildSpec := image_build_spec.NewImageBuildSpec( testOnDiskContextDirPath, testOnDiskContainerImagePath, - testTargetStage) + testTargetStage, + expectedBuildArgs) expectedServiceConfig, err := service.CreateServiceConfig( testContainerImageName, expectedImageBuildSpec, diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/static_constants.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/static_constants.go index 607a2029d7..f71928c266 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/static_constants.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/static_constants.go @@ -30,6 +30,10 @@ var ( testBuildContextDir = "./" testBuildFile = "foo.Dockerfile" testTargetStage = "builder" + testBuildArgName1 = "BUILD_ARG_1" + testBuildArgValue1 = "VALUE_1" + testBuildArgName2 = "BUILD_ARG_2" + testBuildArgValue2 = "VALUE_2" testBuildContextLocator = testModulePackageId testContainerImageLocator = "github.com/kurtosistech/test-package/Dockerfile" testContainerImageLocatorWithBuildFile = "github.com/kurtosistech/test-package/foo.Dockerfile" diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/arg_shared_helpers.go b/core/server/api_container/server/startosis_engine/kurtosis_types/arg_shared_helpers.go index ec399c8703..20a33dba2d 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_types/arg_shared_helpers.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_types/arg_shared_helpers.go @@ -2,10 +2,11 @@ package kurtosis_types import ( "fmt" + "reflect" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/stacktrace" "go.starlark.net/starlark" - "reflect" ) func MakeOptional(argName string) string { diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/image_build_spec.go b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/image_build_spec.go index 1457673549..c494981c53 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/image_build_spec.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/image_build_spec.go @@ -8,6 +8,7 @@ import ( "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/kurtosis_starlark_framework/builtin_argument" "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" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_constants" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_packages" @@ -21,6 +22,7 @@ const ( BuildContextAttr = "build_context_dir" BuildFileAttr = "build_file" TargetStageAttr = "target_stage" + BuildArgsAttr = "build_args" defaultContainerImageFileName = "Dockerfile" ) @@ -62,6 +64,12 @@ func NewImageBuildSpecType() *kurtosis_type_constructor.KurtosisTypeConstructor return builtin_argument.NonEmptyString(value, TargetStageAttr) }, }, + { + Name: BuildArgsAttr, + IsOptional: true, + ZeroValueProvider: builtin_argument.ZeroValueProvider[*starlark.Dict], + Validator: nil, + }, }, }, Instantiate: instantiateImageBuildSpec, @@ -149,6 +157,22 @@ func (imageBuildSpec *ImageBuildSpec) GetTargetStage() (string, *startosis_error return targetStageStr, nil } +// Dockerfile build-time variables +func (imageBuildSpec *ImageBuildSpec) GetBuildArgs() (map[string]string, *startosis_errors.InterpretationError) { + buildArgsStarlark, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[*starlark.Dict](imageBuildSpec.KurtosisValueTypeDefault, BuildArgsAttr) + if interpretationErr != nil { + return nil, interpretationErr + } + if !found || buildArgsStarlark.Len() == 0 { + return nil, nil + } + buildArgs, interpretationErr := kurtosis_types.SafeCastToMapStringString(buildArgsStarlark, BuildArgsAttr) + if interpretationErr != nil { + return nil, interpretationErr + } + return buildArgs, nil +} + func (imageBuildSpec *ImageBuildSpec) ToKurtosisType( locatorOfModuleInWhichThisBuiltInIsBeingCalled string, packageId string, @@ -181,7 +205,12 @@ func (imageBuildSpec *ImageBuildSpec) ToKurtosisType( return nil, interpretationErr } - return image_build_spec.NewImageBuildSpec(buildContextDirPathOnDisk, containerImageFilePathOnDisk, targetStageStr), nil + buildArgs, interpretationErr := imageBuildSpec.GetBuildArgs() + if interpretationErr != nil { + return nil, interpretationErr + } + + return image_build_spec.NewImageBuildSpec(buildContextDirPathOnDisk, containerImageFilePathOnDisk, targetStageStr, buildArgs), nil } // Returns the filepath of the build context directory and container image on APIC based on package info diff --git a/docs/docs/api-reference/starlark-reference/image-build-spec.md b/docs/docs/api-reference/starlark-reference/image-build-spec.md index d0e6db3c2c..8544c36105 100644 --- a/docs/docs/api-reference/starlark-reference/image-build-spec.md +++ b/docs/docs/api-reference/starlark-reference/image-build-spec.md @@ -26,6 +26,13 @@ Kurtosis starts services based on a provided image definition in the `image` arg # Stage of image build to target for multi-stage container image # OPTIONAL target_stage="" + + # Arguments passed at build-time + # OPTIONAL (Default: {}) + build_args={ + "BUILD_ARG_1": "VALUE_1", + "BUILD_ARG_2": "VALUE_2", + } ) ``` :::info diff --git a/docs/docs/api-reference/starlark-reference/service-config.md b/docs/docs/api-reference/starlark-reference/service-config.md index 9384c061b9..1c6f49dcb3 100644 --- a/docs/docs/api-reference/starlark-reference/service-config.md +++ b/docs/docs/api-reference/starlark-reference/service-config.md @@ -58,6 +58,13 @@ config = ServiceConfig( # Stage of image build to target for multi-stage container image # OPTIONAL target_stage="" + + # Arguments passed at build-time + # OPTIONAL (Default: {}) + build_args={ + "BUILD_ARG_1": "VALUE_1", + "BUILD_ARG_2": "VALUE_2", + } ) OR diff --git a/internal_testsuites/starlark/image-build-package/Dockerfile b/internal_testsuites/starlark/image-build-package/Dockerfile index 0e5cd57abd..4780f6ac10 100644 --- a/internal_testsuites/starlark/image-build-package/Dockerfile +++ b/internal_testsuites/starlark/image-build-package/Dockerfile @@ -4,4 +4,23 @@ WORKDIR /app COPY . . + +# The idea is to test if the build argument has been provided. +# The following commands would not work: + +# $ docker build -t image-build-package-test . +# Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE + +# $ docker build -t image-build-package-test --build-arg "BUILD_ARG=WRONG_VALUE" . +# Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE + +# But this command would work: +# $ docker build -t image-build-package-test --build-arg "BUILD_ARG=VALUE" . + +ARG BUILD_ARG="DEFAULT_VALUE" +RUN if [ "$BUILD_ARG" != "VALUE" ]; then \ + echo "Error: the build argument BUILD_ARG has not been provided or is not equal to VALUE"; \ + exit 1; \ +fi + CMD ["echo", "Hello, Kurtosis!"] diff --git a/internal_testsuites/starlark/image-build-package/main.star b/internal_testsuites/starlark/image-build-package/main.star index 3a6e45cf9a..01d87ee604 100644 --- a/internal_testsuites/starlark/image-build-package/main.star +++ b/internal_testsuites/starlark/image-build-package/main.star @@ -5,6 +5,9 @@ def run(plan, args): image=ImageBuildSpec( image_name="kurtosistech/service", build_context_dir="./", + build_args={ + "BUILD_ARG": "VALUE", + } ), ) ) From be6d7d36fc5d75a0f85c6f2b6bf889923318fd96 Mon Sep 17 00:00:00 2001 From: Kevin Today Date: Wed, 13 Mar 2024 11:28:12 -0300 Subject: [PATCH 05/16] chore: Add reminder to tag reviewers to PR template (#2260) ## Description: ## Is this change user facing? YES/NO ## References (if applicable): --- .github/pull_request_template.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a205c2a4fe..599298b310 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,10 +1,13 @@ -## Description: +## Description +## REMINDER: Tag Reviewers, so they get notified to review + ## Is this change user facing? YES/NO -## References (if applicable): +## References (if applicable) + From 2292010f6a62cfd9aa1b9f0e6616ac02a315e941 Mon Sep 17 00:00:00 2001 From: Tedi Mitiku Date: Wed, 13 Mar 2024 14:30:23 -0400 Subject: [PATCH 06/16] feat: generate plan yamls (#2177) ## Description: This change implements the generation of a yaml that represents the effect of a sequence of instructions on an enclave. The major changes are as follows: - Adds gRPC endpoints `GetStarlarkPackge/ScriptPlanYaml` to APIC and Enclave Manager for returning this yaml - Implements `PlanYaml` object and yaml generation logic in `startosis_engine` - Adds `UpdatePlan(plan *PlanYaml)` method to `KurtosisInstruction` interface so each instruction implements logic for updating the plan yaml - Most of the knowledge needed to generate the yaml comes from the interpretation phase and is simply passed into yaml generation logic Tests are in `startosis_interpreter_plan_yaml_tests.go` and demonstrate how the `InstructionsPlan` generates the yaml via the `PlanYaml` object. eg. starlark script turned plan yaml: ``` def run(plan, hi_files_artifact): service = plan.add_service( name="db", config=ServiceConfig( image="postgres:latest", env_vars={ "POSTGRES_DB": "kurtosis", "POSTGRES_USER": "kurtosis", "POSTGRES_PASSWORD": "kurtosis", }, files = { "/root": hi_files_artifact, } ) ) execResult = plan.exec( service_name="db", recipe=ExecRecipe( command=["echo", service.ip_address + " " + service.hostname] ), acceptable_codes=[0], ) runShResult = plan.run_sh( run="echo " + execResult["code"] + " " + execResult["output"], ) plan.run_sh( run="echo " + runShResult.code + " " + runShResult.output, ) ``` plan yaml: ``` packageId: DEFAULT_PACKAGE_ID_FOR_SCRIPT services: - uuid: "1" name: db image: name: postgres:latest envVars: - key: POSTGRES_DB value: kurtosis - key: POSTGRES_PASSWORD value: kurtosis - key: POSTGRES_USER value: kurtosis files: - mountPath: /root filesArtifacts: - uuid: "2" name: hi-file filesArtifacts: - uuid: "2" name: hi-file tasks: - uuid: "3" taskType: exec command: - echo - '{{ kurtosis.1.ip_address }} {{ kurtosis.1.hostname }}' serviceName: db acceptableCodes: - 0 - uuid: "4" taskType: sh command: - echo {{ kurtosis.3.code }} {{ kurtosis.3.output }} image: badouralix/curl-jq - uuid: "5" taskType: sh command: - echo {{ kurtosis.4.code }} {{ kurtosis.4.output }} image: badouralix/curl-jq ``` ## Is this change user facing? NO ## References: The Enclave Manager uses this plan yaml to render packages in the Enclave Builder: https://github.com/kurtosis-tech/kurtosis/pull/2250 --------- Co-authored-by: Ben Gazzard --- .../api_container_service.pb.go | 596 +++++++++---- .../api_container_service_grpc.pb.go | 78 ++ .../api_container_service.connect.go | 59 ++ api/protobuf/core/api_container_service.proto | 37 + api/rust/src/api_container_api.rs | 197 +++++ .../api_container_service_grpc_pb.d.ts | 10 + .../api_container_service_grpc_pb.js | 57 ++ .../api_container_service_grpc_web_pb.d.ts | 24 + .../api_container_service_grpc_web_pb.js | 122 +++ .../api_container_service_pb.d.ts | 109 +++ .../api_container_service_pb.js | 696 +++++++++++++++ .../api_container_service_connect.d.ts | 24 +- .../connect/api_container_service_connect.js | 24 +- .../connect/api_container_service_pb.d.ts | 106 +++ .../connect/api_container_service_pb.js | 35 + .../api_container_gateway_service_server.go | 16 + core/server/api_container/main.go | 4 +- .../server/api_container_service.go | 106 ++- .../instructions_plan/instructions_plan.go | 16 + .../add_service/add_service.go | 61 +- .../add_service/add_services.go | 7 + .../kurtosis_instruction/exec/exec.go | 44 +- .../get_service/get_service.go | 6 + .../kurtosis_instruction.go | 4 + .../kurtosis_print/kurtosis_print.go | 6 + .../mock_kurtosis_instruction.go | 92 +- .../remove_service/remove_service.go | 6 + .../render_templates/render_templates.go | 13 + .../kurtosis_instruction/request/request.go | 8 + .../start_service/start_service.go | 6 + .../stop_service/stop_service.go | 6 + .../store_service_files.go | 9 + .../kurtosis_instruction/tasks/run_python.go | 18 +- .../kurtosis_instruction/tasks/run_sh.go | 18 +- .../upload_files/upload_files.go | 9 + .../kurtosis_instruction/verify/verify.go | 6 + .../kurtosis_instruction/wait/wait.go | 6 + .../kurtosis_plan_instruction_capabilities.go | 4 + .../kurtosis_plan_instruction_internal.go | 5 + .../service_config/service_config.go | 21 +- .../startosis_engine/plan_yaml/plan_yaml.go | 112 +++ .../plan_yaml/plan_yaml_generator.go | 447 ++++++++++ .../startosis_interpreter_plan_yaml_test.go | 809 ++++++++++++++++++ .../kurtosis_enclave_manager_api.pb.go | 492 ++++++++--- .../kurtosis_enclave_manager_api.connect.go | 56 ++ .../kurtosis_enclave_manager_api_grpc.pb.go | 76 +- .../kurtosis_enclave_manager_api.proto | 19 + .../kurtosis_enclave_manager_api_connect.ts | 24 +- .../src/kurtosis_enclave_manager_api_pb.ts | 106 ++- enclave-manager/server/server.go | 71 ++ 50 files changed, 4533 insertions(+), 350 deletions(-) create mode 100644 core/server/api_container/server/startosis_engine/plan_yaml/plan_yaml.go create mode 100644 core/server/api_container/server/startosis_engine/plan_yaml/plan_yaml_generator.go create mode 100644 core/server/api_container/server/startosis_engine/startosis_interpreter_plan_yaml_test.go diff --git a/api/golang/core/kurtosis_core_rpc_api_bindings/api_container_service.pb.go b/api/golang/core/kurtosis_core_rpc_api_bindings/api_container_service.pb.go index 6407ae89b5..d5d6ddb5e7 100644 --- a/api/golang/core/kurtosis_core_rpc_api_bindings/api_container_service.pb.go +++ b/api/golang/core/kurtosis_core_rpc_api_bindings/api_container_service.pb.go @@ -3289,6 +3289,192 @@ func (x *GetStarlarkRunResponse) GetRestartPolicy() RestartPolicy { return RestartPolicy_NEVER } +type PlanYaml struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PlanYaml string `protobuf:"bytes,1,opt,name=plan_yaml,json=planYaml,proto3" json:"plan_yaml,omitempty"` +} + +func (x *PlanYaml) Reset() { + *x = PlanYaml{} + if protoimpl.UnsafeEnabled { + mi := &file_api_container_service_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PlanYaml) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PlanYaml) ProtoMessage() {} + +func (x *PlanYaml) ProtoReflect() protoreflect.Message { + mi := &file_api_container_service_proto_msgTypes[42] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PlanYaml.ProtoReflect.Descriptor instead. +func (*PlanYaml) Descriptor() ([]byte, []int) { + return file_api_container_service_proto_rawDescGZIP(), []int{42} +} + +func (x *PlanYaml) GetPlanYaml() string { + if x != nil { + return x.PlanYaml + } + return "" +} + +type StarlarkScriptPlanYamlArgs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SerializedScript string `protobuf:"bytes,1,opt,name=serialized_script,json=serializedScript,proto3" json:"serialized_script,omitempty"` + SerializedParams *string `protobuf:"bytes,2,opt,name=serialized_params,json=serializedParams,proto3,oneof" json:"serialized_params,omitempty"` + // The name of the main function, the default value is "run" + MainFunctionName *string `protobuf:"bytes,5,opt,name=main_function_name,json=mainFunctionName,proto3,oneof" json:"main_function_name,omitempty"` +} + +func (x *StarlarkScriptPlanYamlArgs) Reset() { + *x = StarlarkScriptPlanYamlArgs{} + if protoimpl.UnsafeEnabled { + mi := &file_api_container_service_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StarlarkScriptPlanYamlArgs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StarlarkScriptPlanYamlArgs) ProtoMessage() {} + +func (x *StarlarkScriptPlanYamlArgs) ProtoReflect() protoreflect.Message { + mi := &file_api_container_service_proto_msgTypes[43] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StarlarkScriptPlanYamlArgs.ProtoReflect.Descriptor instead. +func (*StarlarkScriptPlanYamlArgs) Descriptor() ([]byte, []int) { + return file_api_container_service_proto_rawDescGZIP(), []int{43} +} + +func (x *StarlarkScriptPlanYamlArgs) GetSerializedScript() string { + if x != nil { + return x.SerializedScript + } + return "" +} + +func (x *StarlarkScriptPlanYamlArgs) GetSerializedParams() string { + if x != nil && x.SerializedParams != nil { + return *x.SerializedParams + } + return "" +} + +func (x *StarlarkScriptPlanYamlArgs) GetMainFunctionName() string { + if x != nil && x.MainFunctionName != nil { + return *x.MainFunctionName + } + return "" +} + +type StarlarkPackagePlanYamlArgs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PackageId string `protobuf:"bytes,1,opt,name=package_id,json=packageId,proto3" json:"package_id,omitempty"` + // Serialized parameters data for the Starlark package main function + // This should be a valid JSON string + SerializedParams *string `protobuf:"bytes,2,opt,name=serialized_params,json=serializedParams,proto3,oneof" json:"serialized_params,omitempty"` + // The relative main file filepath, the default value is the "main.star" file in the root of a package + RelativePathToMainFile *string `protobuf:"bytes,3,opt,name=relative_path_to_main_file,json=relativePathToMainFile,proto3,oneof" json:"relative_path_to_main_file,omitempty"` + // The name of the main function, the default value is "run" + MainFunctionName *string `protobuf:"bytes,4,opt,name=main_function_name,json=mainFunctionName,proto3,oneof" json:"main_function_name,omitempty"` +} + +func (x *StarlarkPackagePlanYamlArgs) Reset() { + *x = StarlarkPackagePlanYamlArgs{} + if protoimpl.UnsafeEnabled { + mi := &file_api_container_service_proto_msgTypes[44] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StarlarkPackagePlanYamlArgs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StarlarkPackagePlanYamlArgs) ProtoMessage() {} + +func (x *StarlarkPackagePlanYamlArgs) ProtoReflect() protoreflect.Message { + mi := &file_api_container_service_proto_msgTypes[44] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StarlarkPackagePlanYamlArgs.ProtoReflect.Descriptor instead. +func (*StarlarkPackagePlanYamlArgs) Descriptor() ([]byte, []int) { + return file_api_container_service_proto_rawDescGZIP(), []int{44} +} + +func (x *StarlarkPackagePlanYamlArgs) GetPackageId() string { + if x != nil { + return x.PackageId + } + return "" +} + +func (x *StarlarkPackagePlanYamlArgs) GetSerializedParams() string { + if x != nil && x.SerializedParams != nil { + return *x.SerializedParams + } + return "" +} + +func (x *StarlarkPackagePlanYamlArgs) GetRelativePathToMainFile() string { + if x != nil && x.RelativePathToMainFile != nil { + return *x.RelativePathToMainFile + } + return "" +} + +func (x *StarlarkPackagePlanYamlArgs) GetMainFunctionName() string { + if x != nil && x.MainFunctionName != nil { + return *x.MainFunctionName + } + return "" +} + var File_api_container_service_proto protoreflect.FileDescriptor var file_api_container_service_proto_rawDesc = []byte{ @@ -3845,139 +4031,188 @@ var file_api_container_service_proto_rawDesc = []byte{ 0x6c, 0x69, 0x63, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0d, 0x72, 0x65, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2a, 0x36, 0x0a, 0x0d, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, - 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, - 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, - 0x4e, 0x10, 0x02, 0x2a, 0x2c, 0x0a, 0x11, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x6f, 0x77, 0x6e, - 0x6c, 0x6f, 0x61, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x61, 0x6c, 0x77, 0x61, - 0x79, 0x73, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x10, - 0x01, 0x2a, 0x26, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x0b, 0x0a, 0x07, - 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x4e, 0x4f, 0x5f, - 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, 0x01, 0x2a, 0x32, 0x0a, 0x13, 0x4b, 0x75, 0x72, - 0x74, 0x6f, 0x73, 0x69, 0x73, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, - 0x12, 0x1b, 0x0a, 0x17, 0x4e, 0x4f, 0x5f, 0x49, 0x4e, 0x53, 0x54, 0x52, 0x55, 0x43, 0x54, 0x49, - 0x4f, 0x4e, 0x53, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x2a, 0x26, 0x0a, - 0x0d, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x09, - 0x0a, 0x05, 0x4e, 0x45, 0x56, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x4c, 0x57, - 0x41, 0x59, 0x53, 0x10, 0x01, 0x32, 0xce, 0x0e, 0x0a, 0x13, 0x41, 0x70, 0x69, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6d, 0x0a, - 0x11, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x53, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x12, 0x28, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, - 0x72, 0x6b, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x2a, 0x2e, 0x61, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x27, 0x0a, 0x08, 0x50, + 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x6e, 0x5f, + 0x79, 0x61, 0x6d, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x6e, + 0x59, 0x61, 0x6d, 0x6c, 0x22, 0xdb, 0x01, 0x0a, 0x1a, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, + 0x6b, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, 0x6c, 0x41, + 0x72, 0x67, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, + 0x64, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, + 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x12, 0x30, 0x0a, 0x11, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x10, 0x73, + 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x88, + 0x01, 0x01, 0x12, 0x31, 0x0a, 0x12, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, + 0x52, 0x10, 0x6d, 0x61, 0x69, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, + 0x6d, 0x65, 0x88, 0x01, 0x01, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x15, 0x0a, 0x13, 0x5f, + 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x22, 0xae, 0x02, 0x0a, 0x1b, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x50, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, 0x6c, 0x41, 0x72, + 0x67, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x49, + 0x64, 0x12, 0x30, 0x0a, 0x11, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, + 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x10, + 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, + 0x88, 0x01, 0x01, 0x12, 0x3f, 0x0a, 0x1a, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, + 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74, 0x6f, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x69, 0x6c, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x16, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x54, 0x6f, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x69, 0x6c, + 0x65, 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, 0x12, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x75, 0x6e, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x02, 0x52, 0x10, 0x6d, 0x61, 0x69, 0x6e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x73, 0x65, 0x72, 0x69, + 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x1d, 0x0a, + 0x1b, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, + 0x74, 0x6f, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x15, 0x0a, 0x13, + 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x2a, 0x36, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0b, + 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x02, 0x2a, 0x2c, 0x0a, 0x11, 0x49, + 0x6d, 0x61, 0x67, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x4d, 0x6f, 0x64, 0x65, + 0x12, 0x0a, 0x0a, 0x06, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x10, 0x01, 0x2a, 0x26, 0x0a, 0x07, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, + 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x4e, 0x4f, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x10, + 0x01, 0x2a, 0x32, 0x0a, 0x13, 0x4b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x46, 0x65, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x1b, 0x0a, 0x17, 0x4e, 0x4f, 0x5f, 0x49, + 0x4e, 0x53, 0x54, 0x52, 0x55, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x43, 0x41, 0x43, 0x48, + 0x49, 0x4e, 0x47, 0x10, 0x00, 0x2a, 0x26, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x4e, 0x45, 0x56, 0x45, 0x52, 0x10, + 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x4c, 0x57, 0x41, 0x59, 0x53, 0x10, 0x01, 0x32, 0xa6, 0x10, + 0x0a, 0x13, 0x41, 0x70, 0x69, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6d, 0x0a, 0x11, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, + 0x6c, 0x61, 0x72, 0x6b, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x28, 0x2e, 0x61, 0x70, 0x69, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x52, + 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x41, 0x72, 0x67, 0x73, 0x1a, 0x2a, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, + 0x6b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4c, 0x69, 0x6e, 0x65, + 0x22, 0x00, 0x30, 0x01, 0x12, 0x59, 0x0a, 0x15, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, + 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x24, 0x2e, + 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, + 0x69, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x43, 0x68, + 0x75, 0x6e, 0x6b, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x28, 0x01, 0x12, + 0x6f, 0x0a, 0x12, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x50, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x29, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, + 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x41, 0x72, 0x67, 0x73, + 0x1a, 0x2a, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4c, 0x69, 0x6e, 0x65, 0x22, 0x00, 0x30, 0x01, + 0x12, 0x5b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, + 0x22, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, + 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x41, + 0x72, 0x67, 0x73, 0x1a, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x8d, 0x01, + 0x0a, 0x2a, 0x47, 0x65, 0x74, 0x45, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x41, 0x6e, 0x64, + 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x45, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x69, 0x73, + 0x74, 0x69, 0x6e, 0x67, 0x41, 0x6e, 0x64, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, + 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, + 0x0b, 0x45, 0x78, 0x65, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, - 0x2e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x4c, 0x69, 0x6e, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x59, 0x0a, 0x15, - 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x50, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x2e, 0x45, 0x78, 0x65, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x72, 0x67, 0x73, + 0x1a, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x79, 0x0a, 0x22, 0x57, 0x61, + 0x69, 0x74, 0x46, 0x6f, 0x72, 0x48, 0x74, 0x74, 0x70, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, + 0x12, 0x39, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x48, 0x74, 0x74, 0x70, + 0x47, 0x65, 0x74, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, + 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x22, 0x00, 0x28, 0x01, 0x12, 0x6f, 0x0a, 0x12, 0x52, 0x75, 0x6e, 0x53, 0x74, - 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x29, 0x2e, - 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, - 0x69, 0x2e, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x50, 0x61, 0x63, - 0x6b, 0x61, 0x67, 0x65, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x2a, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, - 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x4c, 0x69, 0x6e, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x5b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x26, 0x2e, 0x61, 0x70, - 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, - 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x8d, 0x01, 0x0a, 0x2a, 0x47, 0x65, 0x74, 0x45, 0x78, 0x69, - 0x73, 0x74, 0x69, 0x6e, 0x67, 0x41, 0x6e, 0x64, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, - 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, - 0x69, 0x65, 0x72, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x45, 0x2e, 0x61, + 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x7b, 0x0a, 0x23, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, + 0x48, 0x74, 0x74, 0x70, 0x50, 0x6f, 0x73, 0x74, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x3a, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, - 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x41, 0x6e, 0x64, 0x48, - 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x0b, 0x45, 0x78, 0x65, 0x63, 0x43, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x43, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x78, 0x65, - 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x79, 0x0a, 0x22, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x48, 0x74, 0x74, - 0x70, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x76, 0x61, 0x69, - 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x39, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x61, 0x69, - 0x74, 0x46, 0x6f, 0x72, 0x48, 0x74, 0x74, 0x70, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x64, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x41, - 0x72, 0x67, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x7b, 0x0a, - 0x23, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x48, 0x74, 0x74, 0x70, 0x50, 0x6f, 0x73, 0x74, + 0x2e, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x48, 0x74, 0x74, 0x70, 0x50, 0x6f, 0x73, 0x74, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x79, 0x12, 0x3a, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, - 0x48, 0x74, 0x74, 0x70, 0x50, 0x6f, 0x73, 0x74, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x41, 0x72, 0x67, 0x73, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x6f, 0x0a, 0x13, 0x55, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, - 0x74, 0x12, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x64, 0x44, 0x61, - 0x74, 0x61, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x1a, 0x2e, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x6c, 0x6f, - 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x6f, 0x0a, 0x15, 0x44, - 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, - 0x66, 0x61, 0x63, 0x74, 0x12, 0x2c, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, - 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x41, 0x72, - 0x67, 0x73, 0x1a, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x64, 0x44, - 0x61, 0x74, 0x61, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x22, 0x00, 0x30, 0x01, 0x12, 0x79, 0x0a, 0x15, - 0x53, 0x74, 0x6f, 0x72, 0x65, 0x57, 0x65, 0x62, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, - 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x2c, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x57, - 0x65, 0x62, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x41, - 0x72, 0x67, 0x73, 0x1a, 0x30, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x57, 0x65, 0x62, - 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x91, 0x01, 0x0a, 0x1d, 0x53, 0x74, 0x6f, 0x72, - 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x46, 0x72, - 0x6f, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x2e, 0x61, 0x70, 0x69, 0x5f, + 0x6c, 0x69, 0x74, 0x79, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x22, 0x00, 0x12, 0x6f, 0x0a, 0x13, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, + 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, - 0x6f, 0x72, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, - 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x72, 0x67, 0x73, 0x1a, - 0x38, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, - 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, + 0x72, 0x65, 0x61, 0x6d, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x1a, + 0x2e, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, + 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x28, 0x01, 0x12, 0x6f, 0x0a, 0x15, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, + 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x2c, 0x2e, 0x61, + 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, + 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x24, 0x2e, 0x61, 0x70, 0x69, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x43, 0x68, 0x75, 0x6e, 0x6b, + 0x22, 0x00, 0x30, 0x01, 0x12, 0x79, 0x0a, 0x15, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x57, 0x65, 0x62, + 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x2c, 0x2e, + 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, + 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x57, 0x65, 0x62, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x30, 0x2e, 0x61, 0x70, + 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, + 0x53, 0x74, 0x6f, 0x72, 0x65, 0x57, 0x65, 0x62, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x91, 0x01, 0x0a, 0x1d, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x75, 0x0a, 0x1e, 0x4c, - 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x55, 0x75, 0x69, 0x64, 0x73, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x39, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, - 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, - 0x41, 0x6e, 0x64, 0x55, 0x75, 0x69, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x91, 0x01, 0x0a, 0x1c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x46, 0x69, - 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x12, 0x36, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x46, - 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x61, 0x70, + 0x65, 0x12, 0x34, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x38, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, + 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x46, 0x72, + 0x6f, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x75, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x41, 0x6e, 0x64, + 0x55, 0x75, 0x69, 0x64, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x39, 0x2e, + 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, + 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x55, 0x75, 0x69, 0x64, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x91, 0x01, 0x0a, 0x1c, 0x49, + 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x36, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, - 0x66, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x67, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x5f, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x41, 0x72, 0x67, - 0x73, 0x1a, 0x2a, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x66, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x46, + 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x67, + 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x12, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x55, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, - 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x29, 0x2e, 0x61, 0x70, 0x69, 0x5f, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, - 0x74, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x52, 0x5a, 0x50, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x2a, 0x2e, 0x61, 0x70, 0x69, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x74, + 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x29, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, + 0x6b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x69, + 0x0a, 0x19, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x53, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x50, 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x2d, 0x2e, 0x61, 0x70, + 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, + 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x6c, + 0x61, 0x6e, 0x59, 0x61, 0x6d, 0x6c, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x50, + 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, 0x6c, 0x22, 0x00, 0x12, 0x6b, 0x0a, 0x1a, 0x47, 0x65, 0x74, + 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x50, + 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x2e, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x72, + 0x6c, 0x61, 0x72, 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x59, + 0x61, 0x6d, 0x6c, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x6c, 0x61, 0x6e, + 0x59, 0x61, 0x6d, 0x6c, 0x22, 0x00, 0x42, 0x52, 0x5a, 0x50, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x2d, 0x74, 0x65, 0x63, 0x68, 0x2f, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x6b, 0x75, 0x72, 0x74, @@ -3999,7 +4234,7 @@ func file_api_container_service_proto_rawDescGZIP() []byte { } var file_api_container_service_proto_enumTypes = make([]protoimpl.EnumInfo, 7) -var file_api_container_service_proto_msgTypes = make([]protoimpl.MessageInfo, 47) +var file_api_container_service_proto_msgTypes = make([]protoimpl.MessageInfo, 50) var file_api_container_service_proto_goTypes = []interface{}{ (ServiceStatus)(0), // 0: api_container_api.ServiceStatus (ImageDownloadMode)(0), // 1: api_container_api.ImageDownloadMode @@ -4050,19 +4285,22 @@ var file_api_container_service_proto_goTypes = []interface{}{ (*ConnectServicesArgs)(nil), // 46: api_container_api.ConnectServicesArgs (*ConnectServicesResponse)(nil), // 47: api_container_api.ConnectServicesResponse (*GetStarlarkRunResponse)(nil), // 48: api_container_api.GetStarlarkRunResponse - nil, // 49: api_container_api.Container.EnvVarsEntry - nil, // 50: api_container_api.ServiceInfo.PrivatePortsEntry - nil, // 51: api_container_api.ServiceInfo.MaybePublicPortsEntry - nil, // 52: api_container_api.GetServicesArgs.ServiceIdentifiersEntry - nil, // 53: api_container_api.GetServicesResponse.ServiceInfoEntry - (*emptypb.Empty)(nil), // 54: google.protobuf.Empty + (*PlanYaml)(nil), // 49: api_container_api.PlanYaml + (*StarlarkScriptPlanYamlArgs)(nil), // 50: api_container_api.StarlarkScriptPlanYamlArgs + (*StarlarkPackagePlanYamlArgs)(nil), // 51: api_container_api.StarlarkPackagePlanYamlArgs + nil, // 52: api_container_api.Container.EnvVarsEntry + nil, // 53: api_container_api.ServiceInfo.PrivatePortsEntry + nil, // 54: api_container_api.ServiceInfo.MaybePublicPortsEntry + nil, // 55: api_container_api.GetServicesArgs.ServiceIdentifiersEntry + nil, // 56: api_container_api.GetServicesResponse.ServiceInfoEntry + (*emptypb.Empty)(nil), // 57: google.protobuf.Empty } var file_api_container_service_proto_depIdxs = []int32{ 5, // 0: api_container_api.Port.transport_protocol:type_name -> api_container_api.Port.TransportProtocol 6, // 1: api_container_api.Container.status:type_name -> api_container_api.Container.Status - 49, // 2: api_container_api.Container.env_vars:type_name -> api_container_api.Container.EnvVarsEntry - 50, // 3: api_container_api.ServiceInfo.private_ports:type_name -> api_container_api.ServiceInfo.PrivatePortsEntry - 51, // 4: api_container_api.ServiceInfo.maybe_public_ports:type_name -> api_container_api.ServiceInfo.MaybePublicPortsEntry + 52, // 2: api_container_api.Container.env_vars:type_name -> api_container_api.Container.EnvVarsEntry + 53, // 3: api_container_api.ServiceInfo.private_ports:type_name -> api_container_api.ServiceInfo.PrivatePortsEntry + 54, // 4: api_container_api.ServiceInfo.maybe_public_ports:type_name -> api_container_api.ServiceInfo.MaybePublicPortsEntry 0, // 5: api_container_api.ServiceInfo.service_status:type_name -> api_container_api.ServiceStatus 8, // 6: api_container_api.ServiceInfo.container:type_name -> api_container_api.Container 3, // 7: api_container_api.RunStarlarkScriptArgs.experimental_features:type_name -> api_container_api.KurtosisFeatureFlag @@ -4081,8 +4319,8 @@ var file_api_container_service_proto_depIdxs = []int32{ 20, // 20: api_container_api.StarlarkError.interpretation_error:type_name -> api_container_api.StarlarkInterpretationError 21, // 21: api_container_api.StarlarkError.validation_error:type_name -> api_container_api.StarlarkValidationError 22, // 22: api_container_api.StarlarkError.execution_error:type_name -> api_container_api.StarlarkExecutionError - 52, // 23: api_container_api.GetServicesArgs.service_identifiers:type_name -> api_container_api.GetServicesArgs.ServiceIdentifiersEntry - 53, // 24: api_container_api.GetServicesResponse.service_info:type_name -> api_container_api.GetServicesResponse.ServiceInfoEntry + 55, // 23: api_container_api.GetServicesArgs.service_identifiers:type_name -> api_container_api.GetServicesArgs.ServiceIdentifiersEntry + 56, // 24: api_container_api.GetServicesResponse.service_info:type_name -> api_container_api.GetServicesResponse.ServiceInfoEntry 27, // 25: api_container_api.GetExistingAndHistoricalServiceIdentifiersResponse.allIdentifiers:type_name -> api_container_api.ServiceIdentifiers 34, // 26: api_container_api.StreamedDataChunk.metadata:type_name -> api_container_api.DataChunkMetadata 41, // 27: api_container_api.ListFilesArtifactNamesAndUuidsResponse.file_names_and_uuids:type_name -> api_container_api.FilesArtifactNameAndUuid @@ -4098,7 +4336,7 @@ var file_api_container_service_proto_depIdxs = []int32{ 33, // 37: api_container_api.ApiContainerService.UploadStarlarkPackage:input_type -> api_container_api.StreamedDataChunk 11, // 38: api_container_api.ApiContainerService.RunStarlarkPackage:input_type -> api_container_api.RunStarlarkPackageArgs 25, // 39: api_container_api.ApiContainerService.GetServices:input_type -> api_container_api.GetServicesArgs - 54, // 40: api_container_api.ApiContainerService.GetExistingAndHistoricalServiceIdentifiers:input_type -> google.protobuf.Empty + 57, // 40: api_container_api.ApiContainerService.GetExistingAndHistoricalServiceIdentifiers:input_type -> google.protobuf.Empty 29, // 41: api_container_api.ApiContainerService.ExecCommand:input_type -> api_container_api.ExecCommandArgs 31, // 42: api_container_api.ApiContainerService.WaitForHttpGetEndpointAvailability:input_type -> api_container_api.WaitForHttpGetEndpointAvailabilityArgs 32, // 43: api_container_api.ApiContainerService.WaitForHttpPostEndpointAvailability:input_type -> api_container_api.WaitForHttpPostEndpointAvailabilityArgs @@ -4106,28 +4344,32 @@ var file_api_container_service_proto_depIdxs = []int32{ 36, // 45: api_container_api.ApiContainerService.DownloadFilesArtifact:input_type -> api_container_api.DownloadFilesArtifactArgs 37, // 46: api_container_api.ApiContainerService.StoreWebFilesArtifact:input_type -> api_container_api.StoreWebFilesArtifactArgs 39, // 47: api_container_api.ApiContainerService.StoreFilesArtifactFromService:input_type -> api_container_api.StoreFilesArtifactFromServiceArgs - 54, // 48: api_container_api.ApiContainerService.ListFilesArtifactNamesAndUuids:input_type -> google.protobuf.Empty + 57, // 48: api_container_api.ApiContainerService.ListFilesArtifactNamesAndUuids:input_type -> google.protobuf.Empty 43, // 49: api_container_api.ApiContainerService.InspectFilesArtifactContents:input_type -> api_container_api.InspectFilesArtifactContentsRequest 46, // 50: api_container_api.ApiContainerService.ConnectServices:input_type -> api_container_api.ConnectServicesArgs - 54, // 51: api_container_api.ApiContainerService.GetStarlarkRun:input_type -> google.protobuf.Empty - 12, // 52: api_container_api.ApiContainerService.RunStarlarkScript:output_type -> api_container_api.StarlarkRunResponseLine - 54, // 53: api_container_api.ApiContainerService.UploadStarlarkPackage:output_type -> google.protobuf.Empty - 12, // 54: api_container_api.ApiContainerService.RunStarlarkPackage:output_type -> api_container_api.StarlarkRunResponseLine - 26, // 55: api_container_api.ApiContainerService.GetServices:output_type -> api_container_api.GetServicesResponse - 28, // 56: api_container_api.ApiContainerService.GetExistingAndHistoricalServiceIdentifiers:output_type -> api_container_api.GetExistingAndHistoricalServiceIdentifiersResponse - 30, // 57: api_container_api.ApiContainerService.ExecCommand:output_type -> api_container_api.ExecCommandResponse - 54, // 58: api_container_api.ApiContainerService.WaitForHttpGetEndpointAvailability:output_type -> google.protobuf.Empty - 54, // 59: api_container_api.ApiContainerService.WaitForHttpPostEndpointAvailability:output_type -> google.protobuf.Empty - 35, // 60: api_container_api.ApiContainerService.UploadFilesArtifact:output_type -> api_container_api.UploadFilesArtifactResponse - 33, // 61: api_container_api.ApiContainerService.DownloadFilesArtifact:output_type -> api_container_api.StreamedDataChunk - 38, // 62: api_container_api.ApiContainerService.StoreWebFilesArtifact:output_type -> api_container_api.StoreWebFilesArtifactResponse - 40, // 63: api_container_api.ApiContainerService.StoreFilesArtifactFromService:output_type -> api_container_api.StoreFilesArtifactFromServiceResponse - 42, // 64: api_container_api.ApiContainerService.ListFilesArtifactNamesAndUuids:output_type -> api_container_api.ListFilesArtifactNamesAndUuidsResponse - 44, // 65: api_container_api.ApiContainerService.InspectFilesArtifactContents:output_type -> api_container_api.InspectFilesArtifactContentsResponse - 47, // 66: api_container_api.ApiContainerService.ConnectServices:output_type -> api_container_api.ConnectServicesResponse - 48, // 67: api_container_api.ApiContainerService.GetStarlarkRun:output_type -> api_container_api.GetStarlarkRunResponse - 52, // [52:68] is the sub-list for method output_type - 36, // [36:52] is the sub-list for method input_type + 57, // 51: api_container_api.ApiContainerService.GetStarlarkRun:input_type -> google.protobuf.Empty + 50, // 52: api_container_api.ApiContainerService.GetStarlarkScriptPlanYaml:input_type -> api_container_api.StarlarkScriptPlanYamlArgs + 51, // 53: api_container_api.ApiContainerService.GetStarlarkPackagePlanYaml:input_type -> api_container_api.StarlarkPackagePlanYamlArgs + 12, // 54: api_container_api.ApiContainerService.RunStarlarkScript:output_type -> api_container_api.StarlarkRunResponseLine + 57, // 55: api_container_api.ApiContainerService.UploadStarlarkPackage:output_type -> google.protobuf.Empty + 12, // 56: api_container_api.ApiContainerService.RunStarlarkPackage:output_type -> api_container_api.StarlarkRunResponseLine + 26, // 57: api_container_api.ApiContainerService.GetServices:output_type -> api_container_api.GetServicesResponse + 28, // 58: api_container_api.ApiContainerService.GetExistingAndHistoricalServiceIdentifiers:output_type -> api_container_api.GetExistingAndHistoricalServiceIdentifiersResponse + 30, // 59: api_container_api.ApiContainerService.ExecCommand:output_type -> api_container_api.ExecCommandResponse + 57, // 60: api_container_api.ApiContainerService.WaitForHttpGetEndpointAvailability:output_type -> google.protobuf.Empty + 57, // 61: api_container_api.ApiContainerService.WaitForHttpPostEndpointAvailability:output_type -> google.protobuf.Empty + 35, // 62: api_container_api.ApiContainerService.UploadFilesArtifact:output_type -> api_container_api.UploadFilesArtifactResponse + 33, // 63: api_container_api.ApiContainerService.DownloadFilesArtifact:output_type -> api_container_api.StreamedDataChunk + 38, // 64: api_container_api.ApiContainerService.StoreWebFilesArtifact:output_type -> api_container_api.StoreWebFilesArtifactResponse + 40, // 65: api_container_api.ApiContainerService.StoreFilesArtifactFromService:output_type -> api_container_api.StoreFilesArtifactFromServiceResponse + 42, // 66: api_container_api.ApiContainerService.ListFilesArtifactNamesAndUuids:output_type -> api_container_api.ListFilesArtifactNamesAndUuidsResponse + 44, // 67: api_container_api.ApiContainerService.InspectFilesArtifactContents:output_type -> api_container_api.InspectFilesArtifactContentsResponse + 47, // 68: api_container_api.ApiContainerService.ConnectServices:output_type -> api_container_api.ConnectServicesResponse + 48, // 69: api_container_api.ApiContainerService.GetStarlarkRun:output_type -> api_container_api.GetStarlarkRunResponse + 49, // 70: api_container_api.ApiContainerService.GetStarlarkScriptPlanYaml:output_type -> api_container_api.PlanYaml + 49, // 71: api_container_api.ApiContainerService.GetStarlarkPackagePlanYaml:output_type -> api_container_api.PlanYaml + 54, // [54:72] is the sub-list for method output_type + 36, // [36:54] is the sub-list for method input_type 36, // [36:36] is the sub-list for extension type_name 36, // [36:36] is the sub-list for extension extendee 0, // [0:36] is the sub-list for field type_name @@ -4643,6 +4885,42 @@ func file_api_container_service_proto_init() { return nil } } + file_api_container_service_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PlanYaml); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_container_service_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StarlarkScriptPlanYamlArgs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_container_service_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StarlarkPackagePlanYamlArgs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_api_container_service_proto_msgTypes[3].OneofWrappers = []interface{}{} file_api_container_service_proto_msgTypes[4].OneofWrappers = []interface{}{ @@ -4668,13 +4946,15 @@ func file_api_container_service_proto_init() { file_api_container_service_proto_msgTypes[24].OneofWrappers = []interface{}{} file_api_container_service_proto_msgTypes[25].OneofWrappers = []interface{}{} file_api_container_service_proto_msgTypes[38].OneofWrappers = []interface{}{} + file_api_container_service_proto_msgTypes[43].OneofWrappers = []interface{}{} + file_api_container_service_proto_msgTypes[44].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_api_container_service_proto_rawDesc, NumEnums: 7, - NumMessages: 47, + NumMessages: 50, NumExtensions: 0, NumServices: 1, }, diff --git a/api/golang/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc.pb.go b/api/golang/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc.pb.go index ca2ca2f836..b0740c5e5f 100644 --- a/api/golang/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc.pb.go +++ b/api/golang/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc.pb.go @@ -36,6 +36,8 @@ const ( ApiContainerService_InspectFilesArtifactContents_FullMethodName = "/api_container_api.ApiContainerService/InspectFilesArtifactContents" ApiContainerService_ConnectServices_FullMethodName = "/api_container_api.ApiContainerService/ConnectServices" ApiContainerService_GetStarlarkRun_FullMethodName = "/api_container_api.ApiContainerService/GetStarlarkRun" + ApiContainerService_GetStarlarkScriptPlanYaml_FullMethodName = "/api_container_api.ApiContainerService/GetStarlarkScriptPlanYaml" + ApiContainerService_GetStarlarkPackagePlanYaml_FullMethodName = "/api_container_api.ApiContainerService/GetStarlarkPackagePlanYaml" ) // ApiContainerServiceClient is the client API for ApiContainerService service. @@ -72,6 +74,10 @@ type ApiContainerServiceClient interface { ConnectServices(ctx context.Context, in *ConnectServicesArgs, opts ...grpc.CallOption) (*ConnectServicesResponse, error) // Get last Starlark run GetStarlarkRun(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetStarlarkRunResponse, error) + // Gets yaml representing the plan the script will execute in an enclave + GetStarlarkScriptPlanYaml(ctx context.Context, in *StarlarkScriptPlanYamlArgs, opts ...grpc.CallOption) (*PlanYaml, error) + // Gets yaml representing the plan the package will execute in an enclave + GetStarlarkPackagePlanYaml(ctx context.Context, in *StarlarkPackagePlanYamlArgs, opts ...grpc.CallOption) (*PlanYaml, error) } type apiContainerServiceClient struct { @@ -345,6 +351,24 @@ func (c *apiContainerServiceClient) GetStarlarkRun(ctx context.Context, in *empt return out, nil } +func (c *apiContainerServiceClient) GetStarlarkScriptPlanYaml(ctx context.Context, in *StarlarkScriptPlanYamlArgs, opts ...grpc.CallOption) (*PlanYaml, error) { + out := new(PlanYaml) + err := c.cc.Invoke(ctx, ApiContainerService_GetStarlarkScriptPlanYaml_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *apiContainerServiceClient) GetStarlarkPackagePlanYaml(ctx context.Context, in *StarlarkPackagePlanYamlArgs, opts ...grpc.CallOption) (*PlanYaml, error) { + out := new(PlanYaml) + err := c.cc.Invoke(ctx, ApiContainerService_GetStarlarkPackagePlanYaml_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ApiContainerServiceServer is the server API for ApiContainerService service. // All implementations should embed UnimplementedApiContainerServiceServer // for forward compatibility @@ -379,6 +403,10 @@ type ApiContainerServiceServer interface { ConnectServices(context.Context, *ConnectServicesArgs) (*ConnectServicesResponse, error) // Get last Starlark run GetStarlarkRun(context.Context, *emptypb.Empty) (*GetStarlarkRunResponse, error) + // Gets yaml representing the plan the script will execute in an enclave + GetStarlarkScriptPlanYaml(context.Context, *StarlarkScriptPlanYamlArgs) (*PlanYaml, error) + // Gets yaml representing the plan the package will execute in an enclave + GetStarlarkPackagePlanYaml(context.Context, *StarlarkPackagePlanYamlArgs) (*PlanYaml, error) } // UnimplementedApiContainerServiceServer should be embedded to have forward compatible implementations. @@ -433,6 +461,12 @@ func (UnimplementedApiContainerServiceServer) ConnectServices(context.Context, * func (UnimplementedApiContainerServiceServer) GetStarlarkRun(context.Context, *emptypb.Empty) (*GetStarlarkRunResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetStarlarkRun not implemented") } +func (UnimplementedApiContainerServiceServer) GetStarlarkScriptPlanYaml(context.Context, *StarlarkScriptPlanYamlArgs) (*PlanYaml, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetStarlarkScriptPlanYaml not implemented") +} +func (UnimplementedApiContainerServiceServer) GetStarlarkPackagePlanYaml(context.Context, *StarlarkPackagePlanYamlArgs) (*PlanYaml, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetStarlarkPackagePlanYaml not implemented") +} // UnsafeApiContainerServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to ApiContainerServiceServer will @@ -758,6 +792,42 @@ func _ApiContainerService_GetStarlarkRun_Handler(srv interface{}, ctx context.Co return interceptor(ctx, in, info, handler) } +func _ApiContainerService_GetStarlarkScriptPlanYaml_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StarlarkScriptPlanYamlArgs) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ApiContainerServiceServer).GetStarlarkScriptPlanYaml(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ApiContainerService_GetStarlarkScriptPlanYaml_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ApiContainerServiceServer).GetStarlarkScriptPlanYaml(ctx, req.(*StarlarkScriptPlanYamlArgs)) + } + return interceptor(ctx, in, info, handler) +} + +func _ApiContainerService_GetStarlarkPackagePlanYaml_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StarlarkPackagePlanYamlArgs) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ApiContainerServiceServer).GetStarlarkPackagePlanYaml(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ApiContainerService_GetStarlarkPackagePlanYaml_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ApiContainerServiceServer).GetStarlarkPackagePlanYaml(ctx, req.(*StarlarkPackagePlanYamlArgs)) + } + return interceptor(ctx, in, info, handler) +} + // ApiContainerService_ServiceDesc is the grpc.ServiceDesc for ApiContainerService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -809,6 +879,14 @@ var ApiContainerService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetStarlarkRun", Handler: _ApiContainerService_GetStarlarkRun_Handler, }, + { + MethodName: "GetStarlarkScriptPlanYaml", + Handler: _ApiContainerService_GetStarlarkScriptPlanYaml_Handler, + }, + { + MethodName: "GetStarlarkPackagePlanYaml", + Handler: _ApiContainerService_GetStarlarkPackagePlanYaml_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/api/golang/core/kurtosis_core_rpc_api_bindings/kurtosis_core_rpc_api_bindingsconnect/api_container_service.connect.go b/api/golang/core/kurtosis_core_rpc_api_bindings/kurtosis_core_rpc_api_bindingsconnect/api_container_service.connect.go index f20776712f..81807b84e2 100644 --- a/api/golang/core/kurtosis_core_rpc_api_bindings/kurtosis_core_rpc_api_bindingsconnect/api_container_service.connect.go +++ b/api/golang/core/kurtosis_core_rpc_api_bindings/kurtosis_core_rpc_api_bindingsconnect/api_container_service.connect.go @@ -82,6 +82,12 @@ const ( // ApiContainerServiceGetStarlarkRunProcedure is the fully-qualified name of the // ApiContainerService's GetStarlarkRun RPC. ApiContainerServiceGetStarlarkRunProcedure = "/api_container_api.ApiContainerService/GetStarlarkRun" + // ApiContainerServiceGetStarlarkScriptPlanYamlProcedure is the fully-qualified name of the + // ApiContainerService's GetStarlarkScriptPlanYaml RPC. + ApiContainerServiceGetStarlarkScriptPlanYamlProcedure = "/api_container_api.ApiContainerService/GetStarlarkScriptPlanYaml" + // ApiContainerServiceGetStarlarkPackagePlanYamlProcedure is the fully-qualified name of the + // ApiContainerService's GetStarlarkPackagePlanYaml RPC. + ApiContainerServiceGetStarlarkPackagePlanYamlProcedure = "/api_container_api.ApiContainerService/GetStarlarkPackagePlanYaml" ) // ApiContainerServiceClient is a client for the api_container_api.ApiContainerService service. @@ -116,6 +122,10 @@ type ApiContainerServiceClient interface { ConnectServices(context.Context, *connect.Request[kurtosis_core_rpc_api_bindings.ConnectServicesArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.ConnectServicesResponse], error) // Get last Starlark run GetStarlarkRun(context.Context, *connect.Request[emptypb.Empty]) (*connect.Response[kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse], error) + // Gets yaml representing the plan the script will execute in an enclave + GetStarlarkScriptPlanYaml(context.Context, *connect.Request[kurtosis_core_rpc_api_bindings.StarlarkScriptPlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) + // Gets yaml representing the plan the package will execute in an enclave + GetStarlarkPackagePlanYaml(context.Context, *connect.Request[kurtosis_core_rpc_api_bindings.StarlarkPackagePlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) } // NewApiContainerServiceClient constructs a client for the api_container_api.ApiContainerService @@ -208,6 +218,16 @@ func NewApiContainerServiceClient(httpClient connect.HTTPClient, baseURL string, baseURL+ApiContainerServiceGetStarlarkRunProcedure, opts..., ), + getStarlarkScriptPlanYaml: connect.NewClient[kurtosis_core_rpc_api_bindings.StarlarkScriptPlanYamlArgs, kurtosis_core_rpc_api_bindings.PlanYaml]( + httpClient, + baseURL+ApiContainerServiceGetStarlarkScriptPlanYamlProcedure, + opts..., + ), + getStarlarkPackagePlanYaml: connect.NewClient[kurtosis_core_rpc_api_bindings.StarlarkPackagePlanYamlArgs, kurtosis_core_rpc_api_bindings.PlanYaml]( + httpClient, + baseURL+ApiContainerServiceGetStarlarkPackagePlanYamlProcedure, + opts..., + ), } } @@ -229,6 +249,8 @@ type apiContainerServiceClient struct { inspectFilesArtifactContents *connect.Client[kurtosis_core_rpc_api_bindings.InspectFilesArtifactContentsRequest, kurtosis_core_rpc_api_bindings.InspectFilesArtifactContentsResponse] connectServices *connect.Client[kurtosis_core_rpc_api_bindings.ConnectServicesArgs, kurtosis_core_rpc_api_bindings.ConnectServicesResponse] getStarlarkRun *connect.Client[emptypb.Empty, kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse] + getStarlarkScriptPlanYaml *connect.Client[kurtosis_core_rpc_api_bindings.StarlarkScriptPlanYamlArgs, kurtosis_core_rpc_api_bindings.PlanYaml] + getStarlarkPackagePlanYaml *connect.Client[kurtosis_core_rpc_api_bindings.StarlarkPackagePlanYamlArgs, kurtosis_core_rpc_api_bindings.PlanYaml] } // RunStarlarkScript calls api_container_api.ApiContainerService.RunStarlarkScript. @@ -317,6 +339,17 @@ func (c *apiContainerServiceClient) GetStarlarkRun(ctx context.Context, req *con return c.getStarlarkRun.CallUnary(ctx, req) } +// GetStarlarkScriptPlanYaml calls api_container_api.ApiContainerService.GetStarlarkScriptPlanYaml. +func (c *apiContainerServiceClient) GetStarlarkScriptPlanYaml(ctx context.Context, req *connect.Request[kurtosis_core_rpc_api_bindings.StarlarkScriptPlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) { + return c.getStarlarkScriptPlanYaml.CallUnary(ctx, req) +} + +// GetStarlarkPackagePlanYaml calls +// api_container_api.ApiContainerService.GetStarlarkPackagePlanYaml. +func (c *apiContainerServiceClient) GetStarlarkPackagePlanYaml(ctx context.Context, req *connect.Request[kurtosis_core_rpc_api_bindings.StarlarkPackagePlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) { + return c.getStarlarkPackagePlanYaml.CallUnary(ctx, req) +} + // ApiContainerServiceHandler is an implementation of the api_container_api.ApiContainerService // service. type ApiContainerServiceHandler interface { @@ -350,6 +383,10 @@ type ApiContainerServiceHandler interface { ConnectServices(context.Context, *connect.Request[kurtosis_core_rpc_api_bindings.ConnectServicesArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.ConnectServicesResponse], error) // Get last Starlark run GetStarlarkRun(context.Context, *connect.Request[emptypb.Empty]) (*connect.Response[kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse], error) + // Gets yaml representing the plan the script will execute in an enclave + GetStarlarkScriptPlanYaml(context.Context, *connect.Request[kurtosis_core_rpc_api_bindings.StarlarkScriptPlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) + // Gets yaml representing the plan the package will execute in an enclave + GetStarlarkPackagePlanYaml(context.Context, *connect.Request[kurtosis_core_rpc_api_bindings.StarlarkPackagePlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) } // NewApiContainerServiceHandler builds an HTTP handler from the service implementation. It returns @@ -438,6 +475,16 @@ func NewApiContainerServiceHandler(svc ApiContainerServiceHandler, opts ...conne svc.GetStarlarkRun, opts..., ) + apiContainerServiceGetStarlarkScriptPlanYamlHandler := connect.NewUnaryHandler( + ApiContainerServiceGetStarlarkScriptPlanYamlProcedure, + svc.GetStarlarkScriptPlanYaml, + opts..., + ) + apiContainerServiceGetStarlarkPackagePlanYamlHandler := connect.NewUnaryHandler( + ApiContainerServiceGetStarlarkPackagePlanYamlProcedure, + svc.GetStarlarkPackagePlanYaml, + opts..., + ) return "/api_container_api.ApiContainerService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case ApiContainerServiceRunStarlarkScriptProcedure: @@ -472,6 +519,10 @@ func NewApiContainerServiceHandler(svc ApiContainerServiceHandler, opts ...conne apiContainerServiceConnectServicesHandler.ServeHTTP(w, r) case ApiContainerServiceGetStarlarkRunProcedure: apiContainerServiceGetStarlarkRunHandler.ServeHTTP(w, r) + case ApiContainerServiceGetStarlarkScriptPlanYamlProcedure: + apiContainerServiceGetStarlarkScriptPlanYamlHandler.ServeHTTP(w, r) + case ApiContainerServiceGetStarlarkPackagePlanYamlProcedure: + apiContainerServiceGetStarlarkPackagePlanYamlHandler.ServeHTTP(w, r) default: http.NotFound(w, r) } @@ -544,3 +595,11 @@ func (UnimplementedApiContainerServiceHandler) ConnectServices(context.Context, func (UnimplementedApiContainerServiceHandler) GetStarlarkRun(context.Context, *connect.Request[emptypb.Empty]) (*connect.Response[kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse], error) { return nil, connect.NewError(connect.CodeUnimplemented, errors.New("api_container_api.ApiContainerService.GetStarlarkRun is not implemented")) } + +func (UnimplementedApiContainerServiceHandler) GetStarlarkScriptPlanYaml(context.Context, *connect.Request[kurtosis_core_rpc_api_bindings.StarlarkScriptPlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("api_container_api.ApiContainerService.GetStarlarkScriptPlanYaml is not implemented")) +} + +func (UnimplementedApiContainerServiceHandler) GetStarlarkPackagePlanYaml(context.Context, *connect.Request[kurtosis_core_rpc_api_bindings.StarlarkPackagePlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("api_container_api.ApiContainerService.GetStarlarkPackagePlanYaml is not implemented")) +} diff --git a/api/protobuf/core/api_container_service.proto b/api/protobuf/core/api_container_service.proto index 01049313e3..440c49d9cb 100644 --- a/api/protobuf/core/api_container_service.proto +++ b/api/protobuf/core/api_container_service.proto @@ -53,6 +53,12 @@ service ApiContainerService { // Get last Starlark run rpc GetStarlarkRun(google.protobuf.Empty) returns (GetStarlarkRunResponse) {}; + + // Gets yaml representing the plan the script will execute in an enclave + rpc GetStarlarkScriptPlanYaml(StarlarkScriptPlanYamlArgs) returns (PlanYaml) {}; + + // Gets yaml representing the plan the package will execute in an enclave + rpc GetStarlarkPackagePlanYaml(StarlarkPackagePlanYamlArgs) returns (PlanYaml) {}; } // ============================================================================================== @@ -564,3 +570,34 @@ message GetStarlarkRunResponse { RestartPolicy restart_policy = 8; } + +// ============================================================================================== +// Get Starlark Plan Yaml +// ============================================================================================== + +message PlanYaml { + string plan_yaml = 1; +} + +message StarlarkScriptPlanYamlArgs { + string serialized_script = 1; + + optional string serialized_params = 2; + + // The name of the main function, the default value is "run" + optional string main_function_name = 5; +} + +message StarlarkPackagePlanYamlArgs { + string package_id = 1; + + // Serialized parameters data for the Starlark package main function + // This should be a valid JSON string + optional string serialized_params = 2; + + // The relative main file filepath, the default value is the "main.star" file in the root of a package + optional string relative_path_to_main_file = 3; + + // The name of the main function, the default value is "run" + optional string main_function_name = 4; +} diff --git a/api/rust/src/api_container_api.rs b/api/rust/src/api_container_api.rs index 494dfa631d..a65f41f1c1 100644 --- a/api/rust/src/api_container_api.rs +++ b/api/rust/src/api_container_api.rs @@ -679,6 +679,41 @@ pub struct GetStarlarkRunResponse { #[prost(enumeration = "RestartPolicy", tag = "8")] pub restart_policy: i32, } +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PlanYaml { + #[prost(string, tag = "1")] + pub plan_yaml: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StarlarkScriptPlanYamlArgs { + #[prost(string, tag = "1")] + pub serialized_script: ::prost::alloc::string::String, + #[prost(string, optional, tag = "2")] + pub serialized_params: ::core::option::Option<::prost::alloc::string::String>, + /// The name of the main function, the default value is "run" + #[prost(string, optional, tag = "5")] + pub main_function_name: ::core::option::Option<::prost::alloc::string::String>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StarlarkPackagePlanYamlArgs { + #[prost(string, tag = "1")] + pub package_id: ::prost::alloc::string::String, + /// Serialized parameters data for the Starlark package main function + /// This should be a valid JSON string + #[prost(string, optional, tag = "2")] + pub serialized_params: ::core::option::Option<::prost::alloc::string::String>, + /// The relative main file filepath, the default value is the "main.star" file in the root of a package + #[prost(string, optional, tag = "3")] + pub relative_path_to_main_file: ::core::option::Option< + ::prost::alloc::string::String, + >, + /// The name of the main function, the default value is "run" + #[prost(string, optional, tag = "4")] + pub main_function_name: ::core::option::Option<::prost::alloc::string::String>, +} #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum ServiceStatus { @@ -1389,6 +1424,62 @@ pub mod api_container_service_client { ); self.inner.unary(req, path, codec).await } + /// Gets yaml representing the plan the script will execute in an enclave + pub async fn get_starlark_script_plan_yaml( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/api_container_api.ApiContainerService/GetStarlarkScriptPlanYaml", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "api_container_api.ApiContainerService", + "GetStarlarkScriptPlanYaml", + ), + ); + self.inner.unary(req, path, codec).await + } + /// Gets yaml representing the plan the package will execute in an enclave + pub async fn get_starlark_package_plan_yaml( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/api_container_api.ApiContainerService/GetStarlarkPackagePlanYaml", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "api_container_api.ApiContainerService", + "GetStarlarkPackagePlanYaml", + ), + ); + self.inner.unary(req, path, codec).await + } } } /// Generated server implementations. @@ -1533,6 +1624,16 @@ pub mod api_container_service_server { tonic::Response, tonic::Status, >; + /// Gets yaml representing the plan the script will execute in an enclave + async fn get_starlark_script_plan_yaml( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + /// Gets yaml representing the plan the package will execute in an enclave + async fn get_starlark_package_plan_yaml( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; } #[derive(Debug)] pub struct ApiContainerServiceServer { @@ -2379,6 +2480,102 @@ pub mod api_container_service_server { }; Box::pin(fut) } + "/api_container_api.ApiContainerService/GetStarlarkScriptPlanYaml" => { + #[allow(non_camel_case_types)] + struct GetStarlarkScriptPlanYamlSvc( + pub Arc, + ); + impl< + T: ApiContainerService, + > tonic::server::UnaryService + for GetStarlarkScriptPlanYamlSvc { + type Response = super::PlanYaml; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + (*inner).get_starlark_script_plan_yaml(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetStarlarkScriptPlanYamlSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/api_container_api.ApiContainerService/GetStarlarkPackagePlanYaml" => { + #[allow(non_camel_case_types)] + struct GetStarlarkPackagePlanYamlSvc( + pub Arc, + ); + impl< + T: ApiContainerService, + > tonic::server::UnaryService + for GetStarlarkPackagePlanYamlSvc { + type Response = super::PlanYaml; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + (*inner).get_starlark_package_plan_yaml(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetStarlarkPackagePlanYamlSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } _ => { Box::pin(async move { Ok( diff --git a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_pb.d.ts b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_pb.d.ts index a574331973..81a95fd280 100644 --- a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_pb.d.ts +++ b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_pb.d.ts @@ -24,6 +24,8 @@ interface IApiContainerServiceService extends grpc.ServiceDefinition; connectServices: grpc.MethodDefinition; getStarlarkRun: grpc.MethodDefinition; + getStarlarkScriptPlanYaml: grpc.MethodDefinition; + getStarlarkPackagePlanYaml: grpc.MethodDefinition; } export const ApiContainerServiceService: IApiContainerServiceService; @@ -45,6 +47,8 @@ export interface IApiContainerServiceServer extends grpc.UntypedServiceImplement inspectFilesArtifactContents: grpc.handleUnaryCall; connectServices: grpc.handleUnaryCall; getStarlarkRun: grpc.handleUnaryCall; + getStarlarkScriptPlanYaml: grpc.handleUnaryCall; + getStarlarkPackagePlanYaml: grpc.handleUnaryCall; } export class ApiContainerServiceClient extends grpc.Client { @@ -94,4 +98,10 @@ export class ApiContainerServiceClient extends grpc.Client { getStarlarkRun(argument: google_protobuf_empty_pb.Empty, callback: grpc.requestCallback): grpc.ClientUnaryCall; getStarlarkRun(argument: google_protobuf_empty_pb.Empty, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; getStarlarkRun(argument: google_protobuf_empty_pb.Empty, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; + getStarlarkScriptPlanYaml(argument: api_container_service_pb.StarlarkScriptPlanYamlArgs, callback: grpc.requestCallback): grpc.ClientUnaryCall; + getStarlarkScriptPlanYaml(argument: api_container_service_pb.StarlarkScriptPlanYamlArgs, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; + getStarlarkScriptPlanYaml(argument: api_container_service_pb.StarlarkScriptPlanYamlArgs, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; + getStarlarkPackagePlanYaml(argument: api_container_service_pb.StarlarkPackagePlanYamlArgs, callback: grpc.requestCallback): grpc.ClientUnaryCall; + getStarlarkPackagePlanYaml(argument: api_container_service_pb.StarlarkPackagePlanYamlArgs, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; + getStarlarkPackagePlanYaml(argument: api_container_service_pb.StarlarkPackagePlanYamlArgs, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback): grpc.ClientUnaryCall; } diff --git a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_pb.js b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_pb.js index ac624f7ecf..d79e19ea23 100644 --- a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_pb.js +++ b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_pb.js @@ -137,6 +137,17 @@ function deserialize_api_container_api_ListFilesArtifactNamesAndUuidsResponse(bu return api_container_service_pb.ListFilesArtifactNamesAndUuidsResponse.deserializeBinary(new Uint8Array(buffer_arg)); } +function serialize_api_container_api_PlanYaml(arg) { + if (!(arg instanceof api_container_service_pb.PlanYaml)) { + throw new Error('Expected argument of type api_container_api.PlanYaml'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_api_container_api_PlanYaml(buffer_arg) { + return api_container_service_pb.PlanYaml.deserializeBinary(new Uint8Array(buffer_arg)); +} + function serialize_api_container_api_RunStarlarkPackageArgs(arg) { if (!(arg instanceof api_container_service_pb.RunStarlarkPackageArgs)) { throw new Error('Expected argument of type api_container_api.RunStarlarkPackageArgs'); @@ -159,6 +170,17 @@ function deserialize_api_container_api_RunStarlarkScriptArgs(buffer_arg) { return api_container_service_pb.RunStarlarkScriptArgs.deserializeBinary(new Uint8Array(buffer_arg)); } +function serialize_api_container_api_StarlarkPackagePlanYamlArgs(arg) { + if (!(arg instanceof api_container_service_pb.StarlarkPackagePlanYamlArgs)) { + throw new Error('Expected argument of type api_container_api.StarlarkPackagePlanYamlArgs'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_api_container_api_StarlarkPackagePlanYamlArgs(buffer_arg) { + return api_container_service_pb.StarlarkPackagePlanYamlArgs.deserializeBinary(new Uint8Array(buffer_arg)); +} + function serialize_api_container_api_StarlarkRunResponseLine(arg) { if (!(arg instanceof api_container_service_pb.StarlarkRunResponseLine)) { throw new Error('Expected argument of type api_container_api.StarlarkRunResponseLine'); @@ -170,6 +192,17 @@ function deserialize_api_container_api_StarlarkRunResponseLine(buffer_arg) { return api_container_service_pb.StarlarkRunResponseLine.deserializeBinary(new Uint8Array(buffer_arg)); } +function serialize_api_container_api_StarlarkScriptPlanYamlArgs(arg) { + if (!(arg instanceof api_container_service_pb.StarlarkScriptPlanYamlArgs)) { + throw new Error('Expected argument of type api_container_api.StarlarkScriptPlanYamlArgs'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_api_container_api_StarlarkScriptPlanYamlArgs(buffer_arg) { + return api_container_service_pb.StarlarkScriptPlanYamlArgs.deserializeBinary(new Uint8Array(buffer_arg)); +} + function serialize_api_container_api_StoreFilesArtifactFromServiceArgs(arg) { if (!(arg instanceof api_container_service_pb.StoreFilesArtifactFromServiceArgs)) { throw new Error('Expected argument of type api_container_api.StoreFilesArtifactFromServiceArgs'); @@ -461,6 +494,30 @@ getStarlarkRun: { responseSerialize: serialize_api_container_api_GetStarlarkRunResponse, responseDeserialize: deserialize_api_container_api_GetStarlarkRunResponse, }, + // Gets yaml representing the plan the script will execute in an enclave +getStarlarkScriptPlanYaml: { + path: '/api_container_api.ApiContainerService/GetStarlarkScriptPlanYaml', + requestStream: false, + responseStream: false, + requestType: api_container_service_pb.StarlarkScriptPlanYamlArgs, + responseType: api_container_service_pb.PlanYaml, + requestSerialize: serialize_api_container_api_StarlarkScriptPlanYamlArgs, + requestDeserialize: deserialize_api_container_api_StarlarkScriptPlanYamlArgs, + responseSerialize: serialize_api_container_api_PlanYaml, + responseDeserialize: deserialize_api_container_api_PlanYaml, + }, + // Gets yaml representing the plan the package will execute in an enclave +getStarlarkPackagePlanYaml: { + path: '/api_container_api.ApiContainerService/GetStarlarkPackagePlanYaml', + requestStream: false, + responseStream: false, + requestType: api_container_service_pb.StarlarkPackagePlanYamlArgs, + responseType: api_container_service_pb.PlanYaml, + requestSerialize: serialize_api_container_api_StarlarkPackagePlanYamlArgs, + requestDeserialize: deserialize_api_container_api_StarlarkPackagePlanYamlArgs, + responseSerialize: serialize_api_container_api_PlanYaml, + responseDeserialize: deserialize_api_container_api_PlanYaml, + }, }; exports.ApiContainerServiceClient = grpc.makeGenericClientConstructor(ApiContainerServiceService); diff --git a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_web_pb.d.ts b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_web_pb.d.ts index f5505b0e0e..4b1d68af33 100644 --- a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_web_pb.d.ts +++ b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_web_pb.d.ts @@ -101,6 +101,20 @@ export class ApiContainerServiceClient { response: api_container_service_pb.GetStarlarkRunResponse) => void ): grpcWeb.ClientReadableStream; + getStarlarkScriptPlanYaml( + request: api_container_service_pb.StarlarkScriptPlanYamlArgs, + metadata: grpcWeb.Metadata | undefined, + callback: (err: grpcWeb.RpcError, + response: api_container_service_pb.PlanYaml) => void + ): grpcWeb.ClientReadableStream; + + getStarlarkPackagePlanYaml( + request: api_container_service_pb.StarlarkPackagePlanYamlArgs, + metadata: grpcWeb.Metadata | undefined, + callback: (err: grpcWeb.RpcError, + response: api_container_service_pb.PlanYaml) => void + ): grpcWeb.ClientReadableStream; + } export class ApiContainerServicePromiseClient { @@ -178,5 +192,15 @@ export class ApiContainerServicePromiseClient { metadata?: grpcWeb.Metadata ): Promise; + getStarlarkScriptPlanYaml( + request: api_container_service_pb.StarlarkScriptPlanYamlArgs, + metadata?: grpcWeb.Metadata + ): Promise; + + getStarlarkPackagePlanYaml( + request: api_container_service_pb.StarlarkPackagePlanYamlArgs, + metadata?: grpcWeb.Metadata + ): Promise; + } diff --git a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_web_pb.js b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_web_pb.js index 07732d2fbc..d21fe965e4 100644 --- a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_web_pb.js +++ b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_grpc_web_pb.js @@ -915,5 +915,127 @@ proto.api_container_api.ApiContainerServicePromiseClient.prototype.getStarlarkRu }; +/** + * @const + * @type {!grpc.web.MethodDescriptor< + * !proto.api_container_api.StarlarkScriptPlanYamlArgs, + * !proto.api_container_api.PlanYaml>} + */ +const methodDescriptor_ApiContainerService_GetStarlarkScriptPlanYaml = new grpc.web.MethodDescriptor( + '/api_container_api.ApiContainerService/GetStarlarkScriptPlanYaml', + grpc.web.MethodType.UNARY, + proto.api_container_api.StarlarkScriptPlanYamlArgs, + proto.api_container_api.PlanYaml, + /** + * @param {!proto.api_container_api.StarlarkScriptPlanYamlArgs} request + * @return {!Uint8Array} + */ + function(request) { + return request.serializeBinary(); + }, + proto.api_container_api.PlanYaml.deserializeBinary +); + + +/** + * @param {!proto.api_container_api.StarlarkScriptPlanYamlArgs} request The + * request proto + * @param {?Object} metadata User defined + * call metadata + * @param {function(?grpc.web.RpcError, ?proto.api_container_api.PlanYaml)} + * callback The callback function(error, response) + * @return {!grpc.web.ClientReadableStream|undefined} + * The XHR Node Readable Stream + */ +proto.api_container_api.ApiContainerServiceClient.prototype.getStarlarkScriptPlanYaml = + function(request, metadata, callback) { + return this.client_.rpcCall(this.hostname_ + + '/api_container_api.ApiContainerService/GetStarlarkScriptPlanYaml', + request, + metadata || {}, + methodDescriptor_ApiContainerService_GetStarlarkScriptPlanYaml, + callback); +}; + + +/** + * @param {!proto.api_container_api.StarlarkScriptPlanYamlArgs} request The + * request proto + * @param {?Object=} metadata User defined + * call metadata + * @return {!Promise} + * Promise that resolves to the response + */ +proto.api_container_api.ApiContainerServicePromiseClient.prototype.getStarlarkScriptPlanYaml = + function(request, metadata) { + return this.client_.unaryCall(this.hostname_ + + '/api_container_api.ApiContainerService/GetStarlarkScriptPlanYaml', + request, + metadata || {}, + methodDescriptor_ApiContainerService_GetStarlarkScriptPlanYaml); +}; + + +/** + * @const + * @type {!grpc.web.MethodDescriptor< + * !proto.api_container_api.StarlarkPackagePlanYamlArgs, + * !proto.api_container_api.PlanYaml>} + */ +const methodDescriptor_ApiContainerService_GetStarlarkPackagePlanYaml = new grpc.web.MethodDescriptor( + '/api_container_api.ApiContainerService/GetStarlarkPackagePlanYaml', + grpc.web.MethodType.UNARY, + proto.api_container_api.StarlarkPackagePlanYamlArgs, + proto.api_container_api.PlanYaml, + /** + * @param {!proto.api_container_api.StarlarkPackagePlanYamlArgs} request + * @return {!Uint8Array} + */ + function(request) { + return request.serializeBinary(); + }, + proto.api_container_api.PlanYaml.deserializeBinary +); + + +/** + * @param {!proto.api_container_api.StarlarkPackagePlanYamlArgs} request The + * request proto + * @param {?Object} metadata User defined + * call metadata + * @param {function(?grpc.web.RpcError, ?proto.api_container_api.PlanYaml)} + * callback The callback function(error, response) + * @return {!grpc.web.ClientReadableStream|undefined} + * The XHR Node Readable Stream + */ +proto.api_container_api.ApiContainerServiceClient.prototype.getStarlarkPackagePlanYaml = + function(request, metadata, callback) { + return this.client_.rpcCall(this.hostname_ + + '/api_container_api.ApiContainerService/GetStarlarkPackagePlanYaml', + request, + metadata || {}, + methodDescriptor_ApiContainerService_GetStarlarkPackagePlanYaml, + callback); +}; + + +/** + * @param {!proto.api_container_api.StarlarkPackagePlanYamlArgs} request The + * request proto + * @param {?Object=} metadata User defined + * call metadata + * @return {!Promise} + * Promise that resolves to the response + */ +proto.api_container_api.ApiContainerServicePromiseClient.prototype.getStarlarkPackagePlanYaml = + function(request, metadata) { + return this.client_.unaryCall(this.hostname_ + + '/api_container_api.ApiContainerService/GetStarlarkPackagePlanYaml', + request, + metadata || {}, + methodDescriptor_ApiContainerService_GetStarlarkPackagePlanYaml); +}; + + module.exports = proto.api_container_api; diff --git a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_pb.d.ts b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_pb.d.ts index 13742313fe..7310abe338 100644 --- a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_pb.d.ts +++ b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_pb.d.ts @@ -1435,6 +1435,115 @@ export namespace GetStarlarkRunResponse { } } +export class PlanYaml extends jspb.Message { + getPlanYaml(): string; + setPlanYaml(value: string): PlanYaml; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): PlanYaml.AsObject; + static toObject(includeInstance: boolean, msg: PlanYaml): PlanYaml.AsObject; + static serializeBinaryToWriter(message: PlanYaml, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): PlanYaml; + static deserializeBinaryFromReader(message: PlanYaml, reader: jspb.BinaryReader): PlanYaml; +} + +export namespace PlanYaml { + export type AsObject = { + planYaml: string, + } +} + +export class StarlarkScriptPlanYamlArgs extends jspb.Message { + getSerializedScript(): string; + setSerializedScript(value: string): StarlarkScriptPlanYamlArgs; + + getSerializedParams(): string; + setSerializedParams(value: string): StarlarkScriptPlanYamlArgs; + hasSerializedParams(): boolean; + clearSerializedParams(): StarlarkScriptPlanYamlArgs; + + getMainFunctionName(): string; + setMainFunctionName(value: string): StarlarkScriptPlanYamlArgs; + hasMainFunctionName(): boolean; + clearMainFunctionName(): StarlarkScriptPlanYamlArgs; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): StarlarkScriptPlanYamlArgs.AsObject; + static toObject(includeInstance: boolean, msg: StarlarkScriptPlanYamlArgs): StarlarkScriptPlanYamlArgs.AsObject; + static serializeBinaryToWriter(message: StarlarkScriptPlanYamlArgs, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): StarlarkScriptPlanYamlArgs; + static deserializeBinaryFromReader(message: StarlarkScriptPlanYamlArgs, reader: jspb.BinaryReader): StarlarkScriptPlanYamlArgs; +} + +export namespace StarlarkScriptPlanYamlArgs { + export type AsObject = { + serializedScript: string, + serializedParams?: string, + mainFunctionName?: string, + } + + export enum SerializedParamsCase { + _SERIALIZED_PARAMS_NOT_SET = 0, + SERIALIZED_PARAMS = 2, + } + + export enum MainFunctionNameCase { + _MAIN_FUNCTION_NAME_NOT_SET = 0, + MAIN_FUNCTION_NAME = 5, + } +} + +export class StarlarkPackagePlanYamlArgs extends jspb.Message { + getPackageId(): string; + setPackageId(value: string): StarlarkPackagePlanYamlArgs; + + getSerializedParams(): string; + setSerializedParams(value: string): StarlarkPackagePlanYamlArgs; + hasSerializedParams(): boolean; + clearSerializedParams(): StarlarkPackagePlanYamlArgs; + + getRelativePathToMainFile(): string; + setRelativePathToMainFile(value: string): StarlarkPackagePlanYamlArgs; + hasRelativePathToMainFile(): boolean; + clearRelativePathToMainFile(): StarlarkPackagePlanYamlArgs; + + getMainFunctionName(): string; + setMainFunctionName(value: string): StarlarkPackagePlanYamlArgs; + hasMainFunctionName(): boolean; + clearMainFunctionName(): StarlarkPackagePlanYamlArgs; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): StarlarkPackagePlanYamlArgs.AsObject; + static toObject(includeInstance: boolean, msg: StarlarkPackagePlanYamlArgs): StarlarkPackagePlanYamlArgs.AsObject; + static serializeBinaryToWriter(message: StarlarkPackagePlanYamlArgs, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): StarlarkPackagePlanYamlArgs; + static deserializeBinaryFromReader(message: StarlarkPackagePlanYamlArgs, reader: jspb.BinaryReader): StarlarkPackagePlanYamlArgs; +} + +export namespace StarlarkPackagePlanYamlArgs { + export type AsObject = { + packageId: string, + serializedParams?: string, + relativePathToMainFile?: string, + mainFunctionName?: string, + } + + export enum SerializedParamsCase { + _SERIALIZED_PARAMS_NOT_SET = 0, + SERIALIZED_PARAMS = 2, + } + + export enum RelativePathToMainFileCase { + _RELATIVE_PATH_TO_MAIN_FILE_NOT_SET = 0, + RELATIVE_PATH_TO_MAIN_FILE = 3, + } + + export enum MainFunctionNameCase { + _MAIN_FUNCTION_NAME_NOT_SET = 0, + MAIN_FUNCTION_NAME = 4, + } +} + export enum ServiceStatus { STOPPED = 0, RUNNING = 1, diff --git a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_pb.js b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_pb.js index 49174b1033..316a1532ff 100644 --- a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_pb.js +++ b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/api_container_service_pb.js @@ -43,6 +43,7 @@ goog.exportSymbol('proto.api_container_api.InspectFilesArtifactContentsRequest', goog.exportSymbol('proto.api_container_api.InspectFilesArtifactContentsResponse', null, global); goog.exportSymbol('proto.api_container_api.KurtosisFeatureFlag', null, global); goog.exportSymbol('proto.api_container_api.ListFilesArtifactNamesAndUuidsResponse', null, global); +goog.exportSymbol('proto.api_container_api.PlanYaml', null, global); goog.exportSymbol('proto.api_container_api.Port', null, global); goog.exportSymbol('proto.api_container_api.Port.TransportProtocol', null, global); goog.exportSymbol('proto.api_container_api.RestartPolicy', null, global); @@ -61,10 +62,12 @@ goog.exportSymbol('proto.api_container_api.StarlarkInstructionArg', null, global goog.exportSymbol('proto.api_container_api.StarlarkInstructionPosition', null, global); goog.exportSymbol('proto.api_container_api.StarlarkInstructionResult', null, global); goog.exportSymbol('proto.api_container_api.StarlarkInterpretationError', null, global); +goog.exportSymbol('proto.api_container_api.StarlarkPackagePlanYamlArgs', null, global); goog.exportSymbol('proto.api_container_api.StarlarkRunFinishedEvent', null, global); goog.exportSymbol('proto.api_container_api.StarlarkRunProgress', null, global); goog.exportSymbol('proto.api_container_api.StarlarkRunResponseLine', null, global); goog.exportSymbol('proto.api_container_api.StarlarkRunResponseLine.RunResponseLineCase', null, global); +goog.exportSymbol('proto.api_container_api.StarlarkScriptPlanYamlArgs', null, global); goog.exportSymbol('proto.api_container_api.StarlarkValidationError', null, global); goog.exportSymbol('proto.api_container_api.StarlarkWarning', null, global); goog.exportSymbol('proto.api_container_api.StoreFilesArtifactFromServiceArgs', null, global); @@ -957,6 +960,69 @@ if (goog.DEBUG && !COMPILED) { */ proto.api_container_api.GetStarlarkRunResponse.displayName = 'proto.api_container_api.GetStarlarkRunResponse'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.api_container_api.PlanYaml = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.api_container_api.PlanYaml, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.api_container_api.PlanYaml.displayName = 'proto.api_container_api.PlanYaml'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.api_container_api.StarlarkScriptPlanYamlArgs, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.api_container_api.StarlarkScriptPlanYamlArgs.displayName = 'proto.api_container_api.StarlarkScriptPlanYamlArgs'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.api_container_api.StarlarkPackagePlanYamlArgs, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.api_container_api.StarlarkPackagePlanYamlArgs.displayName = 'proto.api_container_api.StarlarkPackagePlanYamlArgs'; +} @@ -10460,6 +10526,636 @@ proto.api_container_api.GetStarlarkRunResponse.prototype.setRestartPolicy = func }; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.api_container_api.PlanYaml.prototype.toObject = function(opt_includeInstance) { + return proto.api_container_api.PlanYaml.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.api_container_api.PlanYaml} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.api_container_api.PlanYaml.toObject = function(includeInstance, msg) { + var f, obj = { + planYaml: jspb.Message.getFieldWithDefault(msg, 1, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.api_container_api.PlanYaml} + */ +proto.api_container_api.PlanYaml.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.api_container_api.PlanYaml; + return proto.api_container_api.PlanYaml.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.api_container_api.PlanYaml} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.api_container_api.PlanYaml} + */ +proto.api_container_api.PlanYaml.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setPlanYaml(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.api_container_api.PlanYaml.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.api_container_api.PlanYaml.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.api_container_api.PlanYaml} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.api_container_api.PlanYaml.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getPlanYaml(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } +}; + + +/** + * optional string plan_yaml = 1; + * @return {string} + */ +proto.api_container_api.PlanYaml.prototype.getPlanYaml = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.api_container_api.PlanYaml} returns this + */ +proto.api_container_api.PlanYaml.prototype.setPlanYaml = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.prototype.toObject = function(opt_includeInstance) { + return proto.api_container_api.StarlarkScriptPlanYamlArgs.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.api_container_api.StarlarkScriptPlanYamlArgs} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.toObject = function(includeInstance, msg) { + var f, obj = { + serializedScript: jspb.Message.getFieldWithDefault(msg, 1, ""), + serializedParams: jspb.Message.getFieldWithDefault(msg, 2, ""), + mainFunctionName: jspb.Message.getFieldWithDefault(msg, 5, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.api_container_api.StarlarkScriptPlanYamlArgs} + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.api_container_api.StarlarkScriptPlanYamlArgs; + return proto.api_container_api.StarlarkScriptPlanYamlArgs.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.api_container_api.StarlarkScriptPlanYamlArgs} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.api_container_api.StarlarkScriptPlanYamlArgs} + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setSerializedScript(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setSerializedParams(value); + break; + case 5: + var value = /** @type {string} */ (reader.readString()); + msg.setMainFunctionName(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.api_container_api.StarlarkScriptPlanYamlArgs.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.api_container_api.StarlarkScriptPlanYamlArgs} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getSerializedScript(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 2)); + if (f != null) { + writer.writeString( + 2, + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 5)); + if (f != null) { + writer.writeString( + 5, + f + ); + } +}; + + +/** + * optional string serialized_script = 1; + * @return {string} + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.prototype.getSerializedScript = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.api_container_api.StarlarkScriptPlanYamlArgs} returns this + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.prototype.setSerializedScript = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string serialized_params = 2; + * @return {string} + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.prototype.getSerializedParams = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.api_container_api.StarlarkScriptPlanYamlArgs} returns this + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.prototype.setSerializedParams = function(value) { + return jspb.Message.setField(this, 2, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.api_container_api.StarlarkScriptPlanYamlArgs} returns this + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.prototype.clearSerializedParams = function() { + return jspb.Message.setField(this, 2, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.prototype.hasSerializedParams = function() { + return jspb.Message.getField(this, 2) != null; +}; + + +/** + * optional string main_function_name = 5; + * @return {string} + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.prototype.getMainFunctionName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); +}; + + +/** + * @param {string} value + * @return {!proto.api_container_api.StarlarkScriptPlanYamlArgs} returns this + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.prototype.setMainFunctionName = function(value) { + return jspb.Message.setField(this, 5, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.api_container_api.StarlarkScriptPlanYamlArgs} returns this + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.prototype.clearMainFunctionName = function() { + return jspb.Message.setField(this, 5, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.api_container_api.StarlarkScriptPlanYamlArgs.prototype.hasMainFunctionName = function() { + return jspb.Message.getField(this, 5) != null; +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.toObject = function(opt_includeInstance) { + return proto.api_container_api.StarlarkPackagePlanYamlArgs.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.api_container_api.StarlarkPackagePlanYamlArgs} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.toObject = function(includeInstance, msg) { + var f, obj = { + packageId: jspb.Message.getFieldWithDefault(msg, 1, ""), + serializedParams: jspb.Message.getFieldWithDefault(msg, 2, ""), + relativePathToMainFile: jspb.Message.getFieldWithDefault(msg, 3, ""), + mainFunctionName: jspb.Message.getFieldWithDefault(msg, 4, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.api_container_api.StarlarkPackagePlanYamlArgs} + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.api_container_api.StarlarkPackagePlanYamlArgs; + return proto.api_container_api.StarlarkPackagePlanYamlArgs.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.api_container_api.StarlarkPackagePlanYamlArgs} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.api_container_api.StarlarkPackagePlanYamlArgs} + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setPackageId(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setSerializedParams(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setRelativePathToMainFile(value); + break; + case 4: + var value = /** @type {string} */ (reader.readString()); + msg.setMainFunctionName(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.api_container_api.StarlarkPackagePlanYamlArgs.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.api_container_api.StarlarkPackagePlanYamlArgs} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getPackageId(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 2)); + if (f != null) { + writer.writeString( + 2, + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 3)); + if (f != null) { + writer.writeString( + 3, + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 4)); + if (f != null) { + writer.writeString( + 4, + f + ); + } +}; + + +/** + * optional string package_id = 1; + * @return {string} + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.getPackageId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.api_container_api.StarlarkPackagePlanYamlArgs} returns this + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.setPackageId = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string serialized_params = 2; + * @return {string} + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.getSerializedParams = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.api_container_api.StarlarkPackagePlanYamlArgs} returns this + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.setSerializedParams = function(value) { + return jspb.Message.setField(this, 2, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.api_container_api.StarlarkPackagePlanYamlArgs} returns this + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.clearSerializedParams = function() { + return jspb.Message.setField(this, 2, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.hasSerializedParams = function() { + return jspb.Message.getField(this, 2) != null; +}; + + +/** + * optional string relative_path_to_main_file = 3; + * @return {string} + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.getRelativePathToMainFile = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.api_container_api.StarlarkPackagePlanYamlArgs} returns this + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.setRelativePathToMainFile = function(value) { + return jspb.Message.setField(this, 3, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.api_container_api.StarlarkPackagePlanYamlArgs} returns this + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.clearRelativePathToMainFile = function() { + return jspb.Message.setField(this, 3, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.hasRelativePathToMainFile = function() { + return jspb.Message.getField(this, 3) != null; +}; + + +/** + * optional string main_function_name = 4; + * @return {string} + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.getMainFunctionName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * @param {string} value + * @return {!proto.api_container_api.StarlarkPackagePlanYamlArgs} returns this + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.setMainFunctionName = function(value) { + return jspb.Message.setField(this, 4, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.api_container_api.StarlarkPackagePlanYamlArgs} returns this + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.clearMainFunctionName = function() { + return jspb.Message.setField(this, 4, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.api_container_api.StarlarkPackagePlanYamlArgs.prototype.hasMainFunctionName = function() { + return jspb.Message.getField(this, 4) != null; +}; + + /** * @enum {number} */ diff --git a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_connect.d.ts b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_connect.d.ts index 201f76f184..a8be359ca1 100644 --- a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_connect.d.ts +++ b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_connect.d.ts @@ -3,7 +3,7 @@ /* eslint-disable */ // @ts-nocheck -import { ConnectServicesArgs, ConnectServicesResponse, DownloadFilesArtifactArgs, ExecCommandArgs, ExecCommandResponse, GetExistingAndHistoricalServiceIdentifiersResponse, GetServicesArgs, GetServicesResponse, GetStarlarkRunResponse, InspectFilesArtifactContentsRequest, InspectFilesArtifactContentsResponse, ListFilesArtifactNamesAndUuidsResponse, RunStarlarkPackageArgs, RunStarlarkScriptArgs, StarlarkRunResponseLine, StoreFilesArtifactFromServiceArgs, StoreFilesArtifactFromServiceResponse, StoreWebFilesArtifactArgs, StoreWebFilesArtifactResponse, StreamedDataChunk, UploadFilesArtifactResponse, WaitForHttpGetEndpointAvailabilityArgs, WaitForHttpPostEndpointAvailabilityArgs } from "./api_container_service_pb.js"; +import { ConnectServicesArgs, ConnectServicesResponse, DownloadFilesArtifactArgs, ExecCommandArgs, ExecCommandResponse, GetExistingAndHistoricalServiceIdentifiersResponse, GetServicesArgs, GetServicesResponse, GetStarlarkRunResponse, InspectFilesArtifactContentsRequest, InspectFilesArtifactContentsResponse, ListFilesArtifactNamesAndUuidsResponse, PlanYaml, RunStarlarkPackageArgs, RunStarlarkScriptArgs, StarlarkPackagePlanYamlArgs, StarlarkRunResponseLine, StarlarkScriptPlanYamlArgs, StoreFilesArtifactFromServiceArgs, StoreFilesArtifactFromServiceResponse, StoreWebFilesArtifactArgs, StoreWebFilesArtifactResponse, StreamedDataChunk, UploadFilesArtifactResponse, WaitForHttpGetEndpointAvailabilityArgs, WaitForHttpPostEndpointAvailabilityArgs } from "./api_container_service_pb.js"; import { Empty, MethodKind } from "@bufbuild/protobuf"; /** @@ -184,6 +184,28 @@ export declare const ApiContainerService: { readonly O: typeof GetStarlarkRunResponse, readonly kind: MethodKind.Unary, }, + /** + * Gets yaml representing the plan the script will execute in an enclave + * + * @generated from rpc api_container_api.ApiContainerService.GetStarlarkScriptPlanYaml + */ + readonly getStarlarkScriptPlanYaml: { + readonly name: "GetStarlarkScriptPlanYaml", + readonly I: typeof StarlarkScriptPlanYamlArgs, + readonly O: typeof PlanYaml, + readonly kind: MethodKind.Unary, + }, + /** + * Gets yaml representing the plan the package will execute in an enclave + * + * @generated from rpc api_container_api.ApiContainerService.GetStarlarkPackagePlanYaml + */ + readonly getStarlarkPackagePlanYaml: { + readonly name: "GetStarlarkPackagePlanYaml", + readonly I: typeof StarlarkPackagePlanYamlArgs, + readonly O: typeof PlanYaml, + readonly kind: MethodKind.Unary, + }, } }; diff --git a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_connect.js b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_connect.js index 627620d9d8..a3c7ddc8e0 100644 --- a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_connect.js +++ b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_connect.js @@ -3,7 +3,7 @@ /* eslint-disable */ // @ts-nocheck -import { ConnectServicesArgs, ConnectServicesResponse, DownloadFilesArtifactArgs, ExecCommandArgs, ExecCommandResponse, GetExistingAndHistoricalServiceIdentifiersResponse, GetServicesArgs, GetServicesResponse, GetStarlarkRunResponse, InspectFilesArtifactContentsRequest, InspectFilesArtifactContentsResponse, ListFilesArtifactNamesAndUuidsResponse, RunStarlarkPackageArgs, RunStarlarkScriptArgs, StarlarkRunResponseLine, StoreFilesArtifactFromServiceArgs, StoreFilesArtifactFromServiceResponse, StoreWebFilesArtifactArgs, StoreWebFilesArtifactResponse, StreamedDataChunk, UploadFilesArtifactResponse, WaitForHttpGetEndpointAvailabilityArgs, WaitForHttpPostEndpointAvailabilityArgs } from "./api_container_service_pb.js"; +import { ConnectServicesArgs, ConnectServicesResponse, DownloadFilesArtifactArgs, ExecCommandArgs, ExecCommandResponse, GetExistingAndHistoricalServiceIdentifiersResponse, GetServicesArgs, GetServicesResponse, GetStarlarkRunResponse, InspectFilesArtifactContentsRequest, InspectFilesArtifactContentsResponse, ListFilesArtifactNamesAndUuidsResponse, PlanYaml, RunStarlarkPackageArgs, RunStarlarkScriptArgs, StarlarkPackagePlanYamlArgs, StarlarkRunResponseLine, StarlarkScriptPlanYamlArgs, StoreFilesArtifactFromServiceArgs, StoreFilesArtifactFromServiceResponse, StoreWebFilesArtifactArgs, StoreWebFilesArtifactResponse, StreamedDataChunk, UploadFilesArtifactResponse, WaitForHttpGetEndpointAvailabilityArgs, WaitForHttpPostEndpointAvailabilityArgs } from "./api_container_service_pb.js"; import { Empty, MethodKind } from "@bufbuild/protobuf"; /** @@ -184,6 +184,28 @@ export const ApiContainerService = { O: GetStarlarkRunResponse, kind: MethodKind.Unary, }, + /** + * Gets yaml representing the plan the script will execute in an enclave + * + * @generated from rpc api_container_api.ApiContainerService.GetStarlarkScriptPlanYaml + */ + getStarlarkScriptPlanYaml: { + name: "GetStarlarkScriptPlanYaml", + I: StarlarkScriptPlanYamlArgs, + O: PlanYaml, + kind: MethodKind.Unary, + }, + /** + * Gets yaml representing the plan the package will execute in an enclave + * + * @generated from rpc api_container_api.ApiContainerService.GetStarlarkPackagePlanYaml + */ + getStarlarkPackagePlanYaml: { + name: "GetStarlarkPackagePlanYaml", + I: StarlarkPackagePlanYamlArgs, + O: PlanYaml, + kind: MethodKind.Unary, + }, } }; diff --git a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_pb.d.ts b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_pb.d.ts index b45831ded6..3fbfbeb5f8 100644 --- a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_pb.d.ts +++ b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_pb.d.ts @@ -1809,3 +1809,109 @@ export declare class GetStarlarkRunResponse extends Message | undefined, b: GetStarlarkRunResponse | PlainMessage | undefined): boolean; } +/** + * @generated from message api_container_api.PlanYaml + */ +export declare class PlanYaml extends Message { + /** + * @generated from field: string plan_yaml = 1; + */ + planYaml: string; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "api_container_api.PlanYaml"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): PlanYaml; + + static fromJson(jsonValue: JsonValue, options?: Partial): PlanYaml; + + static fromJsonString(jsonString: string, options?: Partial): PlanYaml; + + static equals(a: PlanYaml | PlainMessage | undefined, b: PlanYaml | PlainMessage | undefined): boolean; +} + +/** + * @generated from message api_container_api.StarlarkScriptPlanYamlArgs + */ +export declare class StarlarkScriptPlanYamlArgs extends Message { + /** + * @generated from field: string serialized_script = 1; + */ + serializedScript: string; + + /** + * @generated from field: optional string serialized_params = 2; + */ + serializedParams?: string; + + /** + * The name of the main function, the default value is "run" + * + * @generated from field: optional string main_function_name = 5; + */ + mainFunctionName?: string; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "api_container_api.StarlarkScriptPlanYamlArgs"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): StarlarkScriptPlanYamlArgs; + + static fromJson(jsonValue: JsonValue, options?: Partial): StarlarkScriptPlanYamlArgs; + + static fromJsonString(jsonString: string, options?: Partial): StarlarkScriptPlanYamlArgs; + + static equals(a: StarlarkScriptPlanYamlArgs | PlainMessage | undefined, b: StarlarkScriptPlanYamlArgs | PlainMessage | undefined): boolean; +} + +/** + * @generated from message api_container_api.StarlarkPackagePlanYamlArgs + */ +export declare class StarlarkPackagePlanYamlArgs extends Message { + /** + * @generated from field: string package_id = 1; + */ + packageId: string; + + /** + * Serialized parameters data for the Starlark package main function + * This should be a valid JSON string + * + * @generated from field: optional string serialized_params = 2; + */ + serializedParams?: string; + + /** + * The relative main file filepath, the default value is the "main.star" file in the root of a package + * + * @generated from field: optional string relative_path_to_main_file = 3; + */ + relativePathToMainFile?: string; + + /** + * The name of the main function, the default value is "run" + * + * @generated from field: optional string main_function_name = 4; + */ + mainFunctionName?: string; + + constructor(data?: PartialMessage); + + static readonly runtime: typeof proto3; + static readonly typeName = "api_container_api.StarlarkPackagePlanYamlArgs"; + static readonly fields: FieldList; + + static fromBinary(bytes: Uint8Array, options?: Partial): StarlarkPackagePlanYamlArgs; + + static fromJson(jsonValue: JsonValue, options?: Partial): StarlarkPackagePlanYamlArgs; + + static fromJsonString(jsonString: string, options?: Partial): StarlarkPackagePlanYamlArgs; + + static equals(a: StarlarkPackagePlanYamlArgs | PlainMessage | undefined, b: StarlarkPackagePlanYamlArgs | PlainMessage | undefined): boolean; +} + diff --git a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_pb.js b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_pb.js index dd244aa275..85aa14826f 100644 --- a/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_pb.js +++ b/api/typescript/src/core/kurtosis_core_rpc_api_bindings/connect/api_container_service_pb.js @@ -636,3 +636,38 @@ export const GetStarlarkRunResponse = proto3.makeMessageType( ], ); +/** + * @generated from message api_container_api.PlanYaml + */ +export const PlanYaml = proto3.makeMessageType( + "api_container_api.PlanYaml", + () => [ + { no: 1, name: "plan_yaml", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + ], +); + +/** + * @generated from message api_container_api.StarlarkScriptPlanYamlArgs + */ +export const StarlarkScriptPlanYamlArgs = proto3.makeMessageType( + "api_container_api.StarlarkScriptPlanYamlArgs", + () => [ + { no: 1, name: "serialized_script", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "serialized_params", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 5, name: "main_function_name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + ], +); + +/** + * @generated from message api_container_api.StarlarkPackagePlanYamlArgs + */ +export const StarlarkPackagePlanYamlArgs = proto3.makeMessageType( + "api_container_api.StarlarkPackagePlanYamlArgs", + () => [ + { no: 1, name: "package_id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "serialized_params", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 3, name: "relative_path_to_main_file", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 4, name: "main_function_name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + ], +); + diff --git a/cli/cli/kurtosis_gateway/server/api_container_gateway/api_container_gateway_service_server.go b/cli/cli/kurtosis_gateway/server/api_container_gateway/api_container_gateway_service_server.go index 43f66db3fb..cb334a8504 100644 --- a/cli/cli/kurtosis_gateway/server/api_container_gateway/api_container_gateway_service_server.go +++ b/cli/cli/kurtosis_gateway/server/api_container_gateway/api_container_gateway_service_server.go @@ -230,6 +230,22 @@ func (service *ApiContainerGatewayServiceServer) GetStarlarkRun(ctx context.Cont return remoteApiContainerResponse, nil } +func (service *ApiContainerGatewayServiceServer) GetStarlarkScriptPlanYaml(ctx context.Context, args *kurtosis_core_rpc_api_bindings.StarlarkScriptPlanYamlArgs) (*kurtosis_core_rpc_api_bindings.PlanYaml, error) { + remoteApiContainerResponse, err := service.remoteApiContainerClient.GetStarlarkScriptPlanYaml(ctx, args) + if err != nil { + return nil, stacktrace.Propagate(err, errorCallingRemoteApiContainerFromGateway) + } + return remoteApiContainerResponse, nil +} + +func (service *ApiContainerGatewayServiceServer) GetStarlarkPackagePlanYaml(ctx context.Context, args *kurtosis_core_rpc_api_bindings.StarlarkPackagePlanYamlArgs) (*kurtosis_core_rpc_api_bindings.PlanYaml, error) { + remoteApiContainerResponse, err := service.remoteApiContainerClient.GetStarlarkPackagePlanYaml(ctx, args) + if err != nil { + return nil, stacktrace.Propagate(err, errorCallingRemoteApiContainerFromGateway) + } + return remoteApiContainerResponse, nil +} + // ==================================================================================================== // // Private helper methods diff --git a/core/server/api_container/main.go b/core/server/api_container/main.go index 268b664184..5540699715 100644 --- a/core/server/api_container/main.go +++ b/core/server/api_container/main.go @@ -216,8 +216,9 @@ func runMain() error { } // TODO: Consolidate Interpreter, Validator and Executor into a single interface + startosisInterpreter := startosis_engine.NewStartosisInterpreter(serviceNetwork, gitPackageContentProvider, runtimeValueStore, starlarkValueSerde, serverArgs.EnclaveEnvVars, interpretationTimeValueStore) startosisRunner := startosis_engine.NewStartosisRunner( - startosis_engine.NewStartosisInterpreter(serviceNetwork, gitPackageContentProvider, runtimeValueStore, starlarkValueSerde, serverArgs.EnclaveEnvVars, interpretationTimeValueStore), + startosisInterpreter, startosis_engine.NewStartosisValidator(&kurtosisBackend, serviceNetwork, filesArtifactStore), startosis_engine.NewStartosisExecutor(starlarkValueSerde, runtimeValueStore, enclavePlan, enclaveDb)) @@ -230,6 +231,7 @@ func runMain() error { filesArtifactStore, serviceNetwork, startosisRunner, + startosisInterpreter, gitPackageContentProvider, restartPolicy, metricsClient, diff --git a/core/server/api_container/server/api_container_service.go b/core/server/api_container/server/api_container_service.go index 74d8bb5f2b..d496ee4e66 100644 --- a/core/server/api_container/server/api_container_service.go +++ b/core/server/api_container/server/api_container_service.go @@ -13,6 +13,10 @@ import ( "context" "fmt" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/docker_compose_transpiler" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_structure" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/instructions_plan/resolver" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "io" "math" "net/http" @@ -34,7 +38,6 @@ import ( "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/core/server/api_container/server/service_network" - "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_constants" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_packages" @@ -96,6 +99,8 @@ type ApiContainerService struct { startosisRunner *startosis_engine.StartosisRunner + startosisInterpreter *startosis_engine.StartosisInterpreter + packageContentProvider startosis_packages.PackageContentProvider restartPolicy kurtosis_core_rpc_api_bindings.RestartPolicy @@ -109,6 +114,7 @@ func NewApiContainerService( filesArtifactStore *enclave_data_directory.FilesArtifactStore, serviceNetwork service_network.ServiceNetwork, startosisRunner *startosis_engine.StartosisRunner, + startosisInterpreter *startosis_engine.StartosisInterpreter, startosisModuleContentProvider startosis_packages.PackageContentProvider, restartPolicy kurtosis_core_rpc_api_bindings.RestartPolicy, metricsClient metrics_client.MetricsClient, @@ -117,6 +123,7 @@ func NewApiContainerService( filesArtifactStore: filesArtifactStore, serviceNetwork: serviceNetwork, startosisRunner: startosisRunner, + startosisInterpreter: startosisInterpreter, packageContentProvider: startosisModuleContentProvider, restartPolicy: restartPolicy, starlarkRun: &kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse{ @@ -249,6 +256,12 @@ func (apicService *ApiContainerService) InspectFilesArtifactContents(_ context.C } func (apicService *ApiContainerService) RunStarlarkPackage(args *kurtosis_core_rpc_api_bindings.RunStarlarkPackageArgs, stream kurtosis_core_rpc_api_bindings.ApiContainerService_RunStarlarkPackageServer) error { + + var scriptWithRunFunction string + var interpretationError *startosis_errors.InterpretationError + var isRemote bool + var detectedPackageId string + var detectedPackageReplaceOptions map[string]string packageIdFromArgs := args.GetPackageId() parallelism := int(args.GetParallelism()) if parallelism == 0 { @@ -260,13 +273,7 @@ func (apicService *ApiContainerService) RunStarlarkPackage(args *kurtosis_core_r mainFuncName := args.GetMainFunctionName() ApiDownloadMode := shared_utils.GetOrDefault(args.ImageDownloadMode, defaultImageDownloadMode) downloadMode := convertFromImageDownloadModeAPI(ApiDownloadMode) - nonBlockignMode := args.GetNonBlockingMode() - - var scriptWithRunFunction string - var interpretationError *startosis_errors.InterpretationError - var isRemote bool - var detectedPackageId string - var detectedPackageReplaceOptions map[string]string + nonBlockingMode := args.GetNonBlockingMode() var actualRelativePathToMainFile string if args.ClonePackage != nil { scriptWithRunFunction, actualRelativePathToMainFile, detectedPackageId, detectedPackageReplaceOptions, interpretationError = @@ -293,7 +300,14 @@ func (apicService *ApiContainerService) RunStarlarkPackage(args *kurtosis_core_r if metricsErr != nil { logrus.Warn("An error occurred tracking kurtosis run event") } - apicService.runStarlark(parallelism, dryRun, detectedPackageId, detectedPackageReplaceOptions, mainFuncName, actualRelativePathToMainFile, scriptWithRunFunction, serializedParams, downloadMode, nonBlockignMode, args.ExperimentalFeatures, stream) + + logrus.Infof("package id: %v\n main func name: %v\n actual relative path to main file: %v\n script with run func: %v\n serialized params:%v\n", + detectedPackageId, + mainFuncName, + actualRelativePathToMainFile, + scriptWithRunFunction, + serializedParams) + apicService.runStarlark(parallelism, dryRun, detectedPackageId, detectedPackageReplaceOptions, mainFuncName, actualRelativePathToMainFile, scriptWithRunFunction, serializedParams, downloadMode, nonBlockingMode, args.ExperimentalFeatures, stream) apicService.starlarkRun = &kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse{ PackageId: packageIdFromArgs, @@ -587,6 +601,80 @@ func (apicService *ApiContainerService) GetStarlarkRun(_ context.Context, _ *emp return apicService.starlarkRun, nil } +func (apicService *ApiContainerService) GetStarlarkPackagePlanYaml(ctx context.Context, args *kurtosis_core_rpc_api_bindings.StarlarkPackagePlanYamlArgs) (*kurtosis_core_rpc_api_bindings.PlanYaml, error) { + packageIdFromArgs := args.GetPackageId() + serializedParams := args.GetSerializedParams() + requestedRelativePathToMainFile := args.GetRelativePathToMainFile() + mainFuncName := args.GetMainFunctionName() + + var scriptWithRunFunction string + var interpretationError *startosis_errors.InterpretationError + var detectedPackageId string + var detectedPackageReplaceOptions map[string]string + var actualRelativePathToMainFile string + scriptWithRunFunction, actualRelativePathToMainFile, detectedPackageId, detectedPackageReplaceOptions, interpretationError = + apicService.runStarlarkPackageSetup(packageIdFromArgs, true, nil, requestedRelativePathToMainFile) + if interpretationError != nil { + return nil, stacktrace.Propagate(interpretationError, "An interpretation error occurred setting up the package for retrieving plan yaml for package: %v", packageIdFromArgs) + } + + _, instructionsPlan, apiInterpretationError := apicService.startosisInterpreter.Interpret( + ctx, + detectedPackageId, + mainFuncName, + detectedPackageReplaceOptions, + actualRelativePathToMainFile, + scriptWithRunFunction, + serializedParams, + false, + enclave_structure.NewEnclaveComponents(), + resolver.NewInstructionsPlanMask(0), + image_download_mode.ImageDownloadMode_Always) + if apiInterpretationError != nil { + interpretationError = startosis_errors.NewInterpretationError(apiInterpretationError.GetErrorMessage()) + return nil, stacktrace.Propagate(interpretationError, "An interpretation error occurred interpreting package for retrieving plan yaml for package: %v", packageIdFromArgs) + } + planYamlStr, err := instructionsPlan.GenerateYaml(plan_yaml.CreateEmptyPlan(packageIdFromArgs)) + if err != nil { + return nil, stacktrace.Propagate(err, "An error occurred generating plan yaml for package: %v", packageIdFromArgs) + } + + return &kurtosis_core_rpc_api_bindings.PlanYaml{PlanYaml: planYamlStr}, nil +} + +// NOTE: GetStarlarkScriptPlanYaml endpoint is only meant to be called by the EM UI, Enclave Builder logic. +// Once the EM UI retrieves the plan yaml, the APIC is removed and not used again. +// It's not ideal that we have to even start an enclave/APIC to simply get the result of interpretation/plan yaml but that would require a larger refactor +// of the startosis_engine to enable the infra for interpretation to be executed as a standalone library, that could be setup by the engine, or even on the client. +func (apicService *ApiContainerService) GetStarlarkScriptPlanYaml(ctx context.Context, args *kurtosis_core_rpc_api_bindings.StarlarkScriptPlanYamlArgs) (*kurtosis_core_rpc_api_bindings.PlanYaml, error) { + serializedStarlarkScript := args.GetSerializedScript() + serializedParams := args.GetSerializedParams() + mainFuncName := args.GetMainFunctionName() + noPackageReplaceOptions := map[string]string{} + + _, instructionsPlan, apiInterpretationError := apicService.startosisInterpreter.Interpret( + ctx, + startosis_constants.PackageIdPlaceholderForStandaloneScript, + mainFuncName, + noPackageReplaceOptions, + startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, + serializedStarlarkScript, + serializedParams, + false, + enclave_structure.NewEnclaveComponents(), + resolver.NewInstructionsPlanMask(0), + image_download_mode.ImageDownloadMode_Always) + if apiInterpretationError != nil { + return nil, startosis_errors.NewInterpretationError(apiInterpretationError.GetErrorMessage()) + } + planYamlStr, err := instructionsPlan.GenerateYaml(plan_yaml.CreateEmptyPlan(startosis_constants.PackageIdPlaceholderForStandaloneScript)) + if err != nil { + return nil, err + } + + return &kurtosis_core_rpc_api_bindings.PlanYaml{PlanYaml: planYamlStr}, nil +} + // ==================================================================================================== // // Private helper methods diff --git a/core/server/api_container/server/startosis_engine/instructions_plan/instructions_plan.go b/core/server/api_container/server/startosis_engine/instructions_plan/instructions_plan.go index caabaf9d98..38e42655d4 100644 --- a/core/server/api_container/server/startosis_engine/instructions_plan/instructions_plan.go +++ b/core/server/api_container/server/startosis_engine/instructions_plan/instructions_plan.go @@ -3,6 +3,7 @@ package instructions_plan import ( "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/uuid_generator" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/stacktrace" "go.starlark.net/starlark" @@ -75,6 +76,21 @@ func (plan *InstructionsPlan) GeneratePlan() ([]*ScheduledInstruction, *startosi return generatedPlan, nil } +// GenerateYaml takes in an existing planYaml (usually empty) and returns a yaml string containing the effects of the plan +func (plan *InstructionsPlan) GenerateYaml(planYaml *plan_yaml.PlanYaml) (string, error) { + for _, instructionUuid := range plan.instructionsSequence { + instruction, found := plan.scheduledInstructionsIndex[instructionUuid] + if !found { + return "", startosis_errors.NewInterpretationError("Unexpected error generating the Kurtosis Instructions plan. Instruction with UUID '%s' was scheduled but could not be found in Kurtosis instruction index", instructionUuid) + } + err := instruction.kurtosisInstruction.UpdatePlan(planYaml) + if err != nil { + return "", startosis_errors.WrapWithInterpretationError(err, "An error occurred updating the plan with instruction: %v.", instructionUuid) + } + } + return planYaml.GenerateYaml() +} + func (plan *InstructionsPlan) Size() int { return len(plan.instructionsSequence) } 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 14c8c11d39..7db6f39962 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 @@ -12,7 +12,10 @@ import ( "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/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" + "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" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/service_config" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_packages" @@ -82,9 +85,10 @@ func NewAddService( readyCondition: nil, // populated at interpretation time interpretationTimeValueStore: interpretationTimeValueStore, - description: "", // populated at interpretation time - - imageDownloadMode: imageDownloadMode, + description: "", // populated at interpretation time + returnValue: nil, // populated at interpretation time + imageVal: nil, // populated at interpretation time + imageDownloadMode: imageDownloadMode, } }, @@ -107,10 +111,12 @@ type AddServiceCapabilities struct { packageId string packageContentProvider startosis_packages.PackageContentProvider packageReplaceOptions map[string]string + imageVal starlark.Value interpretationTimeValueStore *interpretation_time_value_store.InterpretationTimeValueStore resultUuid string + returnValue *kurtosis_types.Service description string imageDownloadMode image_download_mode.ImageDownloadMode @@ -126,6 +132,14 @@ func (builtin *AddServiceCapabilities) Interpret(locatorOfModuleInWhichThisBuilt if err != nil { return nil, startosis_errors.WrapWithInterpretationError(err, "Unable to extract value for '%s' argument", ServiceConfigArgName) } + rawImageVal, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.Value](serviceConfig.KurtosisValueTypeDefault, service_config.ImageAttr) + if interpretationErr != nil { + return nil, startosis_errors.WrapWithInterpretationError(err, "Unable to extract raw image attribute.") + } + if !found { + return nil, startosis_errors.NewInterpretationError("Unable to extract image attribute off of service config.") + } + builtin.imageVal = rawImageVal apiServiceConfig, readyCondition, interpretationErr := validateAndConvertConfigAndReadyCondition( builtin.serviceNetwork, serviceConfig, @@ -149,16 +163,16 @@ func (builtin *AddServiceCapabilities) Interpret(locatorOfModuleInWhichThisBuilt builtin.description = builtin_argument.GetDescriptionOrFallBack(arguments, fmt.Sprintf(addServiceDescriptionFormatStr, builtin.serviceName, builtin.serviceConfig.GetContainerImageName())) - returnValue, interpretationErr := makeAddServiceInterpretationReturnValue(serviceName, builtin.serviceConfig, builtin.resultUuid) + builtin.returnValue, interpretationErr = makeAddServiceInterpretationReturnValue(serviceName, builtin.serviceConfig, builtin.resultUuid) if interpretationErr != nil { return nil, interpretationErr } - err = builtin.interpretationTimeValueStore.PutService(builtin.serviceName, returnValue) + err = builtin.interpretationTimeValueStore.PutService(builtin.serviceName, builtin.returnValue) if err != nil { return nil, startosis_errors.WrapWithInterpretationError(err, "An error occurred while persisting return value for service '%v'", serviceName) } - return returnValue, nil + return builtin.returnValue, nil } func (builtin *AddServiceCapabilities) Validate(_ *builtin_argument.ArgumentValuesSet, validatorEnvironment *startosis_validator.ValidatorEnvironment) *startosis_errors.ValidationError { @@ -255,6 +269,41 @@ func (builtin *AddServiceCapabilities) FillPersistableAttributes(builder *enclav ) } +func (builtin *AddServiceCapabilities) UpdatePlan(planYaml *plan_yaml.PlanYaml) error { + var buildContextLocator string + var targetStage string + var registryAddress string + var interpretationErr *startosis_errors.InterpretationError + + // set image values based on type of image + if builtin.imageVal != nil { + switch starlarkImgVal := builtin.imageVal.(type) { + case *service_config.ImageBuildSpec: + buildContextLocator, interpretationErr = starlarkImgVal.GetBuildContextLocator() + if interpretationErr != nil { + return startosis_errors.WrapWithInterpretationError(interpretationErr, "An error occurred getting build context locator") + } + targetStage, interpretationErr = starlarkImgVal.GetTargetStage() + if interpretationErr != nil { + return startosis_errors.WrapWithInterpretationError(interpretationErr, "An error occurred getting target stage.") + } + case *service_config.ImageSpec: + registryAddress, interpretationErr = starlarkImgVal.GetRegistryAddrIfSet() + if interpretationErr != nil { + return startosis_errors.WrapWithInterpretationError(interpretationErr, "An error occurred getting registry address.") + } + default: + // assume NixBuildSpec or regular image + } + } + + err := planYaml.AddService(builtin.serviceName, builtin.returnValue, builtin.serviceConfig, buildContextLocator, targetStage, registryAddress) + if err != nil { + return stacktrace.NewError("An error occurred updating the plan with service: %v", builtin.serviceName) + } + return nil +} + func (builtin *AddServiceCapabilities) Description() string { return builtin.description } 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 1fa9f3a4b1..c221488f85 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 @@ -13,6 +13,7 @@ import ( "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/service_config" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_constants" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" @@ -369,6 +370,12 @@ func (builtin *AddServicesCapabilities) allServicesReadinessCheck( return failedServiceChecksRegularMap } +func (builtin *AddServicesCapabilities) UpdatePlan(plan *plan_yaml.PlanYaml) error { + // TOOD: Implement + logrus.Warn("ADD SERVICES NOT IMPLEMENTED YET FOR UPDATING PLAN YAML.") + return nil +} + func (builtin *AddServicesCapabilities) Description() string { return builtin.description } 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 0795e5fbf2..4959d1162e 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 @@ -7,10 +7,13 @@ import ( "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_plan_persistence" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_structure" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/tasks" "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/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" + "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" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/recipe" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" @@ -77,12 +80,14 @@ func NewExec(serviceNetwork service_network.ServiceNetwork, runtimeValueStore *r serviceNetwork: serviceNetwork, runtimeValueStore: runtimeValueStore, - serviceName: "", // will be populated at interpretation time - execRecipe: nil, // will be populated at interpretation time - resultUuid: "", // will be populated at interpretation time - acceptableCodes: nil, // will be populated at interpretation time - skipCodeCheck: false, // will be populated at interpretation time - description: "", // populated at interpretation time + serviceName: "", // will be populated at interpretation time + execRecipe: nil, // will be populated at interpretation time + resultUuid: "", // will be populated at interpretation time + acceptableCodes: nil, // will be populated at interpretation time + skipCodeCheck: false, // will be populated at interpretation time + description: "", // populated at interpretation time + cmdList: []string{}, // populated at interpretation time + returnValue: nil, // populated at interpretation time } }, @@ -99,10 +104,13 @@ type ExecCapabilities struct { serviceName service.ServiceName execRecipe *recipe.ExecRecipe + cmdList []string resultUuid string acceptableCodes []int64 skipCodeCheck bool description string + + returnValue *starlark.Dict } func (builtin *ExecCapabilities) Interpret(_ string, arguments *builtin_argument.ArgumentValuesSet) (starlark.Value, *startosis_errors.InterpretationError) { @@ -117,6 +125,17 @@ func (builtin *ExecCapabilities) Interpret(_ string, arguments *builtin_argument if err != nil { return nil, startosis_errors.WrapWithInterpretationError(err, "Unable to extract value for '%s' argument", RecipeArgName) } + starlarkCmdList, ok, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[*starlark.List](execRecipe.KurtosisValueTypeDefault, recipe.CommandAttr) + if interpretationErr != nil { + return nil, interpretationErr + } + if !ok { + return nil, startosis_errors.NewInterpretationError("Unable to extract attribute %v off of exec recipe.", recipe.CommandAttr) + } + cmdList, interpretationErr := kurtosis_types.SafeCastToStringSlice(starlarkCmdList, tasks.PythonArgumentsArgName) + if interpretationErr != nil { + return nil, startosis_errors.WrapWithInterpretationError(err, "An error occurred converting Starlark list of passed arguments to Go string slice") + } acceptableCodes := defaultAcceptableCodes if arguments.IsSet(AcceptableCodesArgName) { @@ -146,17 +165,18 @@ func (builtin *ExecCapabilities) Interpret(_ string, arguments *builtin_argument builtin.serviceName = serviceName builtin.execRecipe = execRecipe + builtin.cmdList = cmdList builtin.resultUuid = resultUuid builtin.acceptableCodes = acceptableCodes builtin.skipCodeCheck = skipCodeCheck builtin.description = builtin_argument.GetDescriptionOrFallBack(arguments, fmt.Sprintf(descriptionFormatStr, builtin.serviceName)) - returnValue, interpretationErr := builtin.execRecipe.CreateStarlarkReturnValue(builtin.resultUuid) + builtin.returnValue, interpretationErr = builtin.execRecipe.CreateStarlarkReturnValue(builtin.resultUuid) if interpretationErr != nil { return nil, startosis_errors.WrapWithInterpretationError(err, "An error occurred while generating return value for %v instruction", ExecBuiltinName) } - return returnValue, nil + return builtin.returnValue, nil } func (builtin *ExecCapabilities) Validate(_ *builtin_argument.ArgumentValuesSet, _ *startosis_validator.ValidatorEnvironment) *startosis_errors.ValidationError { @@ -194,6 +214,14 @@ func (builtin *ExecCapabilities) FillPersistableAttributes(builder *enclave_plan builder.SetType(ExecBuiltinName) } +func (builtin *ExecCapabilities) UpdatePlan(planYaml *plan_yaml.PlanYaml) error { + err := planYaml.AddExec(string(builtin.serviceName), builtin.returnValue, builtin.cmdList, builtin.acceptableCodes) + if err != nil { + return stacktrace.Propagate(err, "An error occurred updating plan with exec.") + } + return nil +} + func (builtin *ExecCapabilities) Description() string { return builtin.description } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/get_service/get_service.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/get_service/get_service.go index e0fbd26613..17b5aa7a2a 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/get_service/get_service.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/get_service/get_service.go @@ -10,6 +10,7 @@ import ( "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/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" "go.starlark.net/starlark" @@ -102,6 +103,11 @@ func (builtin *GetServiceCapabilities) FillPersistableAttributes(builder *enclav builder.SetType(GetServiceBuiltinName).AddServiceName(builtin.serviceName) } +func (builtin *GetServiceCapabilities) UpdatePlan(planYaml *plan_yaml.PlanYaml) error { + // get service does not affect the plan + return nil +} + func (builtin *GetServiceCapabilities) Description() string { return builtin.description } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/kurtosis_instruction.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/kurtosis_instruction.go index 89d809662b..97c2fd1749 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/kurtosis_instruction.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/kurtosis_instruction.go @@ -6,6 +6,7 @@ import ( "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_plan_persistence" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_structure" "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/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" ) @@ -33,4 +34,7 @@ type KurtosisInstruction interface { // It returns a builder and not the built object b/c the caller of this method might want to set some attributes // itself. In the current case, this is called in the executor, and it sets the UUID and the returned value. GetPersistableAttributes() *enclave_plan_persistence.EnclavePlanInstructionBuilder + + // UpdatePlan updates the plan with the effects of running this instruction. + UpdatePlan(plan *plan_yaml.PlanYaml) error } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/kurtosis_print/kurtosis_print.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/kurtosis_print/kurtosis_print.go index 88c33b4921..c111b0a098 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/kurtosis_print/kurtosis_print.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/kurtosis_print/kurtosis_print.go @@ -9,6 +9,7 @@ import ( "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/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" @@ -105,6 +106,11 @@ func (builtin *PrintCapabilities) FillPersistableAttributes(builder *enclave_pla builder.SetType(PrintBuiltinName) } +func (builitin *PrintCapabilities) UpdatePlan(plan *plan_yaml.PlanYaml) error { + // print does not affect the plan + return nil +} + func (builtin *PrintCapabilities) Description() string { return builtin.description } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/mock_instruction/mock_kurtosis_instruction.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/mock_instruction/mock_kurtosis_instruction.go index 5801836154..6d22f66a9c 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/mock_instruction/mock_kurtosis_instruction.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/mock_instruction/mock_kurtosis_instruction.go @@ -1,11 +1,14 @@ -// Code generated by mockery v2.22.1. DO NOT EDIT. +// Code generated by mockery v2.23.1. DO NOT EDIT. package mock_instruction import ( context "context" + builtin_argument "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument" + enclave_plan_persistence "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_plan_persistence" + enclave_structure "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_structure" kurtosis_core_rpc_api_bindings "github.com/kurtosis-tech/kurtosis/api/golang/core/kurtosis_core_rpc_api_bindings" @@ -14,6 +17,8 @@ import ( mock "github.com/stretchr/testify/mock" + plan_yaml "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" + startosis_validator "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" ) @@ -84,6 +89,49 @@ func (_c *MockKurtosisInstruction_Execute_Call) RunAndReturn(run func(context.Co return _c } +// GetArguments provides a mock function with given fields: +func (_m *MockKurtosisInstruction) GetArguments() *builtin_argument.ArgumentValuesSet { + ret := _m.Called() + + var r0 *builtin_argument.ArgumentValuesSet + if rf, ok := ret.Get(0).(func() *builtin_argument.ArgumentValuesSet); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*builtin_argument.ArgumentValuesSet) + } + } + + return r0 +} + +// MockKurtosisInstruction_GetArguments_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetArguments' +type MockKurtosisInstruction_GetArguments_Call struct { + *mock.Call +} + +// GetArguments is a helper method to define mock.On call +func (_e *MockKurtosisInstruction_Expecter) GetArguments() *MockKurtosisInstruction_GetArguments_Call { + return &MockKurtosisInstruction_GetArguments_Call{Call: _e.mock.On("GetArguments")} +} + +func (_c *MockKurtosisInstruction_GetArguments_Call) Run(run func()) *MockKurtosisInstruction_GetArguments_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *MockKurtosisInstruction_GetArguments_Call) Return(_a0 *builtin_argument.ArgumentValuesSet) *MockKurtosisInstruction_GetArguments_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockKurtosisInstruction_GetArguments_Call) RunAndReturn(run func() *builtin_argument.ArgumentValuesSet) *MockKurtosisInstruction_GetArguments_Call { + _c.Call.Return(run) + return _c +} + // GetCanonicalInstruction provides a mock function with given fields: isSkipped func (_m *MockKurtosisInstruction) GetCanonicalInstruction(isSkipped bool) *kurtosis_core_rpc_api_bindings.StarlarkInstruction { ret := _m.Called(isSkipped) @@ -298,6 +346,48 @@ func (_c *MockKurtosisInstruction_TryResolveWith_Call) RunAndReturn(run func(*en return _c } +// UpdatePlan provides a mock function with given fields: plan +func (_m *MockKurtosisInstruction) UpdatePlan(plan *plan_yaml.PlanYaml) error { + ret := _m.Called(plan) + + var r0 error + if rf, ok := ret.Get(0).(func(*plan_yaml.PlanYaml) error); ok { + r0 = rf(plan) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MockKurtosisInstruction_UpdatePlan_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdatePlan' +type MockKurtosisInstruction_UpdatePlan_Call struct { + *mock.Call +} + +// UpdatePlan is a helper method to define mock.On call +// - plan *plan_yaml.PlanYaml +func (_e *MockKurtosisInstruction_Expecter) UpdatePlan(plan interface{}) *MockKurtosisInstruction_UpdatePlan_Call { + return &MockKurtosisInstruction_UpdatePlan_Call{Call: _e.mock.On("UpdatePlan", plan)} +} + +func (_c *MockKurtosisInstruction_UpdatePlan_Call) Run(run func(plan *plan_yaml.PlanYaml)) *MockKurtosisInstruction_UpdatePlan_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*plan_yaml.PlanYaml)) + }) + return _c +} + +func (_c *MockKurtosisInstruction_UpdatePlan_Call) Return(_a0 error) *MockKurtosisInstruction_UpdatePlan_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockKurtosisInstruction_UpdatePlan_Call) RunAndReturn(run func(*plan_yaml.PlanYaml) error) *MockKurtosisInstruction_UpdatePlan_Call { + _c.Call.Return(run) + return _c +} + // ValidateAndUpdateEnvironment provides a mock function with given fields: environment func (_m *MockKurtosisInstruction) ValidateAndUpdateEnvironment(environment *startosis_validator.ValidatorEnvironment) error { ret := _m.Called(environment) diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/remove_service/remove_service.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/remove_service/remove_service.go index 89f9706fe1..e7dc571fda 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/remove_service/remove_service.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/remove_service/remove_service.go @@ -10,6 +10,7 @@ import ( "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/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" "github.com/kurtosis-tech/stacktrace" @@ -106,6 +107,11 @@ func (builtin *RemoveServiceCapabilities) FillPersistableAttributes(builder *enc ) } +func (builtin *RemoveServiceCapabilities) UpdatePlan(plan *plan_yaml.PlanYaml) error { + plan.RemoveService(string(builtin.serviceName)) + return nil +} + func (builtin *RemoveServiceCapabilities) Description() string { return builtin.description } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/render_templates/render_templates.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/render_templates/render_templates.go index f25fdb7778..40e92fbf56 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/render_templates/render_templates.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/render_templates/render_templates.go @@ -12,6 +12,7 @@ import ( "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" @@ -173,6 +174,18 @@ func (builtin *RenderTemplatesCapabilities) FillPersistableAttributes(builder *e ) } +func (builtin *RenderTemplatesCapabilities) UpdatePlan(plan *plan_yaml.PlanYaml) error { + filepaths := []string{} + for filepath := range builtin.templatesAndDataByDestRelFilepath { + filepaths = append(filepaths, filepath) + } + err := plan.AddRenderTemplates(builtin.artifactName, filepaths) + if err != nil { + return stacktrace.Propagate(err, "An error occurred updating plan with render template instruction.") + } + return nil +} + func (builtin *RenderTemplatesCapabilities) Description() string { return builtin.description } 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 b4d9994fee..2a893d2672 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 @@ -11,11 +11,13 @@ import ( "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/recipe" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" "github.com/kurtosis-tech/stacktrace" + "github.com/sirupsen/logrus" "go.starlark.net/starlark" "net/http" ) @@ -207,6 +209,12 @@ func (builtin *RequestCapabilities) FillPersistableAttributes(builder *enclave_p builder.SetType(RequestBuiltinName) } +func (builtin *RequestCapabilities) UpdatePlan(plan *plan_yaml.PlanYaml) error { + // TODO: Implement + logrus.Warn("REQUEST NOT IMPLEMENTED YET FOR UPDATING PLAN") + return nil +} + func (builtin *RequestCapabilities) Description() string { return builtin.description } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/start_service/start_service.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/start_service/start_service.go index 63e20730d0..2856274444 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/start_service/start_service.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/start_service/start_service.go @@ -10,6 +10,7 @@ import ( "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/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" "github.com/kurtosis-tech/stacktrace" @@ -106,6 +107,11 @@ func (builtin *StartServiceCapabilities) FillPersistableAttributes(builder *encl ) } +func (builtin *StartServiceCapabilities) UpdatePlan(plan *plan_yaml.PlanYaml) error { + // start services doesn't affect the plan + return nil +} + func (builtin *StartServiceCapabilities) Description() string { return builtin.description } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/stop_service/stop_service.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/stop_service/stop_service.go index e046816ea9..82fc1a86c7 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/stop_service/stop_service.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/stop_service/stop_service.go @@ -10,6 +10,7 @@ import ( "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/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" "github.com/kurtosis-tech/stacktrace" @@ -106,6 +107,11 @@ func (builtin *StopServiceCapabilities) FillPersistableAttributes(builder *encla ) } +func (builtin *StopServiceCapabilities) UpdatePlan(plan *plan_yaml.PlanYaml) error { + // stop service does not affect the plan + return nil +} + func (builtin *StopServiceCapabilities) Description() string { return builtin.description } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/store_service_files/store_service_files.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/store_service_files/store_service_files.go index 8896c4a650..ab17ad1b5b 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/store_service_files/store_service_files.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/store_service_files/store_service_files.go @@ -10,6 +10,7 @@ import ( "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/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" "github.com/kurtosis-tech/stacktrace" @@ -179,6 +180,14 @@ func (builtin *StoreServiceFilesCapabilities) FillPersistableAttributes(builder ) } +func (builtin *StoreServiceFilesCapabilities) UpdatePlan(plan *plan_yaml.PlanYaml) error { + err := plan.AddStoreServiceFiles(builtin.artifactName, builtin.src) + if err != nil { + return stacktrace.Propagate(err, "An error occurred updating plan with store service files") + } + return nil +} + func (builtin *StoreServiceFilesCapabilities) Description() string { return builtin.description } 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 246378bd38..2971f953fa 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 @@ -16,12 +16,14 @@ import ( "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/service_config" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" "github.com/kurtosis-tech/stacktrace" "github.com/xtgo/uuid" "go.starlark.net/starlark" + "go.starlark.net/starlarkstruct" "strings" ) @@ -108,7 +110,8 @@ func NewRunPythonService(serviceNetwork service_network.ServiceNetwork, runtimeV resultUuid: "", // populated at interpretation time storeSpecList: nil, wait: DefaultWaitTimeoutDurationStr, - description: "", // populated at interpretation time + description: "", // populated at interpretation time + returnValue: nil, // populated at interpretation time } }, @@ -136,6 +139,7 @@ type RunPythonCapabilities struct { pythonArguments []string packages []string + returnValue *starlarkstruct.Struct serviceConfig *service.ServiceConfig storeSpecList []*store_spec.StoreSpec wait string @@ -244,8 +248,8 @@ func (builtin *RunPythonCapabilities) Interpret(_ string, arguments *builtin_arg builtin.description = builtin_argument.GetDescriptionOrFallBack(arguments, runPythonDefaultDescription) - result := createInterpretationResult(resultUuid, builtin.storeSpecList) - return result, nil + builtin.returnValue = createInterpretationResult(resultUuid, builtin.storeSpecList) + return builtin.returnValue, nil } func (builtin *RunPythonCapabilities) Validate(_ *builtin_argument.ArgumentValuesSet, validatorEnvironment *startosis_validator.ValidatorEnvironment) *startosis_errors.ValidationError { @@ -333,6 +337,14 @@ func (builtin *RunPythonCapabilities) FillPersistableAttributes(builder *enclave builder.SetType(RunPythonBuiltinName) } +func (builtin *RunPythonCapabilities) UpdatePlan(plan *plan_yaml.PlanYaml) error { + err := plan.AddRunPython(builtin.run, builtin.returnValue, builtin.serviceConfig, builtin.storeSpecList, builtin.pythonArguments, builtin.packages) + if err != nil { + return stacktrace.Propagate(err, "An error occurred updating plan with run python") + } + return nil +} + func (builtin *RunPythonCapabilities) Description() string { return builtin.description } 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 e4d5f21eaa..451b12cf1a 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 @@ -15,12 +15,14 @@ import ( "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/service_config" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" "github.com/kurtosis-tech/stacktrace" "github.com/xtgo/uuid" "go.starlark.net/starlark" + "go.starlark.net/starlarkstruct" ) const ( @@ -90,7 +92,8 @@ func NewRunShService(serviceNetwork service_network.ServiceNetwork, runtimeValue resultUuid: "", // populated at interpretation time storeSpecList: nil, wait: DefaultWaitTimeoutDurationStr, - description: "", // populated at interpretation time + description: "", // populated at interpretation time + returnValue: nil, // populated at interpretation time } }, @@ -116,6 +119,7 @@ type RunShCapabilities struct { serviceConfig *service.ServiceConfig storeSpecList []*store_spec.StoreSpec + returnValue *starlarkstruct.Struct wait string description string } @@ -201,8 +205,8 @@ func (builtin *RunShCapabilities) Interpret(_ string, arguments *builtin_argumen } builtin.description = builtin_argument.GetDescriptionOrFallBack(arguments, defaultDescription) - result := createInterpretationResult(resultUuid, builtin.storeSpecList) - return result, nil + builtin.returnValue = createInterpretationResult(resultUuid, builtin.storeSpecList) + return builtin.returnValue, nil } func (builtin *RunShCapabilities) Validate(_ *builtin_argument.ArgumentValuesSet, validatorEnvironment *startosis_validator.ValidatorEnvironment) *startosis_errors.ValidationError { @@ -288,6 +292,14 @@ func (builtin *RunShCapabilities) FillPersistableAttributes(builder *enclave_pla builder.SetType(RunShBuiltinName) } +func (builtin *RunShCapabilities) UpdatePlan(plan *plan_yaml.PlanYaml) error { + err := plan.AddRunSh(builtin.run, builtin.returnValue, builtin.serviceConfig, builtin.storeSpecList) + if err != nil { + return stacktrace.Propagate(err, "An error occurred adding run sh task to the plan") + } + return nil +} + func (builtin *RunShCapabilities) Description() string { return builtin.description } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/upload_files/upload_files.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/upload_files/upload_files.go index 3425a77ba3..b1b02397fc 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/upload_files/upload_files.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/upload_files/upload_files.go @@ -10,6 +10,7 @@ import ( "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/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_packages" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" @@ -218,6 +219,14 @@ func (builtin *UploadFilesCapabilities) FillPersistableAttributes(builder *encla ) } +func (builtin *UploadFilesCapabilities) UpdatePlan(plan *plan_yaml.PlanYaml) error { + err := plan.AddUploadFiles(builtin.artifactName, builtin.src) + if err != nil { + return stacktrace.Propagate(err, "An error occurred updating plan with upload files.") + } + return nil +} + func (builtin *UploadFilesCapabilities) Description() string { return builtin.description } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/verify/verify.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/verify/verify.go index 36f51c7a83..842f5d0ddf 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/verify/verify.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/verify/verify.go @@ -9,6 +9,7 @@ import ( "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/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" @@ -160,6 +161,11 @@ func (builtin *VerifyCapabilities) FillPersistableAttributes(builder *enclave_pl builder.SetType(VerifyBuiltinName) } +func (builtin *VerifyCapabilities) UpdatePlan(plan *plan_yaml.PlanYaml) error { + // verify does not affect the plan + return nil +} + func (builtin *VerifyCapabilities) Description() string { return builtin.description } 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 7cce2e4a83..ee89af066e 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 @@ -12,6 +12,7 @@ import ( "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/kurtosis_starlark_framework/builtin_argument" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/recipe" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" @@ -293,6 +294,11 @@ func (builtin *WaitCapabilities) FillPersistableAttributes(builder *enclave_plan builder.SetType(WaitBuiltinName) } +func (builtin *WaitCapabilities) UpdatePlan(plan *plan_yaml.PlanYaml) error { + // wait does not affect the plan + return nil +} + func (builtin *WaitCapabilities) Description() string { return builtin.description } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction/kurtosis_plan_instruction_capabilities.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction/kurtosis_plan_instruction_capabilities.go index 66ca407c64..5037f15fad 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction/kurtosis_plan_instruction_capabilities.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction/kurtosis_plan_instruction_capabilities.go @@ -5,6 +5,7 @@ import ( "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_plan_persistence" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_structure" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" "go.starlark.net/starlark" @@ -25,4 +26,7 @@ type KurtosisPlanInstructionCapabilities interface { // Description Brief description of the instruction based on its contents Description() string + + // UpdatePlan applies the effect of this instruction capabilities onto the yaml representation of the instruction plan. + UpdatePlan(plan *plan_yaml.PlanYaml) error } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction/kurtosis_plan_instruction_internal.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction/kurtosis_plan_instruction_internal.go index e05a718083..968181cb55 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction/kurtosis_plan_instruction_internal.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction/kurtosis_plan_instruction_internal.go @@ -8,6 +8,7 @@ import ( "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/enclave_structure" "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/kurtosis_starlark_framework/builtin_argument" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/plan_yaml" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_validator" "go.starlark.net/starlark" @@ -97,6 +98,10 @@ func (builtin *kurtosisPlanInstructionInternal) GetPersistableAttributes() *encl return enclavePlaneInstructionBuilder.SetStarlarkCode(builtin.String()) } +func (builtin *kurtosisPlanInstructionInternal) UpdatePlan(plan *plan_yaml.PlanYaml) error { + return builtin.capabilities.UpdatePlan(plan) +} + func (builtin *kurtosisPlanInstructionInternal) interpret() (starlark.Value, *startosis_errors.InterpretationError) { result, interpretationErr := builtin.capabilities.Interpret(builtin.GetPosition().GetFilename(), builtin.GetArguments()) if interpretationErr != nil { diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/service_config.go b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/service_config.go index 9eefb07312..aff2818ff5 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/service_config.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/service_config.go @@ -265,6 +265,7 @@ func (config *ServiceConfig) ToKurtosisType( if !found { return nil, startosis_errors.NewInterpretationError("Required attribute '%s' could not be found on type '%s'", ImageAttr, ServiceConfigTypeName) } + // TODO: refactor image build spec into a common interface imageName, maybeImageBuildSpec, maybeImageRegistrySpec, maybeNixBuildSpec, interpretationErr = convertImage( rawImageAttrValue, locatorOfModuleInWhichThisBuiltInIsBeingCalled, @@ -681,32 +682,30 @@ func convertImage( packageId string, packageContentProvider startosis_packages.PackageContentProvider, packageReplaceOptions map[string]string) (string, *image_build_spec.ImageBuildSpec, *image_registry_spec.ImageRegistrySpec, *nix_build_spec.NixBuildSpec, *startosis_errors.InterpretationError) { - imageBuildSpecStarlarkType, isImageBuildSpecStarlarkType := image.(*ImageBuildSpec) - imageSpecStarlarkType, isImageRegistrySpecStarlarkType := image.(*ImageSpec) - nixBuildSpecStarlarkType, isNixBuildSpecStarlarkType := image.(*NixBuildSpec) - if isImageBuildSpecStarlarkType { - imageBuildSpec, interpretationErr := imageBuildSpecStarlarkType.ToKurtosisType(locatorOfModuleInWhichThisBuiltInIsBeingCalled, packageId, packageContentProvider, packageReplaceOptions) + switch image := image.(type) { + case *ImageBuildSpec: + imageBuildSpec, interpretationErr := image.ToKurtosisType(locatorOfModuleInWhichThisBuiltInIsBeingCalled, packageId, packageContentProvider, packageReplaceOptions) if interpretationErr != nil { return "", nil, nil, nil, interpretationErr } - imageName, interpretationErr := imageBuildSpecStarlarkType.GetImageName() + imageName, interpretationErr := image.GetImageName() if interpretationErr != nil { return "", nil, nil, nil, interpretationErr } return imageName, imageBuildSpec, nil, nil, nil - } else if isImageRegistrySpecStarlarkType { - imageRegistrySpec, interpretationErr := imageSpecStarlarkType.ToKurtosisType() + case *ImageSpec: + imageRegistrySpec, interpretationErr := image.ToKurtosisType() if interpretationErr != nil { return "", nil, nil, nil, interpretationErr } return imageRegistrySpec.GetImageName(), nil, imageRegistrySpec, nil, nil - } else if isNixBuildSpecStarlarkType { - nixBuildSpec, interpretationErr := nixBuildSpecStarlarkType.ToKurtosisType(locatorOfModuleInWhichThisBuiltInIsBeingCalled, packageId, packageContentProvider, packageReplaceOptions) + case *NixBuildSpec: + nixBuildSpec, interpretationErr := image.ToKurtosisType(locatorOfModuleInWhichThisBuiltInIsBeingCalled, packageId, packageContentProvider, packageReplaceOptions) if interpretationErr != nil { return "", nil, nil, nil, interpretationErr } return nixBuildSpec.GetImageName(), nil, nil, nixBuildSpec, nil - } else { + default: imageName, interpretationErr := kurtosis_types.SafeCastToString(image, ImageAttr) if interpretationErr != nil { return "", nil, nil, nil, interpretationErr diff --git a/core/server/api_container/server/startosis_engine/plan_yaml/plan_yaml.go b/core/server/api_container/server/startosis_engine/plan_yaml/plan_yaml.go new file mode 100644 index 0000000000..2ea9bcfd03 --- /dev/null +++ b/core/server/api_container/server/startosis_engine/plan_yaml/plan_yaml.go @@ -0,0 +1,112 @@ +package plan_yaml + +import "sort" + +const ( + shell TaskType = "sh" + python TaskType = "python" + exec TaskType = "exec" +) + +type privatePlanYaml struct { + PackageId string `yaml:"packageId,omitempty"` + Services []*Service `yaml:"services,omitempty"` + FilesArtifacts []*FilesArtifact `yaml:"filesArtifacts,omitempty"` + Tasks []*Task `yaml:"tasks,omitempty"` +} + +// Service represents a service in the system. +type Service struct { + Uuid string `yaml:"uuid,omitempty"` + Name string `yaml:"name,omitempty"` + Image *ImageSpec `yaml:"image,omitempty"` + Cmd []string `yaml:"command,omitempty"` + Entrypoint []string `yaml:"entrypoint,omitempty"` + EnvVars []*EnvironmentVariable `yaml:"envVars,omitempty"` + Ports []*Port `yaml:"ports,omitempty"` + Files []*FileMount `yaml:"files,omitempty"` +} + +func (s *Service) MarshalYAML() (interface{}, error) { + sort.Slice(s.EnvVars, func(i, j int) bool { + return s.EnvVars[i].Key < s.EnvVars[j].Key + }) + return s, nil +} + +type ImageSpec struct { + ImageName string `yaml:"name,omitempty"` + + // for built images + BuildContextLocator string `yaml:"buildContextLocator,omitempty"` + TargetStage string `yaml:"targetStage,omitempty"` + + // for images from registry + Registry string `yaml:"registry,omitempty"` +} + +// FilesArtifact represents a collection of files. +type FilesArtifact struct { + Uuid string `yaml:"uuid,omitempty"` + Name string `yaml:"name,omitempty"` + Files []string `yaml:"files,omitempty"` +} + +func (f *FilesArtifact) MarshalYAML() (interface{}, error) { + sort.Slice(f.Files, func(i, j int) bool { + return f.Files[i] < f.Files[j] + }) + return f, nil +} + +// EnvironmentVariable represents an environment variable. +type EnvironmentVariable struct { + Key string `yaml:"key,omitempty"` + Value string `yaml:"value,omitempty"` +} + +// Port represents a port. +type Port struct { + Name string `yaml:"name,omitempty"` + Number uint16 `yaml:"number,omitempty"` + + TransportProtocol TransportProtocol `yaml:"transportProtocol,omitempty"` + ApplicationProtocol ApplicationProtocol `yaml:"applicationProtocol,omitempty"` +} + +// ApplicationProtocol represents the application protocol used. +type ApplicationProtocol string + +// TransportProtocol represents transport protocol used. +type TransportProtocol string + +// FileMount represents a mount point for files. +type FileMount struct { + MountPath string `yaml:"mountPath,omitempty"` + FilesArtifacts []*FilesArtifact `yaml:"filesArtifacts,omitempty"` // TODO: support persistent directories +} + +// Task represents a task to be executed. +type Task struct { + Uuid string `yaml:"uuid,omitempty"` // done + Name string `yaml:"name,omitempty"` // done + TaskType TaskType `yaml:"taskType,omitempty"` // done + RunCmd []string `yaml:"command,omitempty"` // done + Image string `yaml:"image,omitempty"` // done + Files []*FileMount `yaml:"files,omitempty"` + Store []*FilesArtifact `yaml:"store,omitempty"` + + // only exists on shell tasks + EnvVars []*EnvironmentVariable `yaml:"envVar,omitempty"` // done + + // only exists on python tasks + PythonPackages []string `yaml:"pythonPackages,omitempty"` + PythonArgs []string `yaml:"pythonArgs,omitempty"` + + // service name + ServiceName string `yaml:"serviceName,omitempty"` + AcceptableCodes []int64 `yaml:"acceptableCodes,omitempty"` +} + +// TaskType represents the type of task (either python or shell) +type TaskType string diff --git a/core/server/api_container/server/startosis_engine/plan_yaml/plan_yaml_generator.go b/core/server/api_container/server/startosis_engine/plan_yaml/plan_yaml_generator.go new file mode 100644 index 0000000000..01b544dec5 --- /dev/null +++ b/core/server/api_container/server/startosis_engine/plan_yaml/plan_yaml_generator.go @@ -0,0 +1,447 @@ +package plan_yaml + +import ( + "fmt" + "github.com/go-yaml/yaml" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service" + "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service_directory" + store_spec2 "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/store_spec" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types" + "github.com/kurtosis-tech/stacktrace" + "go.starlark.net/starlark" + "go.starlark.net/starlarkstruct" + "golang.org/x/exp/slices" + "strconv" + "strings" +) + +const ( + ipAddressFutureRefType = "ip_address" + codeFutureRefType = "code" + hostnameFutureRefType = "hostname" + outputFutureRefType = "output" +) + +// PlanYaml is a yaml representation of the effect of an Instructions Plan or sequence of instructions on the state of the Enclave. +type PlanYaml struct { + privatePlanYaml *privatePlanYaml + + futureReferenceIndex map[string]string + filesArtifactIndex map[string]*FilesArtifact + latestUuid int +} + +func CreateEmptyPlan(packageId string) *PlanYaml { + return &PlanYaml{ + privatePlanYaml: &privatePlanYaml{ + PackageId: packageId, + Services: []*Service{}, + Tasks: []*Task{}, + FilesArtifacts: []*FilesArtifact{}, + }, + futureReferenceIndex: map[string]string{}, + filesArtifactIndex: map[string]*FilesArtifact{}, + latestUuid: 0, + } +} + +func (planYaml *PlanYaml) GenerateYaml() (string, error) { + yamlBytes, err := yaml.Marshal(planYaml.privatePlanYaml) + if err != nil { + return "", stacktrace.Propagate(err, "An error occurred generating plan yaml.") + } + return string(yamlBytes), nil +} + +func (planYaml *PlanYaml) AddService( + serviceName service.ServiceName, + serviceInfo *kurtosis_types.Service, + serviceConfig *service.ServiceConfig, + // image values might be empty depending on how the image is buitl + imageBuildContextLocator string, + imageTargetStage string, + imageRegistryAddress string, +) error { + uuid := planYaml.generateUuid() + + // store future references of this service + ipAddrFutureRef, err := serviceInfo.GetIpAddress() + if err != nil { + return err + } + hostnameFutureRef, err := serviceInfo.GetHostname() + if err != nil { + return err + } + planYaml.storeFutureReference(uuid, ipAddrFutureRef, ipAddressFutureRefType) + planYaml.storeFutureReference(uuid, hostnameFutureRef, hostnameFutureRefType) + + // construct service yaml object for plan + serviceYaml := &Service{} //nolint exhaustruct + serviceYaml.Uuid = uuid + + serviceYaml.Name = planYaml.swapFutureReference(string(serviceName)) + + imageYaml := &ImageSpec{} //nolint:exhaustruct + imageYaml.ImageName = serviceConfig.GetContainerImageName() + imageYaml.BuildContextLocator = imageBuildContextLocator + imageYaml.TargetStage = imageTargetStage + imageYaml.Registry = imageRegistryAddress + serviceYaml.Image = imageYaml + + cmdArgs := []string{} + for _, cmdArg := range serviceConfig.GetCmdArgs() { + cmdArgs = append(cmdArgs, planYaml.swapFutureReference(cmdArg)) + } + serviceYaml.Cmd = cmdArgs + + entryArgs := []string{} + for _, entryArg := range serviceConfig.GetEntrypointArgs() { + entryArgs = append(entryArgs, planYaml.swapFutureReference(entryArg)) + } + serviceYaml.Entrypoint = entryArgs + + serviceYaml.Ports = []*Port{} + for portName, configPort := range serviceConfig.GetPrivatePorts() { // TODO: support public ports + var applicationProtocolStr string + if configPort.GetMaybeApplicationProtocol() != nil { + applicationProtocolStr = *configPort.GetMaybeApplicationProtocol() + } + port := &Port{ + TransportProtocol: TransportProtocol(configPort.GetTransportProtocol().String()), + ApplicationProtocol: ApplicationProtocol(applicationProtocolStr), + Name: portName, + Number: configPort.GetNumber(), + } + serviceYaml.Ports = append(serviceYaml.Ports, port) + } + + serviceYaml.EnvVars = []*EnvironmentVariable{} + for key, val := range serviceConfig.GetEnvVars() { + envVar := &EnvironmentVariable{ + Key: key, + Value: planYaml.swapFutureReference(val), + } + serviceYaml.EnvVars = append(serviceYaml.EnvVars, envVar) + } + + serviceYaml.Files = planYaml.getFileMountsFromFilesArtifacts(serviceConfig.GetFilesArtifactsExpansion()) + + planYaml.addServiceYaml(serviceYaml) + return nil +} + +func (planYaml *PlanYaml) AddRunSh( + runCommand string, + returnValue *starlarkstruct.Struct, + serviceConfig *service.ServiceConfig, + storeSpecList []*store_spec2.StoreSpec, +) error { + uuid := planYaml.generateUuid() + + // store run sh future references + codeVal, err := returnValue.Attr(codeFutureRefType) + if err != nil { + return err + } + codeFutureRef, interpErr := kurtosis_types.SafeCastToString(codeVal, "run sh "+codeFutureRefType) + if interpErr != nil { + return interpErr + } + planYaml.storeFutureReference(uuid, codeFutureRef, codeFutureRefType) + outputVal, err := returnValue.Attr(outputFutureRefType) + if err != nil { + return err + } + outputFutureRef, interpErr := kurtosis_types.SafeCastToString(outputVal, "run sh "+outputFutureRefType) + if interpErr != nil { + return interpErr + } + planYaml.storeFutureReference(uuid, outputFutureRef, outputFutureRefType) + + // create task yaml object + taskYaml := &Task{} //nolint exhaustruct + taskYaml.Uuid = uuid + taskYaml.TaskType = shell + + taskYaml.RunCmd = []string{planYaml.swapFutureReference(runCommand)} + taskYaml.Image = serviceConfig.GetContainerImageName() + + var envVars []*EnvironmentVariable + for key, val := range serviceConfig.GetEnvVars() { + envVars = append(envVars, &EnvironmentVariable{ + Key: key, + Value: planYaml.swapFutureReference(val), + }) + } + taskYaml.EnvVars = envVars + + taskYaml.Files = planYaml.getFileMountsFromFilesArtifacts(serviceConfig.GetFilesArtifactsExpansion()) + + // for store + // - all files artifacts product from store are new files artifact that are added to the plan + // - add them to files artifacts list + // - add them to the store section of run sh + var store []*FilesArtifact + for _, storeSpec := range storeSpecList { + var newFilesArtifactFromStoreSpec = &FilesArtifact{ + Uuid: planYaml.generateUuid(), + Name: storeSpec.GetName(), + Files: []string{storeSpec.GetSrc()}, + } + planYaml.addFilesArtifactYaml(newFilesArtifactFromStoreSpec) + + store = append(store, &FilesArtifact{ + Uuid: newFilesArtifactFromStoreSpec.Uuid, + Name: newFilesArtifactFromStoreSpec.Name, + Files: []string{}, // don't want to repeat the files on a referenced files artifact + }) + } + taskYaml.Store = store + + planYaml.addTaskYaml(taskYaml) + return nil +} + +func (planYaml *PlanYaml) AddRunPython( + runCommand string, + returnValue *starlarkstruct.Struct, + serviceConfig *service.ServiceConfig, + storeSpecList []*store_spec2.StoreSpec, + pythonArgs []string, + pythonPackages []string) error { + uuid := planYaml.generateUuid() + + // store future references + codeVal, err := returnValue.Attr(codeFutureRefType) + if err != nil { + return err + } + codeFutureRef, interpErr := kurtosis_types.SafeCastToString(codeVal, "run python "+codeFutureRefType) + if interpErr != nil { + return interpErr + } + planYaml.storeFutureReference(uuid, codeFutureRef, codeFutureRefType) + outputVal, err := returnValue.Attr(outputFutureRefType) + if err != nil { + return err + } + outputFutureRef, interpErr := kurtosis_types.SafeCastToString(outputVal, "run python "+outputFutureRefType) + if interpErr != nil { + return interpErr + } + planYaml.storeFutureReference(uuid, outputFutureRef, outputFutureRefType) + + // create task yaml object + taskYaml := &Task{} //nolint exhaustruct + taskYaml.Uuid = uuid + taskYaml.TaskType = python + + taskYaml.RunCmd = []string{planYaml.swapFutureReference(runCommand)} + taskYaml.Image = serviceConfig.GetContainerImageName() + + var envVars []*EnvironmentVariable + for key, val := range serviceConfig.GetEnvVars() { + envVars = append(envVars, &EnvironmentVariable{ + Key: key, + Value: planYaml.swapFutureReference(val), + }) + } + taskYaml.EnvVars = envVars + + // python args and python packages + taskYaml.PythonArgs = append(taskYaml.PythonArgs, pythonArgs...) + taskYaml.PythonPackages = append(taskYaml.PythonPackages, pythonPackages...) + + taskYaml.Files = planYaml.getFileMountsFromFilesArtifacts(serviceConfig.GetFilesArtifactsExpansion()) + + // for store + // - all files artifacts product from store are new files artifact that are added to the plan + // - add them to files artifacts list + // - add them to the store section of run sh + var store []*FilesArtifact + for _, storeSpec := range storeSpecList { + var newFilesArtifactFromStoreSpec = &FilesArtifact{ + Uuid: planYaml.generateUuid(), + Name: storeSpec.GetName(), + Files: []string{storeSpec.GetSrc()}, + } + planYaml.addFilesArtifactYaml(newFilesArtifactFromStoreSpec) + + store = append(store, &FilesArtifact{ + Uuid: newFilesArtifactFromStoreSpec.Uuid, + Name: newFilesArtifactFromStoreSpec.Name, + Files: []string{}, // don't want to repeat the files on a referenced files artifact + }) + } + taskYaml.Store = store + + planYaml.addTaskYaml(taskYaml) + return nil +} + +func (planYaml *PlanYaml) AddExec( + serviceName string, + returnValue *starlark.Dict, + cmdList []string, + acceptableCodes []int64) error { + uuid := planYaml.generateUuid() + + // store future references + codeVal, found, err := returnValue.Get(starlark.String(codeFutureRefType)) + if err != nil { + return err + } + if !found { + return stacktrace.NewError("No code value found on exec dict") + } + codeFutureRef, interpErr := kurtosis_types.SafeCastToString(codeVal, "exec "+codeFutureRefType) + if interpErr != nil { + return interpErr + } + planYaml.storeFutureReference(uuid, codeFutureRef, codeFutureRefType) + outputVal, found, err := returnValue.Get(starlark.String(outputFutureRefType)) + if err != nil { + return err + } + if !found { + return stacktrace.NewError("No code value found on exec dict") + } + outputFutureRef, interpErr := kurtosis_types.SafeCastToString(outputVal, "exec "+outputFutureRefType) + if interpErr != nil { + return interpErr + } + planYaml.storeFutureReference(uuid, outputFutureRef, outputFutureRefType) + + // create task yaml + taskYaml := &Task{} //nolint exhaustruct + taskYaml.Uuid = uuid + taskYaml.TaskType = exec + taskYaml.ServiceName = serviceName + + cmdListWithFutureRefsSwapped := []string{} + for _, cmd := range cmdList { + cmdListWithFutureRefsSwapped = append(cmdListWithFutureRefsSwapped, planYaml.swapFutureReference(cmd)) + } + taskYaml.RunCmd = cmdListWithFutureRefsSwapped + taskYaml.AcceptableCodes = acceptableCodes + + planYaml.privatePlanYaml.Tasks = append(planYaml.privatePlanYaml.Tasks, taskYaml) + return nil +} + +func (planYaml *PlanYaml) AddRenderTemplates(filesArtifactName string, filepaths []string) error { + uuid := planYaml.generateUuid() + filesArtifactYaml := &FilesArtifact{} //nolint exhaustruct + filesArtifactYaml.Uuid = uuid + filesArtifactYaml.Name = filesArtifactName + filesArtifactYaml.Files = filepaths + planYaml.addFilesArtifactYaml(filesArtifactYaml) + return nil +} + +func (planYaml *PlanYaml) AddUploadFiles(filesArtifactName, locator string) error { + uuid := planYaml.generateUuid() + filesArtifactYaml := &FilesArtifact{} //nolint exhauststruct + filesArtifactYaml.Uuid = uuid + filesArtifactYaml.Name = filesArtifactName + filesArtifactYaml.Files = []string{locator} + planYaml.addFilesArtifactYaml(filesArtifactYaml) + return nil +} + +func (planYaml *PlanYaml) AddStoreServiceFiles(filesArtifactName, locator string) error { + uuid := planYaml.generateUuid() + filesArtifactYaml := &FilesArtifact{} //nolint exhaustruct + filesArtifactYaml.Uuid = uuid + filesArtifactYaml.Name = filesArtifactName + filesArtifactYaml.Files = []string{locator} + planYaml.addFilesArtifactYaml(filesArtifactYaml) + return nil +} + +func (planYaml *PlanYaml) RemoveService(serviceName string) { + for idx, service := range planYaml.privatePlanYaml.Services { + if service.Name == serviceName { + planYaml.privatePlanYaml.Services = slices.Delete(planYaml.privatePlanYaml.Services, idx, idx+1) + return + } + } +} + +// getFileMountsFromFilesArtifacts turns filesArtifactExpansions into FileMount's +// file mounts have two cases: +// 1. the referenced files artifact already exists in the planYaml, in which case add the referenced files artifact to the proper filepath as a file mount +// 2. the referenced files artifact does not already exist in the plan, in which case the file MUST have been passed in via a top level arg +// for this case, +// - create new files artifact +// - add the files artifact to the plan +// - add it to as a file mount accordingly +func (planYaml *PlanYaml) getFileMountsFromFilesArtifacts(filesArtifactExpansion *service_directory.FilesArtifactsExpansion) []*FileMount { + var fileMounts []*FileMount + if filesArtifactExpansion == nil { + return fileMounts + } + for mountPath, artifactIdentifiers := range filesArtifactExpansion.ServiceDirpathsToArtifactIdentifiers { + var filesArtifacts []*FilesArtifact + for _, identifier := range artifactIdentifiers { + var filesArtifact *FilesArtifact + // if there's already a files artifact that exists with this name from a previous instruction, reference that + if filesArtifactToReference, ok := planYaml.filesArtifactIndex[identifier]; ok { + filesArtifact = &FilesArtifact{ + Name: filesArtifactToReference.Name, + Uuid: filesArtifactToReference.Uuid, + Files: []string{}, // leave empty because this is referencing an existing files artifact + } + } else { + // otherwise create a new one + // the only information we have about a files artifact that didn't already exist is the name + // if it didn't already exist AND interpretation was successful, it MUST HAVE been passed in via args of run function + filesArtifact = &FilesArtifact{ + Name: identifier, + Uuid: planYaml.generateUuid(), + Files: []string{}, // don't know at interpretation what files are on the artifact when passed in via args + } + planYaml.addFilesArtifactYaml(filesArtifact) + } + filesArtifacts = append(filesArtifacts, filesArtifact) + } + fileMounts = append(fileMounts, &FileMount{ + MountPath: mountPath, + FilesArtifacts: filesArtifacts, + }) + } + return fileMounts +} + +func (planYaml *PlanYaml) addServiceYaml(service *Service) { + planYaml.privatePlanYaml.Services = append(planYaml.privatePlanYaml.Services, service) +} + +func (planYaml *PlanYaml) addFilesArtifactYaml(filesArtifact *FilesArtifact) { + planYaml.filesArtifactIndex[filesArtifact.Name] = filesArtifact + planYaml.privatePlanYaml.FilesArtifacts = append(planYaml.privatePlanYaml.FilesArtifacts, filesArtifact) +} + +func (planYaml *PlanYaml) addTaskYaml(task *Task) { + planYaml.privatePlanYaml.Tasks = append(planYaml.privatePlanYaml.Tasks, task) +} + +// yaml future reference format: {{ kurtosis.. /bye.txt + image: badouralix/curl-jq + files: + - mountPath: /root + filesArtifacts: + - uuid: "2" + name: hi-file + store: + - uuid: "3" + name: bye-file + envVar: + - key: HELLO + value: Hello! +` + require.Equal(suite.T(), expectedYaml, planYaml) +} + +func (suite *StartosisIntepreterPlanYamlTestSuite) TestRunPython() { + script := `def run(plan, hi_files_artifact): + plan.run_python( + run = """ + import requests + response = requests.get("docs.kurtosis.com") + print(response.status_code) + """, + args = [ + "something" + ], + packages = [ + "selenium", + "requests", + ], + files = { + "/hi.txt": hi_files_artifact, + }, + store = [ + StoreSpec(src = "bye.txt", name = "bye-file"), + ], +) +` + inputArgs := `{"hi_files_artifact": "hi-file"}` + _, instructionsPlan, interpretationError := suite.interpreter.Interpret( + context.Background(), + startosis_constants.PackageIdPlaceholderForStandaloneScript, + useDefaultMainFunctionName, + noPackageReplaceOptions, + startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, + script, + inputArgs, + defaultNonBlockingMode, + emptyEnclaveComponents, + emptyInstructionsPlanMask, + image_download_mode.ImageDownloadMode_Always) + require.Nil(suite.T(), interpretationError) + require.Equal(suite.T(), 1, instructionsPlan.Size()) + + planYaml, err := instructionsPlan.GenerateYaml(plan_yaml.CreateEmptyPlan(startosis_constants.PackageIdPlaceholderForStandaloneScript)) + require.NoError(suite.T(), err) + + expectedYaml := `packageId: DEFAULT_PACKAGE_ID_FOR_SCRIPT +filesArtifacts: +- uuid: "2" + name: hi-file +- uuid: "3" + name: bye-file + files: + - bye.txt +tasks: +- uuid: "1" + taskType: python + command: + - "\n import requests\n response = requests.get(\"docs.kurtosis.com\")\n print(response.status_code) + \ \n " + image: python:3.11-alpine + files: + - mountPath: /hi.txt + filesArtifacts: + - uuid: "2" + name: hi-file + store: + - uuid: "3" + name: bye-file + pythonPackages: + - selenium + - requests + pythonArgs: + - something +` + require.Equal(suite.T(), expectedYaml, planYaml) +} + +func (suite *StartosisIntepreterPlanYamlTestSuite) TestExec() { + script := `def run(plan, hi_files_artifact): + plan.add_service( + name="db", + config=ServiceConfig( + image="postgres:latest", + env_vars={ + "POSTGRES_DB": "kurtosis", + "POSTGRES_USER": "kurtosis", + "POSTGRES_PASSWORD": "kurtosis", + }, + files = { + "/root": hi_files_artifact, + } + ) + ) + result = plan.exec( + service_name="db", + recipe=ExecRecipe(command=["echo", "Hello, world"]), + acceptable_codes=[0], + ) +` + inputArgs := `{"hi_files_artifact": "hi-file"}` + _, instructionsPlan, interpretationError := suite.interpreter.Interpret( + context.Background(), + startosis_constants.PackageIdPlaceholderForStandaloneScript, + useDefaultMainFunctionName, + noPackageReplaceOptions, + startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, + script, + inputArgs, + defaultNonBlockingMode, + emptyEnclaveComponents, + emptyInstructionsPlanMask, + image_download_mode.ImageDownloadMode_Always) + require.Nil(suite.T(), interpretationError) + require.Equal(suite.T(), 2, instructionsPlan.Size()) + + planYaml, err := instructionsPlan.GenerateYaml(plan_yaml.CreateEmptyPlan(startosis_constants.PackageIdPlaceholderForStandaloneScript)) + require.NoError(suite.T(), err) + + expectedYaml := `packageId: DEFAULT_PACKAGE_ID_FOR_SCRIPT +services: +- uuid: "1" + name: db + image: + name: postgres:latest + envVars: + - key: POSTGRES_DB + value: kurtosis + - key: POSTGRES_PASSWORD + value: kurtosis + - key: POSTGRES_USER + value: kurtosis + files: + - mountPath: /root + filesArtifacts: + - uuid: "2" + name: hi-file +filesArtifacts: +- uuid: "2" + name: hi-file +tasks: +- uuid: "3" + taskType: exec + command: + - echo + - Hello, world + serviceName: db + acceptableCodes: + - 0 +` + require.Equal(suite.T(), expectedYaml, planYaml) +} + +func (suite *StartosisIntepreterPlanYamlTestSuite) TestRenderTemplate() { + script := `def run(plan, args): + bye_files_artifact = plan.render_templates( + name="bye-file", + config={ + "bye.txt": struct( + template="Bye bye!", + data={} + ), + "fairwell.txt": struct ( + template = "Fair well!", + data = {} + ), + } + ) + + plan.run_sh( + run="cat /root/bye.txt", + files = { + "/root": bye_files_artifact, + }, + ) +` + inputArgs := `{"hi_files_artifact": "hi-file"}` + _, instructionsPlan, interpretationError := suite.interpreter.Interpret( + context.Background(), + startosis_constants.PackageIdPlaceholderForStandaloneScript, + useDefaultMainFunctionName, + noPackageReplaceOptions, + startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, + script, + inputArgs, + defaultNonBlockingMode, + emptyEnclaveComponents, + emptyInstructionsPlanMask, + image_download_mode.ImageDownloadMode_Always) + require.Nil(suite.T(), interpretationError) + require.Equal(suite.T(), 2, instructionsPlan.Size()) + + planYaml, err := instructionsPlan.GenerateYaml(plan_yaml.CreateEmptyPlan(startosis_constants.PackageIdPlaceholderForStandaloneScript)) + require.NoError(suite.T(), err) + + expectedYaml := `packageId: DEFAULT_PACKAGE_ID_FOR_SCRIPT +filesArtifacts: +- uuid: "1" + name: bye-file + files: + - bye.txt + - fairwell.txt +tasks: +- uuid: "2" + taskType: sh + command: + - cat /root/bye.txt + image: badouralix/curl-jq + files: + - mountPath: /root + filesArtifacts: + - uuid: "1" + name: bye-file +` + require.Equal(suite.T(), expectedYaml, planYaml) +} + +func (suite *StartosisIntepreterPlanYamlTestSuite) TestAddServiceWithImageBuildSpec() { + dockerfileModulePath := "github.com/kurtosis-tech/plan-yaml-prac/server/Dockerfile" + serverModulePath := "github.com/kurtosis-tech/plan-yaml-prac/server" + dockerfileContents := `RUN ["something"]` + require.Nil(suite.T(), suite.packageContentProvider.AddFileContent(dockerfileModulePath, dockerfileContents)) + require.Nil(suite.T(), suite.packageContentProvider.AddFileContent(serverModulePath, "")) + packageId := "github.com/kurtosis-tech/plan-yaml-prac" + + script := `def run(plan, hi_files_artifact): + plan.add_service( + name="db", + config=ServiceConfig( + image = ImageBuildSpec( + image_name="` + testContainerImageName + `", + build_context_dir="./server", + target_stage="builder", + ), + files = { + "/root": hi_files_artifact, + } + ) + ) +` + inputArgs := `{"hi_files_artifact": "hi-file"}` + _, instructionsPlan, interpretationError := suite.interpreter.Interpret( + context.Background(), + packageId, + useDefaultMainFunctionName, + noPackageReplaceOptions, + startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, + script, + inputArgs, + defaultNonBlockingMode, + emptyEnclaveComponents, + emptyInstructionsPlanMask, + image_download_mode.ImageDownloadMode_Always) + require.Nil(suite.T(), interpretationError) + require.Equal(suite.T(), 1, instructionsPlan.Size()) + + planYaml, err := instructionsPlan.GenerateYaml(plan_yaml.CreateEmptyPlan(packageId)) + require.NoError(suite.T(), err) + + expectedYaml := `packageId: ` + packageId + ` +services: +- uuid: "1" + name: db + image: + name: kurtosistech/example-datastore-server + buildContextLocator: ./server + targetStage: builder + files: + - mountPath: /root + filesArtifacts: + - uuid: "2" + name: hi-file +filesArtifacts: +- uuid: "2" + name: hi-file +` + require.Equal(suite.T(), expectedYaml, planYaml) +} + +func (suite *StartosisIntepreterPlanYamlTestSuite) TestAddServiceWithImageSpec() { + dockerfileModulePath := "github.com/kurtosis-tech/plan-yaml-prac/server/Dockerfile" + serverModulePath := "github.com/kurtosis-tech/plan-yaml-prac/server" + dockerfileContents := `RUN ["something"]` + require.Nil(suite.T(), suite.packageContentProvider.AddFileContent(dockerfileModulePath, dockerfileContents)) + require.Nil(suite.T(), suite.packageContentProvider.AddFileContent(serverModulePath, "")) + packageId := "github.com/kurtosis-tech/plan-yaml-prac" + + script := `def run(plan, hi_files_artifact): + plan.add_service( + name="db", + config=ServiceConfig( + image = ImageSpec( + image="` + testContainerImageName + `", + registry = "http://my.registry.io/", + ), + files = { + "/root": hi_files_artifact, + } + ) + ) +` + inputArgs := `{"hi_files_artifact": "hi-file"}` + _, instructionsPlan, interpretationError := suite.interpreter.Interpret( + context.Background(), + packageId, + useDefaultMainFunctionName, + noPackageReplaceOptions, + startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, + script, + inputArgs, + defaultNonBlockingMode, + emptyEnclaveComponents, + emptyInstructionsPlanMask, + image_download_mode.ImageDownloadMode_Always) + require.Nil(suite.T(), interpretationError) + require.Equal(suite.T(), 1, instructionsPlan.Size()) + + planYaml, err := instructionsPlan.GenerateYaml(plan_yaml.CreateEmptyPlan(packageId)) + require.NoError(suite.T(), err) + + expectedYaml := `packageId: ` + packageId + ` +services: +- uuid: "1" + name: db + image: + name: kurtosistech/example-datastore-server + registry: http://my.registry.io/ + files: + - mountPath: /root + filesArtifacts: + - uuid: "2" + name: hi-file +filesArtifacts: +- uuid: "2" + name: hi-file +` + require.Equal(suite.T(), expectedYaml, planYaml) +} + +func (suite *StartosisIntepreterPlanYamlTestSuite) TestUploadFiles() { + dockerfileModulePath := "github.com/kurtosis-tech/plan-yaml-prac/server/Dockerfile" + serverModulePath := "github.com/kurtosis-tech/plan-yaml-prac/server" + dockerfileContents := `RUN ["something"]` + require.Nil(suite.T(), suite.packageContentProvider.AddFileContent(dockerfileModulePath, dockerfileContents)) + require.Nil(suite.T(), suite.packageContentProvider.AddFileContent(serverModulePath, "")) + + packageId := "github.com/kurtosis-tech/plan-yaml-prac" + + script := `def run(plan, args): + dockerfile_artifact = plan.upload_files(src="./server/Dockerfile", name="dockerfile") + + plan.run_sh( + run="cat /root/Dockerfile", + files = { + "/root": dockerfile_artifact, + }, + ) +` + _, instructionsPlan, interpretationError := suite.interpreter.Interpret( + context.Background(), + packageId, + useDefaultMainFunctionName, + noPackageReplaceOptions, + startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, + script, + startosis_constants.EmptyInputArgs, + defaultNonBlockingMode, + emptyEnclaveComponents, + emptyInstructionsPlanMask, + image_download_mode.ImageDownloadMode_Always) + require.Nil(suite.T(), interpretationError) + require.Equal(suite.T(), 2, instructionsPlan.Size()) + + planYaml, err := instructionsPlan.GenerateYaml(plan_yaml.CreateEmptyPlan(packageId)) + require.NoError(suite.T(), err) + + expectedYaml := `packageId: ` + packageId + ` +filesArtifacts: +- uuid: "1" + name: dockerfile + files: + - ./server/Dockerfile +tasks: +- uuid: "2" + taskType: sh + command: + - cat /root/Dockerfile + image: badouralix/curl-jq + files: + - mountPath: /root + filesArtifacts: + - uuid: "1" + name: dockerfile +` + require.Equal(suite.T(), expectedYaml, planYaml) +} + +func (suite *StartosisIntepreterPlanYamlTestSuite) TestStoreServiceFiles() { + script := `def run(plan, hi_files_artifact): + plan.add_service( + name="db", + config=ServiceConfig( + image="postgres:latest", + cmd=["touch", "bye.txt"], + files = { + "/root": hi_files_artifact + } + ), + ) + + bye_files_artifact = plan.store_service_files( + name="bye-file", + src="bye.txt", + service_name="db", + ) +` + inputArgs := `{"hi_files_artifact": "hi-file"}` + _, instructionsPlan, interpretationError := suite.interpreter.Interpret( + context.Background(), + startosis_constants.PackageIdPlaceholderForStandaloneScript, + useDefaultMainFunctionName, + noPackageReplaceOptions, + startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, + script, + inputArgs, + defaultNonBlockingMode, + emptyEnclaveComponents, + emptyInstructionsPlanMask, + image_download_mode.ImageDownloadMode_Always) + require.Nil(suite.T(), interpretationError) + require.Equal(suite.T(), 2, instructionsPlan.Size()) + + planYaml, err := instructionsPlan.GenerateYaml(plan_yaml.CreateEmptyPlan(startosis_constants.PackageIdPlaceholderForStandaloneScript)) + require.NoError(suite.T(), err) + + expectedYaml := `packageId: DEFAULT_PACKAGE_ID_FOR_SCRIPT +services: +- uuid: "1" + name: db + image: + name: postgres:latest + command: + - touch + - bye.txt + files: + - mountPath: /root + filesArtifacts: + - uuid: "2" + name: hi-file +filesArtifacts: +- uuid: "2" + name: hi-file +- uuid: "3" + name: bye-file + files: + - bye.txt +` + require.Equal(suite.T(), expectedYaml, planYaml) +} + +func (suite *StartosisIntepreterPlanYamlTestSuite) TestRemoveService() { + script := `def run(plan, hi_files_artifact): + plan.add_service( + name="db", + config=ServiceConfig( + image="postgres:latest", + env_vars={ + "POSTGRES_DB": "tedi", + "POSTGRES_USER": "tedi", + "POSTGRES_PASSWORD": "tedi", + }, + files = { + "/root": hi_files_artifact, + } + ) + ) + plan.remove_service(name="db") +` + inputArgs := `{"hi_files_artifact": "hi-file"}` + _, instructionsPlan, interpretationError := suite.interpreter.Interpret( + context.Background(), + startosis_constants.PackageIdPlaceholderForStandaloneScript, + useDefaultMainFunctionName, + noPackageReplaceOptions, + startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, + script, + inputArgs, + defaultNonBlockingMode, + emptyEnclaveComponents, + emptyInstructionsPlanMask, + image_download_mode.ImageDownloadMode_Always) + require.Nil(suite.T(), interpretationError) + require.Equal(suite.T(), 2, instructionsPlan.Size()) + + planYaml, err := instructionsPlan.GenerateYaml(plan_yaml.CreateEmptyPlan(startosis_constants.PackageIdPlaceholderForStandaloneScript)) + require.NoError(suite.T(), err) + + expectedYaml := `packageId: DEFAULT_PACKAGE_ID_FOR_SCRIPT +filesArtifacts: +- uuid: "2" + name: hi-file +` + require.Equal(suite.T(), expectedYaml, planYaml) +} + +func (suite *StartosisIntepreterPlanYamlTestSuite) TestFutureReferencesAreSwapped() { + script := `def run(plan, hi_files_artifact): + service = plan.add_service( + name="db", + config=ServiceConfig( + image="postgres:latest", + env_vars={ + "POSTGRES_DB": "kurtosis", + "POSTGRES_USER": "kurtosis", + "POSTGRES_PASSWORD": "kurtosis", + }, + files = { + "/root": hi_files_artifact, + } + ) + ) + execResult = plan.exec( + service_name="db", + recipe=ExecRecipe( + command=["echo", service.ip_address + " " + service.hostname] + ), + acceptable_codes=[0], + ) + runShResult = plan.run_sh( + run="echo " + execResult["code"] + " " + execResult["output"], + ) + plan.run_sh( + run="echo " + runShResult.code + " " + runShResult.output, + ) +` + inputArgs := `{"hi_files_artifact": "hi-file"}` + _, instructionsPlan, interpretationError := suite.interpreter.Interpret( + context.Background(), + startosis_constants.PackageIdPlaceholderForStandaloneScript, + useDefaultMainFunctionName, + noPackageReplaceOptions, + startosis_constants.PlaceHolderMainFileForPlaceStandAloneScript, + script, + inputArgs, + defaultNonBlockingMode, + emptyEnclaveComponents, + emptyInstructionsPlanMask, + image_download_mode.ImageDownloadMode_Always) + require.Nil(suite.T(), interpretationError) + require.Equal(suite.T(), 4, instructionsPlan.Size()) + + planYaml, err := instructionsPlan.GenerateYaml(plan_yaml.CreateEmptyPlan(startosis_constants.PackageIdPlaceholderForStandaloneScript)) + require.NoError(suite.T(), err) + + expectedYaml := `packageId: DEFAULT_PACKAGE_ID_FOR_SCRIPT +services: +- uuid: "1" + name: db + image: + name: postgres:latest + envVars: + - key: POSTGRES_DB + value: kurtosis + - key: POSTGRES_PASSWORD + value: kurtosis + - key: POSTGRES_USER + value: kurtosis + files: + - mountPath: /root + filesArtifacts: + - uuid: "2" + name: hi-file +filesArtifacts: +- uuid: "2" + name: hi-file +tasks: +- uuid: "3" + taskType: exec + command: + - echo + - '{{ kurtosis.1.ip_address }} {{ kurtosis.1.hostname }}' + serviceName: db + acceptableCodes: + - 0 +- uuid: "4" + taskType: sh + command: + - echo {{ kurtosis.3.code }} {{ kurtosis.3.output }} + image: badouralix/curl-jq +- uuid: "5" + taskType: sh + command: + - echo {{ kurtosis.4.code }} {{ kurtosis.4.output }} + image: badouralix/curl-jq +` + require.Equal(suite.T(), expectedYaml, planYaml) +} diff --git a/enclave-manager/api/golang/kurtosis_enclave_manager_api_bindings/kurtosis_enclave_manager_api.pb.go b/enclave-manager/api/golang/kurtosis_enclave_manager_api_bindings/kurtosis_enclave_manager_api.pb.go index 0fb7382651..fe054ac9d1 100644 --- a/enclave-manager/api/golang/kurtosis_enclave_manager_api_bindings/kurtosis_enclave_manager_api.pb.go +++ b/enclave-manager/api/golang/kurtosis_enclave_manager_api_bindings/kurtosis_enclave_manager_api.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.24.4 +// protoc-gen-go v1.32.0 +// protoc v4.25.2 // source: kurtosis_enclave_manager_api.proto package kurtosis_enclave_manager_api_bindings @@ -586,6 +586,137 @@ func (x *GetStarlarkRunRequest) GetApicPort() int32 { return 0 } +// ============================================================================================== +// +// Get Starlark Plan Yaml +// +// ============================================================================================== +type StarlarkScriptPlanYamlArgs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ApicIpAddress string `protobuf:"bytes,1,opt,name=apic_ip_address,json=apicIpAddress,proto3" json:"apic_ip_address,omitempty"` + ApicPort int32 `protobuf:"varint,2,opt,name=apic_port,json=apicPort,proto3" json:"apic_port,omitempty"` + StarlarkScriptPlanYamlArgs *kurtosis_core_rpc_api_bindings.StarlarkScriptPlanYamlArgs `protobuf:"bytes,3,opt,name=starlark_script_plan_yaml_args,json=starlarkScriptPlanYamlArgs,proto3" json:"starlark_script_plan_yaml_args,omitempty"` +} + +func (x *StarlarkScriptPlanYamlArgs) Reset() { + *x = StarlarkScriptPlanYamlArgs{} + if protoimpl.UnsafeEnabled { + mi := &file_kurtosis_enclave_manager_api_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StarlarkScriptPlanYamlArgs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StarlarkScriptPlanYamlArgs) ProtoMessage() {} + +func (x *StarlarkScriptPlanYamlArgs) ProtoReflect() protoreflect.Message { + mi := &file_kurtosis_enclave_manager_api_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StarlarkScriptPlanYamlArgs.ProtoReflect.Descriptor instead. +func (*StarlarkScriptPlanYamlArgs) Descriptor() ([]byte, []int) { + return file_kurtosis_enclave_manager_api_proto_rawDescGZIP(), []int{9} +} + +func (x *StarlarkScriptPlanYamlArgs) GetApicIpAddress() string { + if x != nil { + return x.ApicIpAddress + } + return "" +} + +func (x *StarlarkScriptPlanYamlArgs) GetApicPort() int32 { + if x != nil { + return x.ApicPort + } + return 0 +} + +func (x *StarlarkScriptPlanYamlArgs) GetStarlarkScriptPlanYamlArgs() *kurtosis_core_rpc_api_bindings.StarlarkScriptPlanYamlArgs { + if x != nil { + return x.StarlarkScriptPlanYamlArgs + } + return nil +} + +type StarlarkPackagePlanYamlArgs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ApicIpAddress string `protobuf:"bytes,1,opt,name=apic_ip_address,json=apicIpAddress,proto3" json:"apic_ip_address,omitempty"` + ApicPort int32 `protobuf:"varint,2,opt,name=apic_port,json=apicPort,proto3" json:"apic_port,omitempty"` + StarlarkPackagePlanYamlArgs *kurtosis_core_rpc_api_bindings.StarlarkPackagePlanYamlArgs `protobuf:"bytes,3,opt,name=starlark_package_plan_yaml_args,json=starlarkPackagePlanYamlArgs,proto3" json:"starlark_package_plan_yaml_args,omitempty"` +} + +func (x *StarlarkPackagePlanYamlArgs) Reset() { + *x = StarlarkPackagePlanYamlArgs{} + if protoimpl.UnsafeEnabled { + mi := &file_kurtosis_enclave_manager_api_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StarlarkPackagePlanYamlArgs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StarlarkPackagePlanYamlArgs) ProtoMessage() {} + +func (x *StarlarkPackagePlanYamlArgs) ProtoReflect() protoreflect.Message { + mi := &file_kurtosis_enclave_manager_api_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StarlarkPackagePlanYamlArgs.ProtoReflect.Descriptor instead. +func (*StarlarkPackagePlanYamlArgs) Descriptor() ([]byte, []int) { + return file_kurtosis_enclave_manager_api_proto_rawDescGZIP(), []int{10} +} + +func (x *StarlarkPackagePlanYamlArgs) GetApicIpAddress() string { + if x != nil { + return x.ApicIpAddress + } + return "" +} + +func (x *StarlarkPackagePlanYamlArgs) GetApicPort() int32 { + if x != nil { + return x.ApicPort + } + return 0 +} + +func (x *StarlarkPackagePlanYamlArgs) GetStarlarkPackagePlanYamlArgs() *kurtosis_core_rpc_api_bindings.StarlarkPackagePlanYamlArgs { + if x != nil { + return x.StarlarkPackagePlanYamlArgs + } + return nil +} + var File_kurtosis_enclave_manager_api_proto protoreflect.FileDescriptor var file_kurtosis_enclave_manager_api_proto_rawDesc = []byte{ @@ -681,99 +812,141 @@ var file_kurtosis_enclave_manager_api_proto_rawDesc = []byte{ 0x63, 0x5f, 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x70, 0x69, 0x63, 0x49, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x70, 0x69, 0x63, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x61, 0x70, 0x69, 0x63, 0x50, 0x6f, 0x72, 0x74, 0x32, 0xce, - 0x0a, 0x0a, 0x1c, 0x4b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x45, 0x6e, 0x63, 0x6c, 0x61, - 0x76, 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, - 0x64, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x2c, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x61, 0x70, 0x69, 0x63, 0x50, 0x6f, 0x72, 0x74, 0x22, 0xd4, + 0x01, 0x0a, 0x1a, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x53, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x50, 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, 0x6c, 0x41, 0x72, 0x67, 0x73, 0x12, 0x26, 0x0a, + 0x0f, 0x61, 0x70, 0x69, 0x63, 0x5f, 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x70, 0x69, 0x63, 0x49, 0x70, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x70, 0x69, 0x63, 0x5f, 0x70, 0x6f, + 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x61, 0x70, 0x69, 0x63, 0x50, 0x6f, + 0x72, 0x74, 0x12, 0x71, 0x0a, 0x1e, 0x73, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x5f, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x5f, 0x79, 0x61, 0x6d, 0x6c, 0x5f, + 0x61, 0x72, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x61, 0x70, 0x69, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, + 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x6c, 0x61, + 0x6e, 0x59, 0x61, 0x6d, 0x6c, 0x41, 0x72, 0x67, 0x73, 0x52, 0x1a, 0x73, 0x74, 0x61, 0x72, 0x6c, + 0x61, 0x72, 0x6b, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, + 0x6c, 0x41, 0x72, 0x67, 0x73, 0x22, 0xd8, 0x01, 0x0a, 0x1b, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, + 0x72, 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, + 0x6c, 0x41, 0x72, 0x67, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x61, 0x70, 0x69, 0x63, 0x5f, 0x69, 0x70, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, + 0x61, 0x70, 0x69, 0x63, 0x49, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, + 0x09, 0x61, 0x70, 0x69, 0x63, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x08, 0x61, 0x70, 0x69, 0x63, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x74, 0x0a, 0x1f, 0x73, 0x74, + 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x70, + 0x6c, 0x61, 0x6e, 0x5f, 0x79, 0x61, 0x6d, 0x6c, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, + 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, 0x6c, 0x41, + 0x72, 0x67, 0x73, 0x52, 0x1b, 0x73, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x50, 0x61, 0x63, + 0x6b, 0x61, 0x67, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, 0x6c, 0x41, 0x72, 0x67, 0x73, + 0x32, 0xb4, 0x0c, 0x0a, 0x1c, 0x4b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x45, 0x6e, 0x63, + 0x6c, 0x61, 0x76, 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x12, 0x64, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x2c, 0x2e, 0x6b, 0x75, 0x72, + 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x45, 0x6e, + 0x63, 0x6c, 0x61, 0x76, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, + 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x45, + 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x65, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x12, 0x2c, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, 0x6c, + 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, + 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, + 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1e, 0x2e, 0x65, 0x6e, 0x67, + 0x69, 0x6e, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x22, 0x2e, 0x65, 0x6e, 0x67, + 0x69, 0x6e, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x30, 0x01, 0x12, 0xa1, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x41, 0x6e, 0x64, + 0x55, 0x75, 0x69, 0x64, 0x73, 0x12, 0x42, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, + 0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, + 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x55, 0x75, 0x69, + 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x61, 0x70, 0x69, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x55, 0x75, 0x69, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x79, 0x0a, 0x12, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, + 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x33, 0x2e, 0x6b, + 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x5f, + 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x6c, + 0x61, 0x72, 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4c, 0x69, 0x6e, 0x65, 0x22, 0x00, 0x30, + 0x01, 0x12, 0x77, 0x0a, 0x11, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x32, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x72, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x63, 0x6c, - 0x61, 0x76, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, 0x2e, 0x65, - 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x63, - 0x6c, 0x61, 0x76, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x65, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x2c, - 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, - 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x61, - 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, - 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1e, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, - 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x4c, 0x6f, 0x67, 0x73, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x22, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, - 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, - 0x12, 0xa1, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, - 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x55, 0x75, - 0x69, 0x64, 0x73, 0x12, 0x42, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, + 0x72, 0x2e, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x53, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x70, 0x69, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, + 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x4c, 0x69, 0x6e, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x53, 0x0a, 0x0d, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x12, 0x1d, 0x2e, 0x65, 0x6e, + 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, + 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x21, 0x2e, 0x65, 0x6e, 0x67, + 0x69, 0x6e, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, + 0x63, 0x6c, 0x61, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x98, 0x01, 0x0a, 0x1c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, + 0x12, 0x3d, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, 0x6c, + 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x49, 0x6e, 0x73, 0x70, + 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x37, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, + 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x79, 0x0a, 0x15, 0x44, 0x6f, + 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x12, 0x36, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, + 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x44, + 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x70, + 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x43, 0x68, 0x75, 0x6e, + 0x6b, 0x22, 0x00, 0x30, 0x01, 0x12, 0x4a, 0x0a, 0x0e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, + 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x12, 0x1e, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, + 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x45, 0x6e, 0x63, 0x6c, + 0x61, 0x76, 0x65, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, + 0x00, 0x12, 0x6e, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, + 0x52, 0x75, 0x6e, 0x12, 0x2f, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x47, - 0x65, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, - 0x61, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x55, 0x75, 0x69, 0x64, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x41, 0x6e, 0x64, 0x55, 0x75, 0x69, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x79, 0x0a, 0x12, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x6c, - 0x61, 0x72, 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x33, 0x2e, 0x6b, 0x75, 0x72, - 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, - 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2a, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, - 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4c, 0x69, 0x6e, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, - 0x77, 0x0a, 0x11, 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x53, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x12, 0x32, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, - 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, - 0x52, 0x75, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, - 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x4c, 0x69, 0x6e, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x53, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x12, 0x1d, 0x2e, 0x65, 0x6e, 0x67, 0x69, - 0x6e, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x63, - 0x6c, 0x61, 0x76, 0x65, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x21, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, - 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x63, 0x6c, - 0x61, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x98, 0x01, - 0x0a, 0x1c, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, - 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3d, + 0x65, 0x74, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x72, + 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x70, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x34, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, - 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, - 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, - 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, - 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, - 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x79, 0x0a, 0x15, 0x44, 0x6f, 0x77, 0x6e, - 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, - 0x74, 0x12, 0x36, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, - 0x6c, 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x77, - 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, - 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x5f, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x22, - 0x00, 0x30, 0x01, 0x12, 0x4a, 0x0a, 0x0e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x45, 0x6e, - 0x63, 0x6c, 0x61, 0x76, 0x65, 0x12, 0x1e, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x61, - 0x70, 0x69, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, - 0x65, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, - 0x6e, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, - 0x6e, 0x12, 0x2f, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, - 0x6c, 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, - 0x72, 0x6b, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, - 0x64, 0x5a, 0x62, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x75, - 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x2d, 0x74, 0x65, 0x63, 0x68, 0x2f, 0x6b, 0x75, 0x72, 0x74, - 0x6f, 0x73, 0x69, 0x73, 0x2f, 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x2d, 0x6d, 0x61, 0x6e, - 0x61, 0x67, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, - 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, - 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x5f, 0x62, 0x69, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, + 0x72, 0x6b, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, 0x6c, + 0x41, 0x72, 0x67, 0x73, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, + 0x6c, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x72, 0x6c, 0x61, + 0x72, 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x50, 0x6c, 0x61, 0x6e, 0x59, 0x61, 0x6d, + 0x6c, 0x12, 0x35, 0x2e, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x63, + 0x6c, 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x61, + 0x72, 0x6c, 0x61, 0x72, 0x6b, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x50, 0x6c, 0x61, 0x6e, + 0x59, 0x61, 0x6d, 0x6c, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x6c, 0x61, + 0x6e, 0x59, 0x61, 0x6d, 0x6c, 0x22, 0x00, 0x42, 0x64, 0x5a, 0x62, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x2d, 0x74, + 0x65, 0x63, 0x68, 0x2f, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x2f, 0x65, 0x6e, 0x63, + 0x6c, 0x61, 0x76, 0x65, 0x2d, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x6b, 0x75, 0x72, 0x74, 0x6f, 0x73, 0x69, 0x73, + 0x5f, 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, + 0x5f, 0x61, 0x70, 0x69, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -789,7 +962,7 @@ func file_kurtosis_enclave_manager_api_proto_rawDescGZIP() []byte { } var file_kurtosis_enclave_manager_api_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_kurtosis_enclave_manager_api_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_kurtosis_enclave_manager_api_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_kurtosis_enclave_manager_api_proto_goTypes = []interface{}{ (HealthCheckResponse_ServingStatus)(0), // 0: kurtosis_enclave_manager.HealthCheckResponse.ServingStatus (*HealthCheckRequest)(nil), // 1: kurtosis_enclave_manager.HealthCheckRequest @@ -801,59 +974,70 @@ var file_kurtosis_enclave_manager_api_proto_goTypes = []interface{}{ (*InspectFilesArtifactContentsRequest)(nil), // 7: kurtosis_enclave_manager.InspectFilesArtifactContentsRequest (*DownloadFilesArtifactRequest)(nil), // 8: kurtosis_enclave_manager.DownloadFilesArtifactRequest (*GetStarlarkRunRequest)(nil), // 9: kurtosis_enclave_manager.GetStarlarkRunRequest - (*kurtosis_core_rpc_api_bindings.RunStarlarkPackageArgs)(nil), // 10: api_container_api.RunStarlarkPackageArgs - (*kurtosis_core_rpc_api_bindings.RunStarlarkScriptArgs)(nil), // 11: api_container_api.RunStarlarkScriptArgs - (*kurtosis_core_rpc_api_bindings.FilesArtifactNameAndUuid)(nil), // 12: api_container_api.FilesArtifactNameAndUuid - (*kurtosis_core_rpc_api_bindings.DownloadFilesArtifactArgs)(nil), // 13: api_container_api.DownloadFilesArtifactArgs - (*emptypb.Empty)(nil), // 14: google.protobuf.Empty - (*kurtosis_engine_rpc_api_bindings.GetServiceLogsArgs)(nil), // 15: engine_api.GetServiceLogsArgs - (*kurtosis_engine_rpc_api_bindings.CreateEnclaveArgs)(nil), // 16: engine_api.CreateEnclaveArgs - (*kurtosis_engine_rpc_api_bindings.DestroyEnclaveArgs)(nil), // 17: engine_api.DestroyEnclaveArgs - (*kurtosis_engine_rpc_api_bindings.GetEnclavesResponse)(nil), // 18: engine_api.GetEnclavesResponse - (*kurtosis_core_rpc_api_bindings.GetServicesResponse)(nil), // 19: api_container_api.GetServicesResponse - (*kurtosis_engine_rpc_api_bindings.GetServiceLogsResponse)(nil), // 20: engine_api.GetServiceLogsResponse - (*kurtosis_core_rpc_api_bindings.ListFilesArtifactNamesAndUuidsResponse)(nil), // 21: api_container_api.ListFilesArtifactNamesAndUuidsResponse - (*kurtosis_core_rpc_api_bindings.StarlarkRunResponseLine)(nil), // 22: api_container_api.StarlarkRunResponseLine - (*kurtosis_engine_rpc_api_bindings.CreateEnclaveResponse)(nil), // 23: engine_api.CreateEnclaveResponse - (*kurtosis_core_rpc_api_bindings.InspectFilesArtifactContentsResponse)(nil), // 24: api_container_api.InspectFilesArtifactContentsResponse - (*kurtosis_core_rpc_api_bindings.StreamedDataChunk)(nil), // 25: api_container_api.StreamedDataChunk - (*kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse)(nil), // 26: api_container_api.GetStarlarkRunResponse + (*StarlarkScriptPlanYamlArgs)(nil), // 10: kurtosis_enclave_manager.StarlarkScriptPlanYamlArgs + (*StarlarkPackagePlanYamlArgs)(nil), // 11: kurtosis_enclave_manager.StarlarkPackagePlanYamlArgs + (*kurtosis_core_rpc_api_bindings.RunStarlarkPackageArgs)(nil), // 12: api_container_api.RunStarlarkPackageArgs + (*kurtosis_core_rpc_api_bindings.RunStarlarkScriptArgs)(nil), // 13: api_container_api.RunStarlarkScriptArgs + (*kurtosis_core_rpc_api_bindings.FilesArtifactNameAndUuid)(nil), // 14: api_container_api.FilesArtifactNameAndUuid + (*kurtosis_core_rpc_api_bindings.DownloadFilesArtifactArgs)(nil), // 15: api_container_api.DownloadFilesArtifactArgs + (*kurtosis_core_rpc_api_bindings.StarlarkScriptPlanYamlArgs)(nil), // 16: api_container_api.StarlarkScriptPlanYamlArgs + (*kurtosis_core_rpc_api_bindings.StarlarkPackagePlanYamlArgs)(nil), // 17: api_container_api.StarlarkPackagePlanYamlArgs + (*emptypb.Empty)(nil), // 18: google.protobuf.Empty + (*kurtosis_engine_rpc_api_bindings.GetServiceLogsArgs)(nil), // 19: engine_api.GetServiceLogsArgs + (*kurtosis_engine_rpc_api_bindings.CreateEnclaveArgs)(nil), // 20: engine_api.CreateEnclaveArgs + (*kurtosis_engine_rpc_api_bindings.DestroyEnclaveArgs)(nil), // 21: engine_api.DestroyEnclaveArgs + (*kurtosis_engine_rpc_api_bindings.GetEnclavesResponse)(nil), // 22: engine_api.GetEnclavesResponse + (*kurtosis_core_rpc_api_bindings.GetServicesResponse)(nil), // 23: api_container_api.GetServicesResponse + (*kurtosis_engine_rpc_api_bindings.GetServiceLogsResponse)(nil), // 24: engine_api.GetServiceLogsResponse + (*kurtosis_core_rpc_api_bindings.ListFilesArtifactNamesAndUuidsResponse)(nil), // 25: api_container_api.ListFilesArtifactNamesAndUuidsResponse + (*kurtosis_core_rpc_api_bindings.StarlarkRunResponseLine)(nil), // 26: api_container_api.StarlarkRunResponseLine + (*kurtosis_engine_rpc_api_bindings.CreateEnclaveResponse)(nil), // 27: engine_api.CreateEnclaveResponse + (*kurtosis_core_rpc_api_bindings.InspectFilesArtifactContentsResponse)(nil), // 28: api_container_api.InspectFilesArtifactContentsResponse + (*kurtosis_core_rpc_api_bindings.StreamedDataChunk)(nil), // 29: api_container_api.StreamedDataChunk + (*kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse)(nil), // 30: api_container_api.GetStarlarkRunResponse + (*kurtosis_core_rpc_api_bindings.PlanYaml)(nil), // 31: api_container_api.PlanYaml } var file_kurtosis_enclave_manager_api_proto_depIdxs = []int32{ 0, // 0: kurtosis_enclave_manager.HealthCheckResponse.status:type_name -> kurtosis_enclave_manager.HealthCheckResponse.ServingStatus - 10, // 1: kurtosis_enclave_manager.RunStarlarkPackageRequest.RunStarlarkPackageArgs:type_name -> api_container_api.RunStarlarkPackageArgs - 11, // 2: kurtosis_enclave_manager.RunStarlarkScriptRequest.RunStarlarkScriptArgs:type_name -> api_container_api.RunStarlarkScriptArgs - 12, // 3: kurtosis_enclave_manager.InspectFilesArtifactContentsRequest.file_names_and_uuid:type_name -> api_container_api.FilesArtifactNameAndUuid - 13, // 4: kurtosis_enclave_manager.DownloadFilesArtifactRequest.download_files_artifacts_args:type_name -> api_container_api.DownloadFilesArtifactArgs - 1, // 5: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.Check:input_type -> kurtosis_enclave_manager.HealthCheckRequest - 14, // 6: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetEnclaves:input_type -> google.protobuf.Empty - 3, // 7: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetServices:input_type -> kurtosis_enclave_manager.GetServicesRequest - 15, // 8: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetServiceLogs:input_type -> engine_api.GetServiceLogsArgs - 4, // 9: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.ListFilesArtifactNamesAndUuids:input_type -> kurtosis_enclave_manager.GetListFilesArtifactNamesAndUuidsRequest - 5, // 10: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.RunStarlarkPackage:input_type -> kurtosis_enclave_manager.RunStarlarkPackageRequest - 6, // 11: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.RunStarlarkScript:input_type -> kurtosis_enclave_manager.RunStarlarkScriptRequest - 16, // 12: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.CreateEnclave:input_type -> engine_api.CreateEnclaveArgs - 7, // 13: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.InspectFilesArtifactContents:input_type -> kurtosis_enclave_manager.InspectFilesArtifactContentsRequest - 8, // 14: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.DownloadFilesArtifact:input_type -> kurtosis_enclave_manager.DownloadFilesArtifactRequest - 17, // 15: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.DestroyEnclave:input_type -> engine_api.DestroyEnclaveArgs - 9, // 16: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkRun:input_type -> kurtosis_enclave_manager.GetStarlarkRunRequest - 2, // 17: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.Check:output_type -> kurtosis_enclave_manager.HealthCheckResponse - 18, // 18: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetEnclaves:output_type -> engine_api.GetEnclavesResponse - 19, // 19: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetServices:output_type -> api_container_api.GetServicesResponse - 20, // 20: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetServiceLogs:output_type -> engine_api.GetServiceLogsResponse - 21, // 21: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.ListFilesArtifactNamesAndUuids:output_type -> api_container_api.ListFilesArtifactNamesAndUuidsResponse - 22, // 22: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.RunStarlarkPackage:output_type -> api_container_api.StarlarkRunResponseLine - 22, // 23: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.RunStarlarkScript:output_type -> api_container_api.StarlarkRunResponseLine - 23, // 24: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.CreateEnclave:output_type -> engine_api.CreateEnclaveResponse - 24, // 25: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.InspectFilesArtifactContents:output_type -> api_container_api.InspectFilesArtifactContentsResponse - 25, // 26: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.DownloadFilesArtifact:output_type -> api_container_api.StreamedDataChunk - 14, // 27: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.DestroyEnclave:output_type -> google.protobuf.Empty - 26, // 28: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkRun:output_type -> api_container_api.GetStarlarkRunResponse - 17, // [17:29] is the sub-list for method output_type - 5, // [5:17] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name + 12, // 1: kurtosis_enclave_manager.RunStarlarkPackageRequest.RunStarlarkPackageArgs:type_name -> api_container_api.RunStarlarkPackageArgs + 13, // 2: kurtosis_enclave_manager.RunStarlarkScriptRequest.RunStarlarkScriptArgs:type_name -> api_container_api.RunStarlarkScriptArgs + 14, // 3: kurtosis_enclave_manager.InspectFilesArtifactContentsRequest.file_names_and_uuid:type_name -> api_container_api.FilesArtifactNameAndUuid + 15, // 4: kurtosis_enclave_manager.DownloadFilesArtifactRequest.download_files_artifacts_args:type_name -> api_container_api.DownloadFilesArtifactArgs + 16, // 5: kurtosis_enclave_manager.StarlarkScriptPlanYamlArgs.starlark_script_plan_yaml_args:type_name -> api_container_api.StarlarkScriptPlanYamlArgs + 17, // 6: kurtosis_enclave_manager.StarlarkPackagePlanYamlArgs.starlark_package_plan_yaml_args:type_name -> api_container_api.StarlarkPackagePlanYamlArgs + 1, // 7: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.Check:input_type -> kurtosis_enclave_manager.HealthCheckRequest + 18, // 8: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetEnclaves:input_type -> google.protobuf.Empty + 3, // 9: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetServices:input_type -> kurtosis_enclave_manager.GetServicesRequest + 19, // 10: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetServiceLogs:input_type -> engine_api.GetServiceLogsArgs + 4, // 11: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.ListFilesArtifactNamesAndUuids:input_type -> kurtosis_enclave_manager.GetListFilesArtifactNamesAndUuidsRequest + 5, // 12: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.RunStarlarkPackage:input_type -> kurtosis_enclave_manager.RunStarlarkPackageRequest + 6, // 13: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.RunStarlarkScript:input_type -> kurtosis_enclave_manager.RunStarlarkScriptRequest + 20, // 14: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.CreateEnclave:input_type -> engine_api.CreateEnclaveArgs + 7, // 15: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.InspectFilesArtifactContents:input_type -> kurtosis_enclave_manager.InspectFilesArtifactContentsRequest + 8, // 16: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.DownloadFilesArtifact:input_type -> kurtosis_enclave_manager.DownloadFilesArtifactRequest + 21, // 17: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.DestroyEnclave:input_type -> engine_api.DestroyEnclaveArgs + 9, // 18: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkRun:input_type -> kurtosis_enclave_manager.GetStarlarkRunRequest + 10, // 19: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkScriptPlanYaml:input_type -> kurtosis_enclave_manager.StarlarkScriptPlanYamlArgs + 11, // 20: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkPackagePlanYaml:input_type -> kurtosis_enclave_manager.StarlarkPackagePlanYamlArgs + 2, // 21: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.Check:output_type -> kurtosis_enclave_manager.HealthCheckResponse + 22, // 22: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetEnclaves:output_type -> engine_api.GetEnclavesResponse + 23, // 23: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetServices:output_type -> api_container_api.GetServicesResponse + 24, // 24: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetServiceLogs:output_type -> engine_api.GetServiceLogsResponse + 25, // 25: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.ListFilesArtifactNamesAndUuids:output_type -> api_container_api.ListFilesArtifactNamesAndUuidsResponse + 26, // 26: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.RunStarlarkPackage:output_type -> api_container_api.StarlarkRunResponseLine + 26, // 27: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.RunStarlarkScript:output_type -> api_container_api.StarlarkRunResponseLine + 27, // 28: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.CreateEnclave:output_type -> engine_api.CreateEnclaveResponse + 28, // 29: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.InspectFilesArtifactContents:output_type -> api_container_api.InspectFilesArtifactContentsResponse + 29, // 30: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.DownloadFilesArtifact:output_type -> api_container_api.StreamedDataChunk + 18, // 31: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.DestroyEnclave:output_type -> google.protobuf.Empty + 30, // 32: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkRun:output_type -> api_container_api.GetStarlarkRunResponse + 31, // 33: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkScriptPlanYaml:output_type -> api_container_api.PlanYaml + 31, // 34: kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkPackagePlanYaml:output_type -> api_container_api.PlanYaml + 21, // [21:35] is the sub-list for method output_type + 7, // [7:21] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_kurtosis_enclave_manager_api_proto_init() } @@ -970,6 +1154,30 @@ func file_kurtosis_enclave_manager_api_proto_init() { return nil } } + file_kurtosis_enclave_manager_api_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StarlarkScriptPlanYamlArgs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_kurtosis_enclave_manager_api_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StarlarkPackagePlanYamlArgs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -977,7 +1185,7 @@ func file_kurtosis_enclave_manager_api_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_kurtosis_enclave_manager_api_proto_rawDesc, NumEnums: 1, - NumMessages: 9, + NumMessages: 11, NumExtensions: 0, NumServices: 1, }, diff --git a/enclave-manager/api/golang/kurtosis_enclave_manager_api_bindings/kurtosis_enclave_manager_api_bindingsconnect/kurtosis_enclave_manager_api.connect.go b/enclave-manager/api/golang/kurtosis_enclave_manager_api_bindings/kurtosis_enclave_manager_api_bindingsconnect/kurtosis_enclave_manager_api.connect.go index e51bade598..d5ae26ed0f 100644 --- a/enclave-manager/api/golang/kurtosis_enclave_manager_api_bindings/kurtosis_enclave_manager_api_bindingsconnect/kurtosis_enclave_manager_api.connect.go +++ b/enclave-manager/api/golang/kurtosis_enclave_manager_api_bindings/kurtosis_enclave_manager_api_bindingsconnect/kurtosis_enclave_manager_api.connect.go @@ -73,6 +73,12 @@ const ( // KurtosisEnclaveManagerServerGetStarlarkRunProcedure is the fully-qualified name of the // KurtosisEnclaveManagerServer's GetStarlarkRun RPC. KurtosisEnclaveManagerServerGetStarlarkRunProcedure = "/kurtosis_enclave_manager.KurtosisEnclaveManagerServer/GetStarlarkRun" + // KurtosisEnclaveManagerServerGetStarlarkScriptPlanYamlProcedure is the fully-qualified name of the + // KurtosisEnclaveManagerServer's GetStarlarkScriptPlanYaml RPC. + KurtosisEnclaveManagerServerGetStarlarkScriptPlanYamlProcedure = "/kurtosis_enclave_manager.KurtosisEnclaveManagerServer/GetStarlarkScriptPlanYaml" + // KurtosisEnclaveManagerServerGetStarlarkPackagePlanYamlProcedure is the fully-qualified name of + // the KurtosisEnclaveManagerServer's GetStarlarkPackagePlanYaml RPC. + KurtosisEnclaveManagerServerGetStarlarkPackagePlanYamlProcedure = "/kurtosis_enclave_manager.KurtosisEnclaveManagerServer/GetStarlarkPackagePlanYaml" ) // KurtosisEnclaveManagerServerClient is a client for the @@ -90,6 +96,8 @@ type KurtosisEnclaveManagerServerClient interface { DownloadFilesArtifact(context.Context, *connect.Request[kurtosis_enclave_manager_api_bindings.DownloadFilesArtifactRequest]) (*connect.ServerStreamForClient[kurtosis_core_rpc_api_bindings.StreamedDataChunk], error) DestroyEnclave(context.Context, *connect.Request[kurtosis_engine_rpc_api_bindings.DestroyEnclaveArgs]) (*connect.Response[emptypb.Empty], error) GetStarlarkRun(context.Context, *connect.Request[kurtosis_enclave_manager_api_bindings.GetStarlarkRunRequest]) (*connect.Response[kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse], error) + GetStarlarkScriptPlanYaml(context.Context, *connect.Request[kurtosis_enclave_manager_api_bindings.StarlarkScriptPlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) + GetStarlarkPackagePlanYaml(context.Context, *connect.Request[kurtosis_enclave_manager_api_bindings.StarlarkPackagePlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) } // NewKurtosisEnclaveManagerServerClient constructs a client for the @@ -163,6 +171,16 @@ func NewKurtosisEnclaveManagerServerClient(httpClient connect.HTTPClient, baseUR baseURL+KurtosisEnclaveManagerServerGetStarlarkRunProcedure, opts..., ), + getStarlarkScriptPlanYaml: connect.NewClient[kurtosis_enclave_manager_api_bindings.StarlarkScriptPlanYamlArgs, kurtosis_core_rpc_api_bindings.PlanYaml]( + httpClient, + baseURL+KurtosisEnclaveManagerServerGetStarlarkScriptPlanYamlProcedure, + opts..., + ), + getStarlarkPackagePlanYaml: connect.NewClient[kurtosis_enclave_manager_api_bindings.StarlarkPackagePlanYamlArgs, kurtosis_core_rpc_api_bindings.PlanYaml]( + httpClient, + baseURL+KurtosisEnclaveManagerServerGetStarlarkPackagePlanYamlProcedure, + opts..., + ), } } @@ -180,6 +198,8 @@ type kurtosisEnclaveManagerServerClient struct { downloadFilesArtifact *connect.Client[kurtosis_enclave_manager_api_bindings.DownloadFilesArtifactRequest, kurtosis_core_rpc_api_bindings.StreamedDataChunk] destroyEnclave *connect.Client[kurtosis_engine_rpc_api_bindings.DestroyEnclaveArgs, emptypb.Empty] getStarlarkRun *connect.Client[kurtosis_enclave_manager_api_bindings.GetStarlarkRunRequest, kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse] + getStarlarkScriptPlanYaml *connect.Client[kurtosis_enclave_manager_api_bindings.StarlarkScriptPlanYamlArgs, kurtosis_core_rpc_api_bindings.PlanYaml] + getStarlarkPackagePlanYaml *connect.Client[kurtosis_enclave_manager_api_bindings.StarlarkPackagePlanYamlArgs, kurtosis_core_rpc_api_bindings.PlanYaml] } // Check calls kurtosis_enclave_manager.KurtosisEnclaveManagerServer.Check. @@ -246,6 +266,18 @@ func (c *kurtosisEnclaveManagerServerClient) GetStarlarkRun(ctx context.Context, return c.getStarlarkRun.CallUnary(ctx, req) } +// GetStarlarkScriptPlanYaml calls +// kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkScriptPlanYaml. +func (c *kurtosisEnclaveManagerServerClient) GetStarlarkScriptPlanYaml(ctx context.Context, req *connect.Request[kurtosis_enclave_manager_api_bindings.StarlarkScriptPlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) { + return c.getStarlarkScriptPlanYaml.CallUnary(ctx, req) +} + +// GetStarlarkPackagePlanYaml calls +// kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkPackagePlanYaml. +func (c *kurtosisEnclaveManagerServerClient) GetStarlarkPackagePlanYaml(ctx context.Context, req *connect.Request[kurtosis_enclave_manager_api_bindings.StarlarkPackagePlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) { + return c.getStarlarkPackagePlanYaml.CallUnary(ctx, req) +} + // KurtosisEnclaveManagerServerHandler is an implementation of the // kurtosis_enclave_manager.KurtosisEnclaveManagerServer service. type KurtosisEnclaveManagerServerHandler interface { @@ -261,6 +293,8 @@ type KurtosisEnclaveManagerServerHandler interface { DownloadFilesArtifact(context.Context, *connect.Request[kurtosis_enclave_manager_api_bindings.DownloadFilesArtifactRequest], *connect.ServerStream[kurtosis_core_rpc_api_bindings.StreamedDataChunk]) error DestroyEnclave(context.Context, *connect.Request[kurtosis_engine_rpc_api_bindings.DestroyEnclaveArgs]) (*connect.Response[emptypb.Empty], error) GetStarlarkRun(context.Context, *connect.Request[kurtosis_enclave_manager_api_bindings.GetStarlarkRunRequest]) (*connect.Response[kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse], error) + GetStarlarkScriptPlanYaml(context.Context, *connect.Request[kurtosis_enclave_manager_api_bindings.StarlarkScriptPlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) + GetStarlarkPackagePlanYaml(context.Context, *connect.Request[kurtosis_enclave_manager_api_bindings.StarlarkPackagePlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) } // NewKurtosisEnclaveManagerServerHandler builds an HTTP handler from the service implementation. It @@ -329,6 +363,16 @@ func NewKurtosisEnclaveManagerServerHandler(svc KurtosisEnclaveManagerServerHand svc.GetStarlarkRun, opts..., ) + kurtosisEnclaveManagerServerGetStarlarkScriptPlanYamlHandler := connect.NewUnaryHandler( + KurtosisEnclaveManagerServerGetStarlarkScriptPlanYamlProcedure, + svc.GetStarlarkScriptPlanYaml, + opts..., + ) + kurtosisEnclaveManagerServerGetStarlarkPackagePlanYamlHandler := connect.NewUnaryHandler( + KurtosisEnclaveManagerServerGetStarlarkPackagePlanYamlProcedure, + svc.GetStarlarkPackagePlanYaml, + opts..., + ) return "/kurtosis_enclave_manager.KurtosisEnclaveManagerServer/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case KurtosisEnclaveManagerServerCheckProcedure: @@ -355,6 +399,10 @@ func NewKurtosisEnclaveManagerServerHandler(svc KurtosisEnclaveManagerServerHand kurtosisEnclaveManagerServerDestroyEnclaveHandler.ServeHTTP(w, r) case KurtosisEnclaveManagerServerGetStarlarkRunProcedure: kurtosisEnclaveManagerServerGetStarlarkRunHandler.ServeHTTP(w, r) + case KurtosisEnclaveManagerServerGetStarlarkScriptPlanYamlProcedure: + kurtosisEnclaveManagerServerGetStarlarkScriptPlanYamlHandler.ServeHTTP(w, r) + case KurtosisEnclaveManagerServerGetStarlarkPackagePlanYamlProcedure: + kurtosisEnclaveManagerServerGetStarlarkPackagePlanYamlHandler.ServeHTTP(w, r) default: http.NotFound(w, r) } @@ -411,3 +459,11 @@ func (UnimplementedKurtosisEnclaveManagerServerHandler) DestroyEnclave(context.C func (UnimplementedKurtosisEnclaveManagerServerHandler) GetStarlarkRun(context.Context, *connect.Request[kurtosis_enclave_manager_api_bindings.GetStarlarkRunRequest]) (*connect.Response[kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse], error) { return nil, connect.NewError(connect.CodeUnimplemented, errors.New("kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkRun is not implemented")) } + +func (UnimplementedKurtosisEnclaveManagerServerHandler) GetStarlarkScriptPlanYaml(context.Context, *connect.Request[kurtosis_enclave_manager_api_bindings.StarlarkScriptPlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkScriptPlanYaml is not implemented")) +} + +func (UnimplementedKurtosisEnclaveManagerServerHandler) GetStarlarkPackagePlanYaml(context.Context, *connect.Request[kurtosis_enclave_manager_api_bindings.StarlarkPackagePlanYamlArgs]) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkPackagePlanYaml is not implemented")) +} diff --git a/enclave-manager/api/golang/kurtosis_enclave_manager_api_bindings/kurtosis_enclave_manager_api_grpc.pb.go b/enclave-manager/api/golang/kurtosis_enclave_manager_api_bindings/kurtosis_enclave_manager_api_grpc.pb.go index 8495d11622..229a14a55d 100644 --- a/enclave-manager/api/golang/kurtosis_enclave_manager_api_bindings/kurtosis_enclave_manager_api_grpc.pb.go +++ b/enclave-manager/api/golang/kurtosis_enclave_manager_api_bindings/kurtosis_enclave_manager_api_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.24.4 +// - protoc v4.25.2 // source: kurtosis_enclave_manager_api.proto package kurtosis_enclave_manager_api_bindings @@ -34,6 +34,8 @@ const ( KurtosisEnclaveManagerServer_DownloadFilesArtifact_FullMethodName = "/kurtosis_enclave_manager.KurtosisEnclaveManagerServer/DownloadFilesArtifact" KurtosisEnclaveManagerServer_DestroyEnclave_FullMethodName = "/kurtosis_enclave_manager.KurtosisEnclaveManagerServer/DestroyEnclave" KurtosisEnclaveManagerServer_GetStarlarkRun_FullMethodName = "/kurtosis_enclave_manager.KurtosisEnclaveManagerServer/GetStarlarkRun" + KurtosisEnclaveManagerServer_GetStarlarkScriptPlanYaml_FullMethodName = "/kurtosis_enclave_manager.KurtosisEnclaveManagerServer/GetStarlarkScriptPlanYaml" + KurtosisEnclaveManagerServer_GetStarlarkPackagePlanYaml_FullMethodName = "/kurtosis_enclave_manager.KurtosisEnclaveManagerServer/GetStarlarkPackagePlanYaml" ) // KurtosisEnclaveManagerServerClient is the client API for KurtosisEnclaveManagerServer service. @@ -52,6 +54,8 @@ type KurtosisEnclaveManagerServerClient interface { DownloadFilesArtifact(ctx context.Context, in *DownloadFilesArtifactRequest, opts ...grpc.CallOption) (KurtosisEnclaveManagerServer_DownloadFilesArtifactClient, error) DestroyEnclave(ctx context.Context, in *kurtosis_engine_rpc_api_bindings.DestroyEnclaveArgs, opts ...grpc.CallOption) (*emptypb.Empty, error) GetStarlarkRun(ctx context.Context, in *GetStarlarkRunRequest, opts ...grpc.CallOption) (*kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse, error) + GetStarlarkScriptPlanYaml(ctx context.Context, in *StarlarkScriptPlanYamlArgs, opts ...grpc.CallOption) (*kurtosis_core_rpc_api_bindings.PlanYaml, error) + GetStarlarkPackagePlanYaml(ctx context.Context, in *StarlarkPackagePlanYamlArgs, opts ...grpc.CallOption) (*kurtosis_core_rpc_api_bindings.PlanYaml, error) } type kurtosisEnclaveManagerServerClient struct { @@ -262,6 +266,24 @@ func (c *kurtosisEnclaveManagerServerClient) GetStarlarkRun(ctx context.Context, return out, nil } +func (c *kurtosisEnclaveManagerServerClient) GetStarlarkScriptPlanYaml(ctx context.Context, in *StarlarkScriptPlanYamlArgs, opts ...grpc.CallOption) (*kurtosis_core_rpc_api_bindings.PlanYaml, error) { + out := new(kurtosis_core_rpc_api_bindings.PlanYaml) + err := c.cc.Invoke(ctx, KurtosisEnclaveManagerServer_GetStarlarkScriptPlanYaml_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *kurtosisEnclaveManagerServerClient) GetStarlarkPackagePlanYaml(ctx context.Context, in *StarlarkPackagePlanYamlArgs, opts ...grpc.CallOption) (*kurtosis_core_rpc_api_bindings.PlanYaml, error) { + out := new(kurtosis_core_rpc_api_bindings.PlanYaml) + err := c.cc.Invoke(ctx, KurtosisEnclaveManagerServer_GetStarlarkPackagePlanYaml_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // KurtosisEnclaveManagerServerServer is the server API for KurtosisEnclaveManagerServer service. // All implementations should embed UnimplementedKurtosisEnclaveManagerServerServer // for forward compatibility @@ -278,6 +300,8 @@ type KurtosisEnclaveManagerServerServer interface { DownloadFilesArtifact(*DownloadFilesArtifactRequest, KurtosisEnclaveManagerServer_DownloadFilesArtifactServer) error DestroyEnclave(context.Context, *kurtosis_engine_rpc_api_bindings.DestroyEnclaveArgs) (*emptypb.Empty, error) GetStarlarkRun(context.Context, *GetStarlarkRunRequest) (*kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse, error) + GetStarlarkScriptPlanYaml(context.Context, *StarlarkScriptPlanYamlArgs) (*kurtosis_core_rpc_api_bindings.PlanYaml, error) + GetStarlarkPackagePlanYaml(context.Context, *StarlarkPackagePlanYamlArgs) (*kurtosis_core_rpc_api_bindings.PlanYaml, error) } // UnimplementedKurtosisEnclaveManagerServerServer should be embedded to have forward compatible implementations. @@ -320,6 +344,12 @@ func (UnimplementedKurtosisEnclaveManagerServerServer) DestroyEnclave(context.Co func (UnimplementedKurtosisEnclaveManagerServerServer) GetStarlarkRun(context.Context, *GetStarlarkRunRequest) (*kurtosis_core_rpc_api_bindings.GetStarlarkRunResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetStarlarkRun not implemented") } +func (UnimplementedKurtosisEnclaveManagerServerServer) GetStarlarkScriptPlanYaml(context.Context, *StarlarkScriptPlanYamlArgs) (*kurtosis_core_rpc_api_bindings.PlanYaml, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetStarlarkScriptPlanYaml not implemented") +} +func (UnimplementedKurtosisEnclaveManagerServerServer) GetStarlarkPackagePlanYaml(context.Context, *StarlarkPackagePlanYamlArgs) (*kurtosis_core_rpc_api_bindings.PlanYaml, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetStarlarkPackagePlanYaml not implemented") +} // UnsafeKurtosisEnclaveManagerServerServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to KurtosisEnclaveManagerServerServer will @@ -560,6 +590,42 @@ func _KurtosisEnclaveManagerServer_GetStarlarkRun_Handler(srv interface{}, ctx c return interceptor(ctx, in, info, handler) } +func _KurtosisEnclaveManagerServer_GetStarlarkScriptPlanYaml_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StarlarkScriptPlanYamlArgs) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KurtosisEnclaveManagerServerServer).GetStarlarkScriptPlanYaml(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: KurtosisEnclaveManagerServer_GetStarlarkScriptPlanYaml_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KurtosisEnclaveManagerServerServer).GetStarlarkScriptPlanYaml(ctx, req.(*StarlarkScriptPlanYamlArgs)) + } + return interceptor(ctx, in, info, handler) +} + +func _KurtosisEnclaveManagerServer_GetStarlarkPackagePlanYaml_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StarlarkPackagePlanYamlArgs) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KurtosisEnclaveManagerServerServer).GetStarlarkPackagePlanYaml(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: KurtosisEnclaveManagerServer_GetStarlarkPackagePlanYaml_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KurtosisEnclaveManagerServerServer).GetStarlarkPackagePlanYaml(ctx, req.(*StarlarkPackagePlanYamlArgs)) + } + return interceptor(ctx, in, info, handler) +} + // KurtosisEnclaveManagerServer_ServiceDesc is the grpc.ServiceDesc for KurtosisEnclaveManagerServer service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -599,6 +665,14 @@ var KurtosisEnclaveManagerServer_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetStarlarkRun", Handler: _KurtosisEnclaveManagerServer_GetStarlarkRun_Handler, }, + { + MethodName: "GetStarlarkScriptPlanYaml", + Handler: _KurtosisEnclaveManagerServer_GetStarlarkScriptPlanYaml_Handler, + }, + { + MethodName: "GetStarlarkPackagePlanYaml", + Handler: _KurtosisEnclaveManagerServer_GetStarlarkPackagePlanYaml_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/enclave-manager/api/protobuf/kurtosis_enclave_manager_api.proto b/enclave-manager/api/protobuf/kurtosis_enclave_manager_api.proto index 76a9512bf4..97fe2a0a15 100644 --- a/enclave-manager/api/protobuf/kurtosis_enclave_manager_api.proto +++ b/enclave-manager/api/protobuf/kurtosis_enclave_manager_api.proto @@ -21,6 +21,8 @@ service KurtosisEnclaveManagerServer { rpc DownloadFilesArtifact(DownloadFilesArtifactRequest) returns (stream api_container_api.StreamedDataChunk) {}; rpc DestroyEnclave(engine_api.DestroyEnclaveArgs) returns (google.protobuf.Empty) {}; rpc GetStarlarkRun(GetStarlarkRunRequest) returns (api_container_api.GetStarlarkRunResponse) {}; + rpc GetStarlarkScriptPlanYaml(StarlarkScriptPlanYamlArgs) returns (api_container_api.PlanYaml) {}; + rpc GetStarlarkPackagePlanYaml(StarlarkPackagePlanYamlArgs) returns (api_container_api.PlanYaml) {}; } message HealthCheckRequest { @@ -75,3 +77,20 @@ message GetStarlarkRunRequest{ string apic_ip_address = 1; int32 apic_port = 2; } + + +// ============================================================================================== +// Get Starlark Plan Yaml +// ============================================================================================== +message StarlarkScriptPlanYamlArgs { + string apic_ip_address = 1; + int32 apic_port = 2; + + api_container_api.StarlarkScriptPlanYamlArgs starlark_script_plan_yaml_args = 3; +} + +message StarlarkPackagePlanYamlArgs { + string apic_ip_address = 1; + int32 apic_port = 2; + api_container_api.StarlarkPackagePlanYamlArgs starlark_package_plan_yaml_args = 3; +} \ No newline at end of file diff --git a/enclave-manager/api/typescript/src/kurtosis_enclave_manager_api_connect.ts b/enclave-manager/api/typescript/src/kurtosis_enclave_manager_api_connect.ts index 9f53d33c27..8db61a99a1 100644 --- a/enclave-manager/api/typescript/src/kurtosis_enclave_manager_api_connect.ts +++ b/enclave-manager/api/typescript/src/kurtosis_enclave_manager_api_connect.ts @@ -1,12 +1,12 @@ -// @generated by protoc-gen-connect-es v0.13.2 with parameter "target=ts" +// @generated by protoc-gen-connect-es v1.3.0 with parameter "target=ts" // @generated from file kurtosis_enclave_manager_api.proto (package kurtosis_enclave_manager, syntax proto3) /* eslint-disable */ // @ts-nocheck -import { DownloadFilesArtifactRequest, GetListFilesArtifactNamesAndUuidsRequest, GetServicesRequest, GetStarlarkRunRequest, HealthCheckRequest, HealthCheckResponse, InspectFilesArtifactContentsRequest, RunStarlarkPackageRequest, RunStarlarkScriptRequest } from "./kurtosis_enclave_manager_api_pb.js"; +import { DownloadFilesArtifactRequest, GetListFilesArtifactNamesAndUuidsRequest, GetServicesRequest, GetStarlarkRunRequest, HealthCheckRequest, HealthCheckResponse, InspectFilesArtifactContentsRequest, RunStarlarkPackageRequest, RunStarlarkScriptRequest, StarlarkPackagePlanYamlArgs, StarlarkScriptPlanYamlArgs } from "./kurtosis_enclave_manager_api_pb.js"; import { Empty, MethodKind } from "@bufbuild/protobuf"; import { CreateEnclaveArgs, CreateEnclaveResponse, DestroyEnclaveArgs, GetEnclavesResponse, GetServiceLogsArgs, GetServiceLogsResponse } from "./engine_service_pb.js"; -import { GetServicesResponse, GetStarlarkRunResponse, InspectFilesArtifactContentsResponse, ListFilesArtifactNamesAndUuidsResponse, StarlarkRunResponseLine, StreamedDataChunk } from "./api_container_service_pb.js"; +import { GetServicesResponse, GetStarlarkRunResponse, InspectFilesArtifactContentsResponse, ListFilesArtifactNamesAndUuidsResponse, PlanYaml, StarlarkRunResponseLine, StreamedDataChunk } from "./api_container_service_pb.js"; /** * @generated from service kurtosis_enclave_manager.KurtosisEnclaveManagerServer @@ -122,6 +122,24 @@ export const KurtosisEnclaveManagerServer = { O: GetStarlarkRunResponse, kind: MethodKind.Unary, }, + /** + * @generated from rpc kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkScriptPlanYaml + */ + getStarlarkScriptPlanYaml: { + name: "GetStarlarkScriptPlanYaml", + I: StarlarkScriptPlanYamlArgs, + O: PlanYaml, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc kurtosis_enclave_manager.KurtosisEnclaveManagerServer.GetStarlarkPackagePlanYaml + */ + getStarlarkPackagePlanYaml: { + name: "GetStarlarkPackagePlanYaml", + I: StarlarkPackagePlanYamlArgs, + O: PlanYaml, + kind: MethodKind.Unary, + }, } } as const; diff --git a/enclave-manager/api/typescript/src/kurtosis_enclave_manager_api_pb.ts b/enclave-manager/api/typescript/src/kurtosis_enclave_manager_api_pb.ts index 48ade988d6..af2407b0d3 100644 --- a/enclave-manager/api/typescript/src/kurtosis_enclave_manager_api_pb.ts +++ b/enclave-manager/api/typescript/src/kurtosis_enclave_manager_api_pb.ts @@ -1,11 +1,11 @@ -// @generated by protoc-gen-es v1.5.1 with parameter "target=ts" +// @generated by protoc-gen-es v1.3.1 with parameter "target=ts" // @generated from file kurtosis_enclave_manager_api.proto (package kurtosis_enclave_manager, syntax proto3) /* eslint-disable */ // @ts-nocheck import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; import { Message, proto3 } from "@bufbuild/protobuf"; -import { DownloadFilesArtifactArgs, FilesArtifactNameAndUuid, RunStarlarkPackageArgs, RunStarlarkScriptArgs } from "./api_container_service_pb.js"; +import { DownloadFilesArtifactArgs, FilesArtifactNameAndUuid, RunStarlarkPackageArgs, RunStarlarkScriptArgs, StarlarkPackagePlanYamlArgs as StarlarkPackagePlanYamlArgs$1, StarlarkScriptPlanYamlArgs as StarlarkScriptPlanYamlArgs$1 } from "./api_container_service_pb.js"; /** * @generated from message kurtosis_enclave_manager.HealthCheckRequest @@ -440,3 +440,105 @@ export class GetStarlarkRunRequest extends Message { } } +/** + * ============================================================================================== + * Get Starlark Plan Yaml + * ============================================================================================== + * + * @generated from message kurtosis_enclave_manager.StarlarkScriptPlanYamlArgs + */ +export class StarlarkScriptPlanYamlArgs extends Message { + /** + * @generated from field: string apic_ip_address = 1; + */ + apicIpAddress = ""; + + /** + * @generated from field: int32 apic_port = 2; + */ + apicPort = 0; + + /** + * @generated from field: api_container_api.StarlarkScriptPlanYamlArgs starlark_script_plan_yaml_args = 3; + */ + starlarkScriptPlanYamlArgs?: StarlarkScriptPlanYamlArgs$1; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "kurtosis_enclave_manager.StarlarkScriptPlanYamlArgs"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "apic_ip_address", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "apic_port", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + { no: 3, name: "starlark_script_plan_yaml_args", kind: "message", T: StarlarkScriptPlanYamlArgs$1 }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): StarlarkScriptPlanYamlArgs { + return new StarlarkScriptPlanYamlArgs().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): StarlarkScriptPlanYamlArgs { + return new StarlarkScriptPlanYamlArgs().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): StarlarkScriptPlanYamlArgs { + return new StarlarkScriptPlanYamlArgs().fromJsonString(jsonString, options); + } + + static equals(a: StarlarkScriptPlanYamlArgs | PlainMessage | undefined, b: StarlarkScriptPlanYamlArgs | PlainMessage | undefined): boolean { + return proto3.util.equals(StarlarkScriptPlanYamlArgs, a, b); + } +} + +/** + * @generated from message kurtosis_enclave_manager.StarlarkPackagePlanYamlArgs + */ +export class StarlarkPackagePlanYamlArgs extends Message { + /** + * @generated from field: string apic_ip_address = 1; + */ + apicIpAddress = ""; + + /** + * @generated from field: int32 apic_port = 2; + */ + apicPort = 0; + + /** + * @generated from field: api_container_api.StarlarkPackagePlanYamlArgs starlark_package_plan_yaml_args = 3; + */ + starlarkPackagePlanYamlArgs?: StarlarkPackagePlanYamlArgs$1; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "kurtosis_enclave_manager.StarlarkPackagePlanYamlArgs"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "apic_ip_address", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "apic_port", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, + { no: 3, name: "starlark_package_plan_yaml_args", kind: "message", T: StarlarkPackagePlanYamlArgs$1 }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): StarlarkPackagePlanYamlArgs { + return new StarlarkPackagePlanYamlArgs().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): StarlarkPackagePlanYamlArgs { + return new StarlarkPackagePlanYamlArgs().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): StarlarkPackagePlanYamlArgs { + return new StarlarkPackagePlanYamlArgs().fromJsonString(jsonString, options); + } + + static equals(a: StarlarkPackagePlanYamlArgs | PlainMessage | undefined, b: StarlarkPackagePlanYamlArgs | PlainMessage | undefined): boolean { + return proto3.util.equals(StarlarkPackagePlanYamlArgs, a, b); + } +} + diff --git a/enclave-manager/server/server.go b/enclave-manager/server/server.go index 5952e7a188..1b0c30f997 100644 --- a/enclave-manager/server/server.go +++ b/enclave-manager/server/server.go @@ -426,6 +426,77 @@ func (c *WebServer) GetStarlarkRun( return resp, nil } +func (c *WebServer) GetStarlarkScriptPlanYaml( + ctx context.Context, + req *connect.Request[kurtosis_enclave_manager_api_bindings.StarlarkScriptPlanYamlArgs], +) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) { + auth, err := c.ValidateRequestAuthorization(ctx, c.enforceAuth, req.Header()) + if err != nil { + return nil, stacktrace.Propagate(err, "Authentication attempt failed") + } + if !auth { + return nil, stacktrace.Propagate(err, "User not authorized") + } + apiContainerServiceClient, err := c.createAPICClient(req.Msg.ApicIpAddress, req.Msg.ApicPort) + if err != nil { + return nil, stacktrace.Propagate(err, "Failed to create the APIC client") + } + + request := &connect.Request[kurtosis_core_rpc_api_bindings.StarlarkScriptPlanYamlArgs]{ + Msg: &kurtosis_core_rpc_api_bindings.StarlarkScriptPlanYamlArgs{ + SerializedScript: req.Msg.StarlarkScriptPlanYamlArgs.SerializedScript, + SerializedParams: req.Msg.StarlarkScriptPlanYamlArgs.SerializedParams, + MainFunctionName: req.Msg.StarlarkScriptPlanYamlArgs.MainFunctionName, + }, + } + result, err := (*apiContainerServiceClient).GetStarlarkScriptPlanYaml(ctx, request) + if err != nil { + return nil, err + } + resp := &connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml]{ + Msg: &kurtosis_core_rpc_api_bindings.PlanYaml{ + PlanYaml: result.Msg.PlanYaml, + }, + } + return resp, nil +} + +func (c *WebServer) GetStarlarkPackagePlanYaml( + ctx context.Context, + req *connect.Request[kurtosis_enclave_manager_api_bindings.StarlarkPackagePlanYamlArgs], +) (*connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml], error) { + auth, err := c.ValidateRequestAuthorization(ctx, c.enforceAuth, req.Header()) + if err != nil { + return nil, stacktrace.Propagate(err, "Authentication attempt failed") + } + if !auth { + return nil, stacktrace.Propagate(err, "User not authorized") + } + apiContainerServiceClient, err := c.createAPICClient(req.Msg.ApicIpAddress, req.Msg.ApicPort) + if err != nil { + return nil, stacktrace.Propagate(err, "Failed to create the APIC client") + } + + request := &connect.Request[kurtosis_core_rpc_api_bindings.StarlarkPackagePlanYamlArgs]{ + Msg: &kurtosis_core_rpc_api_bindings.StarlarkPackagePlanYamlArgs{ + PackageId: req.Msg.StarlarkPackagePlanYamlArgs.PackageId, + SerializedParams: req.Msg.StarlarkPackagePlanYamlArgs.SerializedParams, + RelativePathToMainFile: req.Msg.StarlarkPackagePlanYamlArgs.RelativePathToMainFile, + MainFunctionName: req.Msg.StarlarkPackagePlanYamlArgs.MainFunctionName, + }, + } + result, err := (*apiContainerServiceClient).GetStarlarkPackagePlanYaml(ctx, request) + if err != nil { + return nil, err + } + resp := &connect.Response[kurtosis_core_rpc_api_bindings.PlanYaml]{ + Msg: &kurtosis_core_rpc_api_bindings.PlanYaml{ + PlanYaml: result.Msg.PlanYaml, + }, + } + return resp, nil +} + func (c *WebServer) createAPICClient( ip string, port int32, From 7fa27ed1b1ea56deff945a58f63ada5c5c1fe4e6 Mon Sep 17 00:00:00 2001 From: Tedi Mitiku Date: Wed, 13 Mar 2024 17:03:31 -0400 Subject: [PATCH 07/16] feat: support package nodes in enclave builder ui (#2283) ## Description THIS PR IS A COPY OF THIS PR: https://github.com/kurtosis-tech/kurtosis/pull/2250 The frontend PR was initially made off the backend PR branch. I merged the backend PR branch to main. Then merged the frontend PR into the backend PR branch. Now merging into main again. --------- Co-authored-by: Ben Gazzard --- enclave-manager/web/packages/app/package.json | 2 +- .../client/enclaveManager/KurtosisClient.ts | 28 +- .../configuration/PackageSelector.tsx | 193 ++++++++++ .../drawer/bodies/PackageSelectBody.tsx | 192 +--------- .../enclaveBuilder/EnclaveBuilderDrawer.tsx | 4 +- .../enclaveBuilder/KurtosisArtifactNode.tsx | 24 -- .../enclaveBuilder/KurtosisNode.tsx | 236 ------------ .../enclaveBuilder/KurtosisServiceNode.tsx | 145 -------- .../components/enclaveBuilder/Toolbar.tsx | 250 +++++++++++++ .../VariableContextProvider.tsx | 19 +- .../components/enclaveBuilder/Visualiser.tsx | 211 +---------- .../input/FileTreeArgumentInput.tsx | 9 +- .../enclaveBuilder/input/ImageConfigInput.tsx | 37 +- .../input/MentionStringArgumentInput.css | 9 +- .../input/MentionStringArgumentInput.tsx | 12 +- .../input/MountArtifactFileInput.tsx | 4 +- .../input/PortConfigurationInput.tsx | 3 +- .../input/SelectServiceInput.tsx | 24 ++ .../input/StoreConfigurationInput.tsx | 29 ++ .../modals/ConfigurePackageNodeModal.tsx | 95 +++++ .../enclaveBuilder/modals/EditFileModal.tsx | 22 +- .../nodes/KurtosisArtifactNode.tsx | 44 +++ .../enclaveBuilder/nodes/KurtosisExecNode.tsx | 100 +++++ .../enclaveBuilder/nodes/KurtosisNode.tsx | 333 +++++++++++++++++ .../nodes/KurtosisPackageNode.tsx | 341 ++++++++++++++++++ .../{ => nodes}/KurtosisPythonNode.tsx | 84 +++-- .../nodes/KurtosisServiceNode.tsx | 142 ++++++++ .../{ => nodes}/KurtosisShellNode.tsx | 89 +++-- .../components/enclaveBuilder/types.ts | 125 ++++++- .../components/enclaveBuilder/utils.ts | 285 ++++++++++----- .../components/form/BooleanArgumentInput.tsx | 6 +- .../components/form/DictArgumentInput.tsx | 12 +- .../components/form/IntegerArgumentInput.tsx | 2 +- .../components/form/KurtosisFormControl.tsx | 12 +- .../components/form/ListArgumentInput.tsx | 22 +- .../components/form/OptionArgumentInput.tsx | 3 +- .../components/form/SelectArgumentInput.tsx | 2 +- .../components/form/StringArgumentInput.tsx | 3 +- .../components/widgets/PortsSummary.tsx | 7 +- .../web/packages/components/package.json | 2 +- enclave-manager/web/yarn.lock | 8 +- 41 files changed, 2149 insertions(+), 1021 deletions(-) create mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/configuration/PackageSelector.tsx delete mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisArtifactNode.tsx delete mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisNode.tsx delete mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisServiceNode.tsx create mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/Toolbar.tsx create mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/SelectServiceInput.tsx create mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/StoreConfigurationInput.tsx create mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/modals/ConfigurePackageNodeModal.tsx create mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisArtifactNode.tsx create mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisExecNode.tsx create mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisNode.tsx create mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisPackageNode.tsx rename enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/{ => nodes}/KurtosisPythonNode.tsx (63%) create mode 100644 enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisServiceNode.tsx rename enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/{ => nodes}/KurtosisShellNode.tsx (55%) diff --git a/enclave-manager/web/packages/app/package.json b/enclave-manager/web/packages/app/package.json index 7fd8b5daec..0a8b790fab 100644 --- a/enclave-manager/web/packages/app/package.json +++ b/enclave-manager/web/packages/app/package.json @@ -9,7 +9,7 @@ "enclave-manager-sdk": "file:../../../api/typescript", "html-react-parser": "^4.2.2", "js-cookie": "^3.0.5", - "kurtosis-cloud-indexer-sdk": "^0.0.2", + "kurtosis-cloud-indexer-sdk": "^0.0.31", "kurtosis-ui-components": "0.88.5", "react-error-boundary": "^4.0.11", "react-hook-form": "^7.47.0", diff --git a/enclave-manager/web/packages/app/src/client/enclaveManager/KurtosisClient.ts b/enclave-manager/web/packages/app/src/client/enclaveManager/KurtosisClient.ts index 68074ecdab..bb84b06c6a 100644 --- a/enclave-manager/web/packages/app/src/client/enclaveManager/KurtosisClient.ts +++ b/enclave-manager/web/packages/app/src/client/enclaveManager/KurtosisClient.ts @@ -5,6 +5,7 @@ import { RunStarlarkPackageArgs, RunStarlarkScriptArgs, ServiceInfo, + StarlarkPackagePlanYamlArgs, } from "enclave-manager-sdk/build/api_container_service_pb"; import { CreateEnclaveArgs, @@ -24,6 +25,7 @@ import { InspectFilesArtifactContentsRequest, RunStarlarkPackageRequest, RunStarlarkScriptRequest, + StarlarkPackagePlanYamlArgs as StarlarkPackagePlanYamlArgsRequest, } from "enclave-manager-sdk/build/kurtosis_enclave_manager_api_pb"; import { assertDefined, asyncResult, isDefined, RemoveFunctions } from "kurtosis-ui-components"; import { EnclaveFullInfo } from "../../emui/enclaves/types"; @@ -184,15 +186,15 @@ export abstract class KurtosisClient { } async createEnclave( - enclaveName: string, - apiContainerLogLevel: string, + enclaveName?: string, + apiContainerLogLevel?: string, productionMode?: boolean, apiContainerVersionTag?: string, ) { return asyncResult(() => { const request = new CreateEnclaveArgs({ - enclaveName, - apiContainerLogLevel, + enclaveName: enclaveName || "", + apiContainerLogLevel: apiContainerLogLevel || "info", mode: productionMode ? EnclaveMode.PRODUCTION : EnclaveMode.TEST, apiContainerVersionTag: apiContainerVersionTag || "", }); @@ -237,4 +239,22 @@ export abstract class KurtosisClient { }); return this.client.runStarlarkScript(request, this.getHeaderOptions()); } + + async getStarlarkPackagePlanYaml( + apicInfo: RemoveFunctions, + packageId: string, + args: Record, + ) { + return asyncResult(() => { + const request = new StarlarkPackagePlanYamlArgsRequest({ + apicIpAddress: apicInfo.bridgeIpAddress, + apicPort: apicInfo.grpcPortInsideEnclave, + starlarkPackagePlanYamlArgs: new StarlarkPackagePlanYamlArgs({ + packageId: packageId, + serializedParams: JSON.stringify(args), + }), + }); + return this.client.getStarlarkPackagePlanYaml(request, this.getHeaderOptions()); + }); + } } diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/configuration/PackageSelector.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/configuration/PackageSelector.tsx new file mode 100644 index 0000000000..be0059a68c --- /dev/null +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/configuration/PackageSelector.tsx @@ -0,0 +1,193 @@ +import { SmallCloseIcon } from "@chakra-ui/icons"; +import { + Button, + Flex, + Icon, + Input, + InputGroup, + InputLeftElement, + InputRightElement, + Spinner, + Text, +} from "@chakra-ui/react"; +import { KurtosisPackage } from "kurtosis-cloud-indexer-sdk"; +import { + FindCommand, + isDefined, + KurtosisAlert, + KurtosisPackageCardHorizontal, + parsePackageUrl, + useKeyboardAction, + useSavedPackages, +} from "kurtosis-ui-components"; +import { debounce } from "lodash"; +import { ChangeEvent, useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { FiSearch } from "react-icons/fi"; +import { useCatalogContext } from "../../../catalog/CatalogContext"; + +type ExactMatchState = + | { type: "loading"; url: string } + | { type: "loaded"; package: KurtosisPackage } + | { type: "error"; error: string }; + +type PackageSelectorProps = { + onPackageSelected: (kurtosisPackage: KurtosisPackage) => void; +}; +export const PackageSelector = ({ onPackageSelected }: PackageSelectorProps) => { + const searchRef = useRef(null); + const [searchTerm, setSearchTerm] = useState(""); + + const [exactMatch, setExactMatch] = useState(); + const { catalog, getSinglePackage } = useCatalogContext(); + + const checkSinglePackageDebounced = useMemo( + () => + debounce( + async (packageName: string) => { + const singlePackageResult = await getSinglePackage(packageName); + if (singlePackageResult.isErr) { + setExactMatch({ type: "error", error: singlePackageResult.error }); + return; + } + if (isDefined(singlePackageResult.value.package)) { + setExactMatch({ type: "loaded", package: singlePackageResult.value.package }); + } + }, + 1000, + { trailing: true, leading: false }, + ), + [getSinglePackage], + ); + + const startCheckSinglePackage = useCallback( + async (packageName: string) => { + let isKurtosisPackageName = false; + try { + parsePackageUrl(packageName); + isKurtosisPackageName = true; + } catch (error: any) { + // This packageName isn't a kurtosis package url + } + if (isKurtosisPackageName) { + setExactMatch({ type: "loading", url: packageName }); + checkSinglePackageDebounced(packageName); + } else { + setExactMatch(undefined); + } + }, + [checkSinglePackageDebounced], + ); + + const searchResults = useMemo( + () => + catalog.map((catalog) => + catalog.packages.filter( + (kurtosisPackage) => kurtosisPackage.name.toLowerCase().indexOf(searchTerm.toLowerCase()) >= 0, + ), + ), + [catalog, searchTerm], + ); + + const { savedPackages } = useSavedPackages(); + + const handleSearchTermChange = async (e: ChangeEvent) => { + setSearchTerm(e.target.value); + }; + + useKeyboardAction(useMemo(() => ({ find: () => searchRef.current?.focus() }), [searchRef])); + + useEffect(() => { + startCheckSinglePackage(searchTerm); + }, [startCheckSinglePackage, searchTerm]); + + if (searchResults.isErr) { + return ; + } + + return ( + <> + + + + + + + {searchTerm.length > 0 ? ( + + ) : ( + + )} + + + {isDefined(exactMatch) && ( + + + Exact Match + + {exactMatch.type === "loading" && ( + + + Looking for a Kurtosis Package at {exactMatch.url} + + )} + {exactMatch.type === "loaded" && ( + onPackageSelected(exactMatch.package)} + /> + )} + {exactMatch.type === "error" && ( + + )} + + )} + {(searchTerm.length > 0 || savedPackages.length === 0) && ( + + + {searchTerm.length === 0 ? "All Packages" : "Search Results"} + + {searchResults.value.map((kurtosisPackage) => ( + onPackageSelected(kurtosisPackage)} + /> + ))} + + )} + {searchTerm.length === 0 && savedPackages.length > 0 && ( + + + Saved + + {savedPackages.map((kurtosisPackage) => ( + onPackageSelected(kurtosisPackage)} + /> + ))} + + All Packages + + {searchResults.value.map((kurtosisPackage) => ( + onPackageSelected(kurtosisPackage)} + /> + ))} + + )} + + ); +}; diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/configuration/drawer/bodies/PackageSelectBody.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/configuration/drawer/bodies/PackageSelectBody.tsx index 699e83c5d7..c02b7f5e19 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/configuration/drawer/bodies/PackageSelectBody.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/configuration/drawer/bodies/PackageSelectBody.tsx @@ -1,40 +1,9 @@ -import { SmallCloseIcon } from "@chakra-ui/icons"; -import { - Button, - DrawerBody, - DrawerFooter, - DrawerHeader, - Flex, - Icon, - Input, - InputGroup, - InputLeftElement, - InputRightElement, - Spinner, - Text, -} from "@chakra-ui/react"; +import { Button, DrawerBody, DrawerFooter, DrawerHeader, Flex, Text } from "@chakra-ui/react"; import { KurtosisPackage } from "kurtosis-cloud-indexer-sdk"; -import { - FindCommand, - isDefined, - KurtosisAlert, - KurtosisPackageCardHorizontal, - parsePackageUrl, - useKeyboardAction, - useSavedPackages, -} from "kurtosis-ui-components"; -import { debounce } from "lodash"; -import { ChangeEvent, useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { FiSearch } from "react-icons/fi"; -import { useCatalogContext } from "../../../../../catalog/CatalogContext"; +import { PackageSelector } from "../../PackageSelector"; import { DrawerExpandCollapseButton } from "../DrawerExpandCollapseButton"; import { DrawerSizes } from "../types"; -type ExactMatchState = - | { type: "loading"; url: string } - | { type: "loaded"; package: KurtosisPackage } - | { type: "error"; error: string }; - type PackageSelectBodyProps = { onPackageSelected: (kurtosisPackage: KurtosisPackage) => void; onClose: () => void; @@ -47,80 +16,6 @@ export const PackageSelectBody = ({ drawerSize, onDrawerSizeClick, }: PackageSelectBodyProps) => { - const searchRef = useRef(null); - const [searchTerm, setSearchTerm] = useState(""); - - const [exactMatch, setExactMatch] = useState(); - const { catalog, getSinglePackage } = useCatalogContext(); - - const checkSinglePackageDebounced = useMemo( - () => - debounce( - async (packageName: string) => { - const singlePackageResult = await getSinglePackage(packageName); - if (singlePackageResult.isErr) { - setExactMatch({ type: "error", error: singlePackageResult.error }); - return; - } - if (isDefined(singlePackageResult.value.package)) { - setExactMatch({ type: "loaded", package: singlePackageResult.value.package }); - } - }, - 1000, - { trailing: true, leading: false }, - ), - [getSinglePackage], - ); - - const startCheckSinglePackage = useCallback( - async (packageName: string) => { - let isKurtosisPackageName = false; - try { - parsePackageUrl(packageName); - isKurtosisPackageName = true; - } catch (error: any) { - // This packageName isn't a kurtosis package url - } - if (isKurtosisPackageName) { - setExactMatch({ type: "loading", url: packageName }); - checkSinglePackageDebounced(packageName); - } else { - setExactMatch(undefined); - } - }, - [checkSinglePackageDebounced], - ); - - const searchResults = useMemo( - () => - catalog.map((catalog) => - catalog.packages.filter( - (kurtosisPackage) => kurtosisPackage.name.toLowerCase().indexOf(searchTerm.toLowerCase()) >= 0, - ), - ), - [catalog, searchTerm], - ); - - const { savedPackages } = useSavedPackages(); - - const handleSearchTermChange = async (e: ChangeEvent) => { - setSearchTerm(e.target.value); - }; - - useKeyboardAction(useMemo(() => ({ find: () => searchRef.current?.focus() }), [searchRef])); - - useEffect(() => { - startCheckSinglePackage(searchTerm); - }, [startCheckSinglePackage, searchTerm]); - - if (searchResults.isErr) { - return ( - - - - ); - } - return ( <> @@ -130,88 +25,7 @@ export const PackageSelectBody = ({ - - - - - - - {searchTerm.length > 0 ? ( - - ) : ( - - )} - - - {isDefined(exactMatch) && ( - - - Exact Match - - {exactMatch.type === "loading" && ( - - - Looking for a Kurtosis Package at {exactMatch.url} - - )} - {exactMatch.type === "loaded" && ( - onPackageSelected(exactMatch.package)} - /> - )} - {exactMatch.type === "error" && ( - - )} - - )} - {(searchTerm.length > 0 || savedPackages.length === 0) && ( - - - {searchTerm.length === 0 ? "All Packages" : "Search Results"} - - {searchResults.value.map((kurtosisPackage) => ( - onPackageSelected(kurtosisPackage)} - /> - ))} - - )} - {searchTerm.length === 0 && savedPackages.length > 0 && ( - - - Saved - - {savedPackages.map((kurtosisPackage) => ( - onPackageSelected(kurtosisPackage)} - /> - ))} - - All Packages - - {searchResults.value.map((kurtosisPackage) => ( - onPackageSelected(kurtosisPackage)} - /> - ))} - - )} + diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/EnclaveBuilderDrawer.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/EnclaveBuilderDrawer.tsx index 1c4af19c5f..781622f5a1 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/EnclaveBuilderDrawer.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/EnclaveBuilderDrawer.tsx @@ -23,7 +23,7 @@ import { useEnclavesContext } from "../../EnclavesContext"; import { EnclaveFullInfo } from "../../types"; import { ViewStarlarkModal } from "./modals/ViewStarlarkModal"; import { KurtosisNodeData } from "./types"; -import { getInitialGraphStateFromEnclave, getNodeName } from "./utils"; +import { getInitialGraphStateFromEnclave } from "./utils"; import { useVariableContext, VariableContextProvider } from "./VariableContextProvider"; import { Visualiser, VisualiserImperativeAttributes } from "./Visualiser"; @@ -106,7 +106,7 @@ const EnclaveBuilderDrawerImpl = ({ () => Object.values(data) .filter((nodeData) => !nodeData.isValid) - .map((nodeData) => `${nodeData.type} ${getNodeName(nodeData)} has invalid data`), + .map((nodeData) => `${nodeData.type} ${nodeData.name} has invalid data`), [data], ); const [isLoading, setIsLoading] = useState(false); diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisArtifactNode.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisArtifactNode.tsx deleted file mode 100644 index 3cc2cc1871..0000000000 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisArtifactNode.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { memo } from "react"; -import { NodeProps } from "reactflow"; -import { KurtosisFormControl } from "../form/KurtosisFormControl"; -import { StringArgumentInput } from "../form/StringArgumentInput"; -import { FileTreeArgumentInput } from "./input/FileTreeArgumentInput"; -import { validateName } from "./input/validators"; -import { KurtosisNode } from "./KurtosisNode"; -import { KurtosisArtifactNodeData } from "./types"; - -export const KurtosisArtifactNode = memo( - ({ id, selected }: NodeProps) => { - return ( - - name={"artifactName"} label={"Artifact Name"} isRequired> - - - - - - - ); - }, - (oldProps, newProps) => oldProps.id === newProps.id && oldProps.selected === newProps.selected, -); diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisNode.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisNode.tsx deleted file mode 100644 index 60c27df1a2..0000000000 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisNode.tsx +++ /dev/null @@ -1,236 +0,0 @@ -import { Flex, Icon, IconButton, Text, useToken } from "@chakra-ui/react"; -import { isDefined } from "kurtosis-ui-components"; -import { debounce } from "lodash"; -import { FC, memo, PropsWithChildren, useCallback, useEffect, useMemo } from "react"; -import { DefaultValues, FormProvider, useForm } from "react-hook-form"; -import { FiCpu, FiFile, FiTerminal, FiTrash } from "react-icons/fi"; -import { RxCornerBottomRight } from "react-icons/rx"; -import { Handle, NodeResizeControl, Position, useReactFlow, useViewport } from "reactflow"; -import { KurtosisNodeData } from "./types"; -import { getNodeName } from "./utils"; -import { useVariableContext } from "./VariableContextProvider"; - -const colors: Record = { - service: "blue.900", - artifact: "yellow.900", - shell: "red.900", - python: "red.900", -}; - -export const nodeIcons: Record = { - service: FiCpu, - artifact: FiFile, - shell: FiTerminal, - python: FiTerminal, -}; - -const nodeTypeReadable: Record = { - service: "Service", - artifact: "Files", - shell: "Shell execution task", - python: "Python execution task", -}; - -type KurtosisNodeProps = PropsWithChildren<{ - id: string; - selected: boolean; - minWidth: number; - maxWidth: number; -}>; - -export const KurtosisNode = memo( - ({ id, selected, minWidth, maxWidth, children }: KurtosisNodeProps) => { - const { data } = useVariableContext(); - const nodeData = data[id] as DataType; - - if (!isDefined(nodeData)) { - return null; - } - - return ( - - id={id} - selected={selected} - minWidth={minWidth} - maxWidth={maxWidth} - nodeData={nodeData} - > - {children} - - ); - }, -); - -type KurtosisNodeImplProps = KurtosisNodeProps & { nodeData: DataType }; -const KurtosisNodeImpl = ({ - id, - nodeData, - selected, - minWidth, - maxWidth, - children, -}: KurtosisNodeImplProps) => { - const { updateData, removeData } = useVariableContext(); - const color = colors[nodeData.type]; - const chakraColor = useToken("colors", color); - const name = useMemo(() => getNodeName(nodeData), [nodeData]); - const formMethods = useForm({ - defaultValues: nodeData as DefaultValues, - mode: "onBlur", - shouldFocusError: false, - }); - - const { deleteElements } = useReactFlow(); - - const handleDeleteNode = (e: React.MouseEvent) => { - e.stopPropagation(); - e.preventDefault(); - deleteElements({ nodes: [{ id }] }); - removeData(id); - }; - - const handleChange = useMemo( - () => - debounce(async () => { - const isValid = await formMethods.trigger(); - updateData(id, { ...formMethods.getValues(), isValid }); - }, 500), - [updateData, formMethods, id], - ); - - useEffect(() => { - const watcher = formMethods.watch(handleChange); - return () => watcher.unsubscribe(); - }, [formMethods, handleChange]); - - if (!isDefined(nodeData)) { - return null; - } - - return ( - - - - - - - - - {children} - - - - ); -}; - -type ZoomAwareNodeContentProps = PropsWithChildren<{ - name: string; - type: KurtosisNodeData["type"]; - onDelete: (e: React.MouseEvent) => void; -}>; - -const ZoomAwareNodeContent = ({ name, type, onDelete, children }: ZoomAwareNodeContentProps) => { - const viewport = useViewport(); - return ( - - {children} - - ); -}; - -type ZoomAwareNodeContentImplProps = ZoomAwareNodeContentProps & { zoom: number }; - -const ZoomAwareNodeContentImpl = memo(({ name, type, onDelete, zoom, children }: ZoomAwareNodeContentImplProps) => { - const { zoomOut, zoomIn } = useReactFlow(); - const handleScroll = useCallback( - (e: React.WheelEvent) => { - if (e.currentTarget.scrollTop === 0 && e.deltaY < 0) { - zoomIn(); - } - if ( - Math.abs(e.currentTarget.scrollHeight - e.currentTarget.clientHeight - e.currentTarget.scrollTop) <= 1 && - e.deltaY > 0 - ) { - zoomOut(); - } - }, - [zoomOut, zoomIn], - ); - - if (zoom < 0.4) { - return ( - - - - {name || Unnamed} - - - ); - } - - return ( - <> - - - - {name || Unnamed} - - {nodeTypeReadable[type]} - - - } - colorScheme={"red"} - variant={"ghost"} - size={"sm"} - onClick={onDelete} - /> - - - {children} - - - ); -}); diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisServiceNode.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisServiceNode.tsx deleted file mode 100644 index 9afed72e56..0000000000 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisServiceNode.tsx +++ /dev/null @@ -1,145 +0,0 @@ -import { Flex, Tab, TabList, TabPanel, TabPanels, Tabs } from "@chakra-ui/react"; -import { isDefined } from "kurtosis-ui-components"; -import { memo } from "react"; -import { NodeProps } from "reactflow"; -import { BooleanArgumentInput } from "../form/BooleanArgumentInput"; -import { DictArgumentInput } from "../form/DictArgumentInput"; -import { IntegerArgumentInput } from "../form/IntegerArgumentInput"; -import { KurtosisFormControl } from "../form/KurtosisFormControl"; -import { ListArgumentInput } from "../form/ListArgumentInput"; -import { StringArgumentInput } from "../form/StringArgumentInput"; -import { KurtosisFormInputProps } from "../form/types"; -import { ImageConfigInput } from "./input/ImageConfigInput"; -import { MentionStringArgumentInput } from "./input/MentionStringArgumentInput"; -import { MountArtifactFileInput } from "./input/MountArtifactFileInput"; -import { PortConfigurationField } from "./input/PortConfigurationInput"; -import { validateName } from "./input/validators"; -import { KurtosisNode } from "./KurtosisNode"; -import { KurtosisFileMount, KurtosisPort, KurtosisServiceNodeData } from "./types"; -import { useVariableContext } from "./VariableContextProvider"; - -export const KurtosisServiceNode = memo( - ({ id, selected }: NodeProps) => { - const { data } = useVariableContext(); - const nodeData = data[id] as KurtosisServiceNodeData; - - if (!isDefined(nodeData)) { - return null; - } - - return ( - - - name={"serviceName"} label={"Service Name"} isRequired> - - - name={"image.image"} label={"Container Image"} isRequired> - - - - - - Environment - Ports - Files - Exec - - - - - name={"env"} label={"Environment Variables"}> - - name={"env"} - KeyFieldComponent={StringArgumentInput} - ValueFieldComponent={MentionStringArgumentInput} - /> - - - - name={"ports"} label={"Ports"}> - ({ - portName: "", - applicationProtocol: "", - transportProtocol: "TCP", - port: 0, - })} - /> - - - - - name={"files"} - label={"Files"} - helperText={"Choose where to mount artifacts on this services filesystem"} - > - ({ - mountPoint: "", - artifactName: "", - })} - /> - - - - - - name={"execStepEnabled"} - label={"Exec step enabled"} - isRequired - helperText={"Whether kurtosis should execute a command in this service once the service is ready."} - > - name={"execStepEnabled"} /> - - - name={"execStepCommand"} - label={"Command"} - isRequired={nodeData.execStepEnabled === "true"} - isDisabled={nodeData.execStepEnabled === "false"} - > - - - - name={"execStepAcceptableCodes"} - label={"Acceptable Exit Codes"} - isDisabled={nodeData.execStepEnabled === "false"} - helperText={ - "If the executed command returns a code not on this list starlark will fail. Defaults to [0]" - } - > - - FieldComponent={AcceptableCodeInput} - size={"sm"} - name={"execStepAcceptableCodes"} - createNewValue={() => ({ value: 0 })} - disabled={nodeData.execStepEnabled === "false"} - /> - - - - - - - ); - }, - (oldProps, newProps) => oldProps.id === newProps.id && oldProps.selected === newProps.selected, -); - -const AcceptableCodeInput = (props: KurtosisFormInputProps) => { - return ( - - {...props} - size={"sm"} - name={`${props.name as `execStepAcceptableCodes.${number}`}.value`} - /> - ); -}; diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/Toolbar.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/Toolbar.tsx new file mode 100644 index 0000000000..1c23d8f97f --- /dev/null +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/Toolbar.tsx @@ -0,0 +1,250 @@ +import { Box, Button, ButtonGroup, Icon } from "@chakra-ui/react"; +import Dagre from "@dagrejs/dagre"; +import { useCallback, useRef } from "react"; +import { FiShare2 } from "react-icons/fi"; +import { Edge, Node, useOnViewportChange, useReactFlow, XYPosition } from "reactflow"; +import { v4 as uuidv4 } from "uuid"; +import { nodeIcons } from "./nodes/KurtosisNode"; +import { useVariableContext } from "./VariableContextProvider"; + +const g = new Dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({})); +const getLayoutedElements = (nodes: Node[], edges: Edge[]) => { + if (nodes.length === 0) { + return { nodes, edges }; + } + g.setGraph({ rankdir: "LR", ranksep: 100 }); + + edges.forEach((edge) => g.setEdge(edge.source, edge.target)); + nodes.forEach((node) => + g.setNode(node.id, node as Node<{ label: string }, string | undefined> & { width?: number; height?: number }), + ); + + Dagre.layout(g); + + return { + nodes: nodes.map((node) => { + const { x, y } = g.node(node.id); + + return { ...node, position: { x, y } }; + }), + edges, + }; +}; + +export const Toolbar = () => { + const insertOffset = useRef(0); + const { updateData } = useVariableContext(); + const { fitView, getViewport, getNodes, getEdges, addNodes, setNodes, setEdges } = useReactFlow(); + + useOnViewportChange({ onEnd: () => (insertOffset.current = 1) }); + + const onLayout = useCallback(() => { + const nodes = getNodes(); + const edges = getEdges(); + const layouted = getLayoutedElements(nodes, edges); + + setNodes([...layouted.nodes]); + setEdges([...layouted.edges]); + + window.requestAnimationFrame(() => { + fitView(); + }); + }, [fitView, setEdges, setNodes, getEdges, getNodes]); + + const getNewNodePosition = (): XYPosition => { + const viewport = getViewport(); + insertOffset.current += 1; + return { x: -viewport.x + insertOffset.current * 20 + 400, y: -viewport.y + insertOffset.current * 20 }; + }; + + const handleAddServiceNode = () => { + const id = uuidv4(); + updateData(id, { + type: "service", + name: "", + image: { + image: "", + type: "image", + buildContextDir: "", + flakeLocationDir: "", + flakeOutput: "", + registry: "", + registryPassword: "", + registryUsername: "", + targetStage: "", + }, + ports: [], + env: [], + files: [], + cmd: "", + entrypoint: "", + isValid: false, + }); + addNodes({ + id, + position: getNewNodePosition(), + width: 650, + style: { width: "650px" }, + type: "serviceNode", + data: {}, + }); + }; + + const handleAddExecNode = () => { + const id = uuidv4(); + updateData(id, { + type: "exec", + name: "", + service: "", + command: "", + acceptableCodes: [], + isValid: false, + }); + addNodes({ + id, + position: getNewNodePosition(), + width: 650, + style: { width: "650px" }, + type: "execNode", + data: {}, + }); + }; + + const handleAddArtifactNode = () => { + const id = uuidv4(); + updateData(id, { type: "artifact", name: "", files: {}, isValid: false }); + addNodes({ + id, + position: getNewNodePosition(), + width: 400, + style: { width: "400px" }, + type: "artifactNode", + data: {}, + }); + }; + + const handleAddShellNode = () => { + const id = uuidv4(); + updateData(id, { + type: "shell", + name: "", + command: "", + image: { + image: "", + type: "image", + buildContextDir: "", + flakeLocationDir: "", + flakeOutput: "", + registry: "", + registryPassword: "", + registryUsername: "", + targetStage: "", + }, + env: [], + files: [], + store: [{ name: "", path: "" }], + wait_enabled: "true", + wait: "", + isValid: false, + }); + addNodes({ + id, + position: getNewNodePosition(), + width: 650, + style: { width: "650px" }, + type: "shellNode", + data: {}, + }); + }; + + const handleAddPythonNode = () => { + const id = uuidv4(); + updateData(id, { + type: "python", + name: "", + command: "", + packages: [], + image: { + image: "", + type: "image", + buildContextDir: "", + flakeLocationDir: "", + flakeOutput: "", + registry: "", + registryPassword: "", + registryUsername: "", + targetStage: "", + }, + args: [], + files: [], + store: [{ name: "", path: "" }], + wait_enabled: "true", + wait: "", + isValid: false, + }); + addNodes({ + id, + position: getNewNodePosition(), + width: 650, + style: { width: "650px" }, + type: "pythonNode", + data: {}, + }); + }; + + const handleAddPackageNode = () => { + const id = uuidv4(); + updateData(id, { + type: "package", + name: "", + packageId: "", + args: {}, + locator: "", + isValid: false, + }); + addNodes({ + id, + position: getNewNodePosition(), + width: 900, + style: { width: "900px" }, + type: "packageNode", + data: {}, + }); + }; + + return ( + + + + + + + + + + + + ); +}; diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/VariableContextProvider.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/VariableContextProvider.tsx index f071f4f782..a696ed1526 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/VariableContextProvider.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/VariableContextProvider.tsx @@ -5,8 +5,8 @@ import { getVariablesFromNodes } from "./utils"; type VariableContextState = { data: Record; variables: Variable[]; - updateData: (id: string, data: KurtosisNodeData) => void; - removeData: (id: string) => void; + updateData: (id: string, data: KurtosisNodeData | ((oldData: KurtosisNodeData) => KurtosisNodeData)) => void; + removeData: (id: { id: string }[]) => void; }; const VariableContext = createContext({ @@ -27,14 +27,19 @@ export const VariableContextProvider = ({ initialData, children }: PropsWithChil return getVariablesFromNodes(data); }, [data]); - const updateData = useCallback((id: string, data: KurtosisNodeData) => { - setData((oldData) => ({ ...oldData, [id]: data })); - }, []); + const updateData = useCallback( + (id: string, data: KurtosisNodeData | ((oldData: KurtosisNodeData) => KurtosisNodeData)) => { + setData((oldData) => ({ ...oldData, [id]: typeof data === "object" ? data : data(oldData[id]) })); + }, + [], + ); - const removeData = useCallback((id: string) => { + const removeData = useCallback((ids: { id: string }[]) => { setData((oldData) => { const r = { ...oldData }; - delete r[id]; + for (const { id } of ids) { + delete r[id]; + } return r; }); }, []); diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/Visualiser.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/Visualiser.tsx index 73c0767588..c255ba2585 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/Visualiser.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/Visualiser.tsx @@ -1,8 +1,6 @@ -import { Box, Button, ButtonGroup, Flex, Icon } from "@chakra-ui/react"; -import Dagre from "@dagrejs/dagre"; +import { Box, Flex } from "@chakra-ui/react"; import { RemoveFunctions } from "kurtosis-ui-components"; import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from "react"; -import { FiShare2 } from "react-icons/fi"; import { Background, BackgroundVariant, @@ -13,48 +11,26 @@ import { useEdgesState, useNodesState, useReactFlow, - XYPosition, } from "reactflow"; -import { v4 as uuidv4 } from "uuid"; import { EnclaveFullInfo } from "../../types"; -import { KurtosisArtifactNode } from "./KurtosisArtifactNode"; -import { nodeIcons } from "./KurtosisNode"; -import { KurtosisPythonNode } from "./KurtosisPythonNode"; -import { KurtosisServiceNode } from "./KurtosisServiceNode"; -import { KurtosisShellNode } from "./KurtosisShellNode"; +import { KurtosisArtifactNode } from "./nodes/KurtosisArtifactNode"; +import { KurtosisExecNode } from "./nodes/KurtosisExecNode"; +import { KurtosisPackageNode } from "./nodes/KurtosisPackageNode"; +import { KurtosisPythonNode } from "./nodes/KurtosisPythonNode"; +import { KurtosisServiceNode } from "./nodes/KurtosisServiceNode"; +import { KurtosisShellNode } from "./nodes/KurtosisShellNode"; +import { Toolbar } from "./Toolbar"; import { generateStarlarkFromGraph, getNodeDependencies } from "./utils"; import { useVariableContext } from "./VariableContextProvider"; import "./Visualiser.css"; -const g = new Dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({})); -const getLayoutedElements = (nodes: Node[], edges: Edge[]) => { - if (nodes.length === 0) { - return { nodes, edges }; - } - g.setGraph({ rankdir: "LR", ranksep: 100 }); - - edges.forEach((edge) => g.setEdge(edge.source, edge.target)); - nodes.forEach((node) => - g.setNode(node.id, node as Node<{ label: string }, string | undefined> & { width?: number; height?: number }), - ); - - Dagre.layout(g); - - return { - nodes: nodes.map((node) => { - const { x, y } = g.node(node.id); - - return { ...node, position: { x, y } }; - }), - edges, - }; -}; - const nodeTypes = { serviceNode: KurtosisServiceNode, + execNode: KurtosisExecNode, artifactNode: KurtosisArtifactNode, shellNode: KurtosisShellNode, pythonNode: KurtosisPythonNode, + packageNode: KurtosisPackageNode, }; export type VisualiserImperativeAttributes = { @@ -67,145 +43,12 @@ type VisualiserProps = { }; export const Visualiser = forwardRef( ({ initialNodes, initialEdges, existingEnclave }, ref) => { - const { data, updateData } = useVariableContext(); + const { data } = useVariableContext(); const insertOffset = useRef(0); - const { fitView, addNodes, getViewport } = useReactFlow(); - const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes || []); + const { fitView } = useReactFlow(); + const [nodes, , onNodesChange] = useNodesState(initialNodes || []); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges || []); - const onLayout = useCallback(() => { - const layouted = getLayoutedElements(nodes, edges); - - setNodes([...layouted.nodes]); - setEdges([...layouted.edges]); - - window.requestAnimationFrame(() => { - fitView(); - }); - }, [nodes, edges, fitView, setEdges, setNodes]); - - const getNewNodePosition = (): XYPosition => { - const viewport = getViewport(); - insertOffset.current += 1; - return { x: -viewport.x + insertOffset.current * 20 + 400, y: -viewport.y + insertOffset.current * 20 }; - }; - - const handleAddServiceNode = () => { - const id = uuidv4(); - updateData(id, { - type: "service", - serviceName: "", - image: { - image: "", - type: "image", - buildContextDir: "", - flakeLocationDir: "", - flakeOutput: "", - registry: "", - registryPassword: "", - registryUsername: "", - targetStage: "", - }, - ports: [], - env: [], - files: [], - execStepEnabled: "false", - execStepCommand: "", - execStepAcceptableCodes: [], - isValid: false, - }); - addNodes({ - id, - position: getNewNodePosition(), - width: 650, - style: { width: "650px" }, - type: "serviceNode", - data: {}, - }); - }; - - const handleAddArtifactNode = () => { - const id = uuidv4(); - updateData(id, { type: "artifact", artifactName: "", files: {}, isValid: false }); - addNodes({ - id, - position: getNewNodePosition(), - width: 400, - style: { width: "400px" }, - type: "artifactNode", - data: {}, - }); - }; - - const handleAddShellNode = () => { - const id = uuidv4(); - updateData(id, { - type: "shell", - shellName: "", - command: "", - image: { - image: "", - type: "image", - buildContextDir: "", - flakeLocationDir: "", - flakeOutput: "", - registry: "", - registryPassword: "", - registryUsername: "", - targetStage: "", - }, - env: [], - files: [], - store: "", - wait_enabled: "true", - wait: "", - isValid: false, - }); - addNodes({ - id, - position: getNewNodePosition(), - width: 650, - style: { width: "650px" }, - type: "shellNode", - data: {}, - }); - }; - - const handleAddPythonNode = () => { - const id = uuidv4(); - updateData(id, { - type: "python", - pythonName: "", - command: "", - packages: [], - image: { - image: "", - type: "image", - buildContextDir: "", - flakeLocationDir: "", - flakeOutput: "", - registry: "", - registryPassword: "", - registryUsername: "", - targetStage: "", - }, - args: [], - files: [], - store: "", - wait_enabled: "true", - wait: "", - isValid: false, - }); - addNodes({ - id, - position: getNewNodePosition(), - width: 650, - style: { width: "650px" }, - type: "pythonNode", - data: {}, - }); - }; - const handleNodeDoubleClick = useCallback( (e: React.MouseEvent, node: Node) => { fitView({ nodes: [node], maxZoom: 1, duration: 500 }); @@ -261,33 +104,7 @@ export const Visualiser = forwardRef - - - - - - - - - + ({ defaultValue={"" as any} rules={{ required: isRequired, validate: validate }} render={({ field, fieldState }) => { - return ; + return ; }} /> ); @@ -30,10 +30,11 @@ export const FileTreeArgumentInput = ({ type FileTreeInputProps = { files: Record; + isDisabled?: boolean; onUpdateFiles: (newFiles: Record) => void; }; -const FileTreeInput = ({ files, onUpdateFiles }: FileTreeInputProps) => { +const FileTreeInput = ({ files, isDisabled, onUpdateFiles }: FileTreeInputProps) => { const [selectedPath, setSelectedPath] = useState(); const [showNewFileInputDialog, setShowNewFileInputDialog] = useState(false); const [editingFilePath, setEditingFilePath] = useState(); @@ -94,7 +95,7 @@ const FileTreeInput = ({ files, onUpdateFiles }: FileTreeInputProps) => { return ( - + @@ -119,7 +120,7 @@ const FileTreeInput = ({ files, onUpdateFiles }: FileTreeInputProps) => { onClose={() => setEditingFilePath(undefined)} filePath={editingFilePath || []} file={files["/" + editingFilePath?.join("/")]} - onSave={handleSaveEditedFile} + onSave={isDisabled ? undefined : handleSaveEditedFile} /> ); diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/ImageConfigInput.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/ImageConfigInput.tsx index e144f21e55..24e17682d5 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/ImageConfigInput.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/ImageConfigInput.tsx @@ -34,7 +34,10 @@ const tabs: { display: string; value: KurtosisImageType }[] = [ { display: "Nix", value: "nix" }, ]; -export const ImageConfigInput = () => { +type ImageConfigInputProps = { + disabled?: boolean; +}; +export const ImageConfigInput = ({ disabled }: ImageConfigInputProps) => { const { setValue, watch } = useFormContext<{ image: KurtosisImageConfig }>(); const imageName = watch("image.image"); const imageType = watch("image.type"); @@ -42,17 +45,20 @@ export const ImageConfigInput = () => { const handleTabsChange = (newTabIndex: number) => { setActiveTabIndex(newTabIndex); - setValue("image.type", tabs[activeTabIndex].value); + if (!disabled) { + setValue("image.type", tabs[activeTabIndex].value); + } }; return ( - {tabs[activeTabIndex].display} + {tabs.find((t) => t.value === imageType)?.display || "Unknown"} @@ -87,28 +93,37 @@ export const ImageConfigInput = () => { size={"xs"} name={"image.username"} label={"Username"} + isDisabled={disabled} helperText={"The username that will be used to pull the image from the given registry"} > - + - + @@ -120,21 +135,24 @@ export const ImageConfigInput = () => { helperText={ "Locator to build context within the Kurtosis package. As of now, Kurtosis expects a Dockerfile at the root of the build context" } + isDisabled={disabled} isRequired={activeTabIndex === 1} > - + @@ -143,12 +161,14 @@ export const ImageConfigInput = () => { name={"image.buildContextDir"} label={"Build Context Dir"} helperText={"Locator to build context within the Kurtosis package."} + isDisabled={disabled} isRequired={activeTabIndex === 2} > @@ -159,12 +179,14 @@ export const ImageConfigInput = () => { helperText={ "The relative path (from the `build_context_dir`) to the folder containing the flake.nix file" } + isDisabled={disabled} isRequired={activeTabIndex === 2} > @@ -172,11 +194,12 @@ export const ImageConfigInput = () => { name={"image.flakeOutput"} label={"Flake Output"} size={"xs"} + isDisabled={disabled} helperText={ "The selector for the Flake output with the image derivation. Fallbacks to the default package." } > - + diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/MentionStringArgumentInput.css b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/MentionStringArgumentInput.css index 65a156a440..d2bcb7735a 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/MentionStringArgumentInput.css +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/MentionStringArgumentInput.css @@ -3,7 +3,7 @@ height: var(--input-height); font-size: var(--input-font-size); border: 1px solid; - border-color: inherit; + border-color: var(--chakra-colors-chakra-border-color); border-radius: var(--input-border-radius); outline: 2px solid transparent; outline-offset: 2px; @@ -14,8 +14,9 @@ --input-border-radius: var(--chakra-radii-sm); --input-height: var(--chakra-sizes-8); padding-top: 4px; + background-color: var(--chakra-colors-gray-850); - &[aria-invalid="true"] { + &:has(input[aria-invalid="true"]) { border-color: var(--chakra-colors-red-300); box-shadow: 0 0 0 1px var(--chakra-colors-red-300); } @@ -40,6 +41,10 @@ &:focus-visible { outline: none; } + + &[disabled=""] { + color: var(--chakra-colors-gray-200); + } } .mentions__suggestions__list { diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/MentionStringArgumentInput.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/MentionStringArgumentInput.tsx index f639361482..b90a5f55c2 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/MentionStringArgumentInput.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/MentionStringArgumentInput.tsx @@ -7,7 +7,9 @@ import { KurtosisFormInputProps } from "../../form/types"; import { useVariableContext } from "../VariableContextProvider"; import "./MentionStringArgumentInput.css"; -type MentionStringArgumentInputProps = KurtosisFormInputProps; +type MentionStringArgumentInputProps = KurtosisFormInputProps & { + multiline?: boolean; +}; export const MentionStringArgumentInput = ({ name, @@ -17,6 +19,7 @@ export const MentionStringArgumentInput = ({ disabled, width, tabIndex, + multiline, }: MentionStringArgumentInputProps) => { const { variables, data } = useVariableContext(); const nodeId = useNodeId(); @@ -59,10 +62,15 @@ export const MentionStringArgumentInput = ({ "&singleLine": { width: width, }, + "&multiLine": { + minHeight: "90px", + overflow: "scroll", + }, + maxWidth: "600px", }} aria-invalid={fieldState.invalid} tabIndex={tabIndex} - singleLine + singleLine={!multiline} value={field.value} disabled={disabled} onChange={(e, newValue, newPlainTextValue, mentions) => field.onChange(newValue)} diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/MountArtifactFileInput.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/MountArtifactFileInput.tsx index ca12376444..aca0e4d217 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/MountArtifactFileInput.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/MountArtifactFileInput.tsx @@ -10,7 +10,7 @@ export const MountArtifactFileInput = (props: KurtosisFormInputProps { return variables - .filter((variable) => variable.id.match(/^(?:artifact|shell|python)\.[^.]+$/)) + .filter((variable) => variable.id.match(/^(?:artifact|shell|python)\.[^.]+.store/)) .map((variable) => ({ display: variable.displayName, value: `{{${variable.id}}}` })); }, [variables]); @@ -30,7 +30,7 @@ export const MountArtifactFileInput = (props: KurtosisFormInputProps diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/PortConfigurationInput.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/PortConfigurationInput.tsx index f3e84c7b4e..f6bcd2f51b 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/PortConfigurationInput.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/PortConfigurationInput.tsx @@ -12,7 +12,7 @@ export const PortConfigurationField = (props: KurtosisFormInputProps @@ -25,6 +25,7 @@ export const PortConfigurationField = (props: KurtosisFormInputProps {...props} + isRequired={false} size={"sm"} placeholder={"Application Protocol (eg postgresql)"} name={`${props.name as `ports.${number}`}.applicationProtocol`} diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/SelectServiceInput.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/SelectServiceInput.tsx new file mode 100644 index 0000000000..125fc81d27 --- /dev/null +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/SelectServiceInput.tsx @@ -0,0 +1,24 @@ +import { useMemo } from "react"; +import { SelectArgumentInput, SelectOption } from "../../form/SelectArgumentInput"; +import { KurtosisFormInputProps } from "../../form/types"; +import { KurtosisExecNodeData } from "../types"; +import { useVariableContext } from "../VariableContextProvider"; + +export const SelectServiceInput = (props: KurtosisFormInputProps) => { + const { variables } = useVariableContext(); + const serviceVariableOptions = useMemo((): SelectOption[] => { + return variables + .filter((variable) => variable.id.match(/^(?:service)\.[^.]+\.name$/)) + .map((variable) => ({ display: variable.displayName, value: `{{${variable.id}}}` })); + }, [variables]); + + return ( + + options={serviceVariableOptions} + {...props} + size={"sm"} + placeholder={"Select a Service"} + name={props.name} + /> + ); +}; diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/StoreConfigurationInput.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/StoreConfigurationInput.tsx new file mode 100644 index 0000000000..da315c853e --- /dev/null +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/input/StoreConfigurationInput.tsx @@ -0,0 +1,29 @@ +import { Grid, GridItem } from "@chakra-ui/react"; +import { Path } from "react-hook-form"; +import { StringArgumentInput } from "../../form/StringArgumentInput"; +import { KurtosisFormInputProps } from "../../form/types"; +import { KurtosisStore } from "../types"; +import { MentionStringArgumentInput } from "./MentionStringArgumentInput"; + +export const StoreConfigurationInput = (props: KurtosisFormInputProps) => { + return ( + + + } + /> + + + + {...props} + size={"sm"} + placeholder={"/some/path"} + name={`${props.name as `store.${number}`}.path` as Path} + /> + + + ); +}; diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/modals/ConfigurePackageNodeModal.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/modals/ConfigurePackageNodeModal.tsx new file mode 100644 index 0000000000..bbcf70d56b --- /dev/null +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/modals/ConfigurePackageNodeModal.tsx @@ -0,0 +1,95 @@ +import { + Button, + Flex, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + Text, +} from "@chakra-ui/react"; +import { KurtosisPackage } from "kurtosis-cloud-indexer-sdk"; +import { isDefined, PackageLogo, readablePackageName } from "kurtosis-ui-components"; +import { useEffect, useState } from "react"; +import { FormProvider, useForm, useFormContext } from "react-hook-form"; +import { CatalogContextProvider } from "../../../../catalog/CatalogContext"; +import { KurtosisPackageArgumentInput } from "../../configuration/KurtosisPackageArgumentInput"; +import { PackageSelector } from "../../configuration/PackageSelector"; +import { transformFormArgsToKurtosisArgs, transformKurtosisArgsToFormArgs } from "../../configuration/utils"; +import { KurtosisPackageNodeData } from "../types"; + +type ConfigurePackageNodeModalProps = { + isOpen: boolean; + initialValues: Record; + onClose: () => void; +}; +export const ConfigurePackageNodeModal = ({ isOpen, onClose, initialValues }: ConfigurePackageNodeModalProps) => { + const [kurtosisPackage, setKurtosisPackage] = useState(); + const parentFormMethods = useFormContext(); + const formMethods = useForm>(); + + const onValidSubmit = (data: Record) => { + if (isDefined(kurtosisPackage)) { + parentFormMethods.setValue("args", transformFormArgsToKurtosisArgs(data.args, kurtosisPackage)); + parentFormMethods.setValue("packageId", kurtosisPackage.name); + parentFormMethods.setValue("locator", kurtosisPackage.locator); + onClose(); + } + }; + + useEffect(() => { + if (isDefined(kurtosisPackage)) { + formMethods.setValue("args", transformKurtosisArgsToFormArgs(initialValues, kurtosisPackage)); + } + }, [kurtosisPackage, initialValues, formMethods]); + + return ( + + + + + + {isDefined(kurtosisPackage) ? ( + + + {readablePackageName(kurtosisPackage.name)} + + ) : ( + "Choose a package" + )} + + + + + {!isDefined(kurtosisPackage) && } + {isDefined(kurtosisPackage) && ( + + {kurtosisPackage.args.map((arg, i) => ( + + ))} + + )} + + + + + + + + + + + + ); +}; diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/modals/EditFileModal.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/modals/EditFileModal.tsx index 65361a7928..8945843d79 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/modals/EditFileModal.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/modals/EditFileModal.tsx @@ -9,7 +9,7 @@ import { ModalHeader, ModalOverlay, } from "@chakra-ui/react"; -import { CodeEditor, CodeEditorImperativeAttributes } from "kurtosis-ui-components"; +import { CodeEditor, CodeEditorImperativeAttributes, isDefined } from "kurtosis-ui-components"; import { useMemo, useRef } from "react"; type EditFileModalProps = { @@ -17,7 +17,7 @@ type EditFileModalProps = { onClose: () => void; filePath: string[]; file: string; - onSave: (newContents: string) => void; + onSave?: (newContents: string) => void; }; export const EditFileModal = ({ isOpen, onClose, filePath, file, onSave }: EditFileModalProps) => { const codeEditorRef = useRef(null); @@ -33,20 +33,22 @@ export const EditFileModal = ({ isOpen, onClose, filePath, file, onSave }: EditF - + - + {isDefined(onSave) && ( + + )} diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisArtifactNode.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisArtifactNode.tsx new file mode 100644 index 0000000000..e204cbc0d8 --- /dev/null +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisArtifactNode.tsx @@ -0,0 +1,44 @@ +import { isDefined } from "kurtosis-ui-components"; +import { memo } from "react"; +import { NodeProps } from "reactflow"; +import { KurtosisFormControl } from "../../form/KurtosisFormControl"; +import { StringArgumentInput } from "../../form/StringArgumentInput"; +import { FileTreeArgumentInput } from "../input/FileTreeArgumentInput"; +import { validateName } from "../input/validators"; +import { KurtosisArtifactNodeData, KurtosisPythonNodeData } from "../types"; +import { useVariableContext } from "../VariableContextProvider"; +import { KurtosisNode } from "./KurtosisNode"; + +export const KurtosisArtifactNode = memo( + ({ id, selected }: NodeProps) => { + const { data } = useVariableContext(); + const nodeData = data[id] as KurtosisPythonNodeData; + + if (!isDefined(nodeData)) { + return null; + } + + return ( + + + name={"name"} + label={"Artifact Name"} + isRequired + isDisabled={nodeData.isFromPackage} + > + + + + + + + ); + }, + (oldProps, newProps) => oldProps.id === newProps.id && oldProps.selected === newProps.selected, +); diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisExecNode.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisExecNode.tsx new file mode 100644 index 0000000000..33a60257dd --- /dev/null +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisExecNode.tsx @@ -0,0 +1,100 @@ +import { Flex } from "@chakra-ui/react"; +import { isDefined } from "kurtosis-ui-components"; +import { memo, useEffect } from "react"; +import { useFormContext } from "react-hook-form"; +import { NodeProps } from "reactflow"; +import { IntegerArgumentInput } from "../../form/IntegerArgumentInput"; +import { KurtosisFormControl } from "../../form/KurtosisFormControl"; +import { ListArgumentInput } from "../../form/ListArgumentInput"; +import { KurtosisFormInputProps } from "../../form/types"; +import { MentionStringArgumentInput } from "../input/MentionStringArgumentInput"; +import { SelectServiceInput } from "../input/SelectServiceInput"; +import { KurtosisExecNodeData } from "../types"; +import { useVariableContext } from "../VariableContextProvider"; +import { KurtosisNode } from "./KurtosisNode"; + +export const KurtosisExecNode = memo( + ({ id, selected }: NodeProps) => { + const { data } = useVariableContext(); + const nodeData = data[id] as KurtosisExecNodeData; + + if (!isDefined(nodeData)) { + return null; + } + + return ( + + + + + name={"service"} + label={"Service"} + isRequired + isDisabled={nodeData.isFromPackage} + > + + + + + + name={"command"} + label={"Command"} + isRequired + isDisabled={nodeData.isFromPackage} + > + + + + name={"acceptableCodes"} + label={"Acceptable Exit Codes"} + isDisabled={nodeData.isFromPackage} + helperText={"If the executed command returns a code not on this list starlark will fail. Defaults to [0]"} + > + + FieldComponent={AcceptableCodeInput} + size={"sm"} + name={"acceptableCodes"} + createNewValue={() => ({ value: 0 })} + disabled={nodeData.isFromPackage} + /> + + + + ); + }, + (oldProps, newProps) => oldProps.id === newProps.id && oldProps.selected === newProps.selected, +); + +const AcceptableCodeInput = (props: KurtosisFormInputProps) => { + return ( + + {...props} + size={"sm"} + name={`${props.name as `acceptableCodes.${number}`}.value`} + /> + ); +}; + +const ExecNameUpdater = memo(() => { + const { variables } = useVariableContext(); + const { watch, setValue } = useFormContext(); + + const service = watch("service"); + const name = watch("name"); + + useEffect(() => { + const serviceVariableId = service.replace(/\{\{(.*)}}/, "$1"); + const serviceName = variables.find((v) => v.id === serviceVariableId)?.displayName || "Unknown"; + if (name !== `${serviceName} exec`) { + setValue("name", `${serviceName} exec`); + } + }, [name, service, setValue, variables]); + + return null; +}); diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisNode.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisNode.tsx new file mode 100644 index 0000000000..7c31b8d599 --- /dev/null +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisNode.tsx @@ -0,0 +1,333 @@ +import { Box, Flex, Icon, IconButton, Text, useToken } from "@chakra-ui/react"; +import { isDefined } from "kurtosis-ui-components"; +import { debounce } from "lodash"; +import { FC, memo, PropsWithChildren, ReactElement, useCallback, useEffect, useMemo } from "react"; +import { DefaultValues, FormProvider, useForm } from "react-hook-form"; +import { FiCpu, FiFile, FiPackage, FiTerminal, FiTrash } from "react-icons/fi"; +import { RxCornerBottomRight } from "react-icons/rx"; +import { Handle, NodeResizeControl, Position, useReactFlow, useViewport } from "reactflow"; +import { KurtosisNodeData } from "../types"; +import { useVariableContext } from "../VariableContextProvider"; + +const colors: Record = { + service: "blue.900", + artifact: "yellow.900", + shell: "red.900", + python: "red.900", + exec: "red.900", + package: "kurtosisGreen.700", +}; + +export const nodeIcons: Record = { + service: FiCpu, + artifact: FiFile, + shell: FiTerminal, + python: FiTerminal, + exec: FiTerminal, + package: FiPackage, +}; + +const nodeTypeReadable: Record = { + service: "Service", + artifact: "Files", + exec: "Service execution task", + shell: "Shell execution task", + python: "Python execution task", + package: "Package", +}; + +type KurtosisNodeProps = PropsWithChildren<{ + id: string; + selected: boolean; + minWidth: number; + maxWidth: number; + // Optional element to show outside of the zoom aware behaviour + portalContent?: ReactElement; + backgroundColor?: string; +}>; + +export const KurtosisNode = memo( + ({ + id, + selected, + minWidth, + maxWidth, + portalContent, + backgroundColor, + children, + }: KurtosisNodeProps) => { + const { data } = useVariableContext(); + const nodeData = data[id] as DataType; + + if (!isDefined(nodeData)) { + return null; + } + + return ( + + id={id} + selected={selected} + minWidth={minWidth} + maxWidth={maxWidth} + nodeData={nodeData} + portalContent={portalContent} + backgroundColor={backgroundColor} + > + {children} + + ); + }, +); + +type KurtosisNodeImplProps = KurtosisNodeProps & { nodeData: DataType }; +const KurtosisNodeImpl = ({ + id, + nodeData, + selected, + minWidth, + maxWidth, + portalContent, + backgroundColor, + children, +}: KurtosisNodeImplProps) => { + if (!selected) { + return ( + <> + {" "} + + + + + ); + } + + return ( + + {children} + + ); +}; + +const KurtosisFormNode = ({ + id, + nodeData, + selected, + minWidth, + maxWidth, + portalContent, + backgroundColor, + children, +}: KurtosisNodeImplProps) => { + const { updateData, removeData } = useVariableContext(); + const { getNodes } = useReactFlow(); + const color = colors[nodeData.type]; + const chakraColor = useToken("colors", color); + const formMethods = useForm({ + defaultValues: nodeData as DefaultValues, + mode: "onBlur", + shouldFocusError: false, + }); + + const { deleteElements } = useReactFlow(); + + const handleDeleteNode = (e: React.MouseEvent) => { + e.stopPropagation(); + e.preventDefault(); + const nodesToRemove = [ + { id }, + ...getNodes() + .filter((n) => n.parentNode === id) + .map((n) => ({ id: n.id })), + ]; + deleteElements({ nodes: nodesToRemove }); + removeData(nodesToRemove); + }; + + const handleChange = useMemo( + () => + debounce(async () => { + const isValid = await formMethods.trigger(); + updateData(id, (oldData) => ({ ...oldData, ...formMethods.getValues(), isValid })); + }, 500), + [updateData, formMethods, id], + ); + + useEffect(() => { + const watcher = formMethods.watch(handleChange); + return () => watcher.unsubscribe(); + }, [formMethods, handleChange]); + + if (!isDefined(nodeData)) { + return null; + } + + return ( + + + + + + + + + + {children} + + {isDefined(portalContent) && portalContent} + + + + ); +}; + +type ZoomAwareNodeContentProps = PropsWithChildren<{ + name: string; + type: KurtosisNodeData["type"]; + isDisabled?: boolean; + onDelete: (e: React.MouseEvent) => void; +}>; + +const ZoomAwareNodeContent = ({ name, type, isDisabled, onDelete, children }: ZoomAwareNodeContentProps) => { + const viewport = useViewport(); + return ( + + {children} + + ); +}; + +type ZoomAwareNodeContentImplProps = ZoomAwareNodeContentProps & { zoom: number }; + +const ZoomAwareNodeContentImpl = memo( + ({ name, type, isDisabled, onDelete, zoom, children }: ZoomAwareNodeContentImplProps) => { + const { zoomOut, zoomIn } = useReactFlow(); + const handleScroll = useCallback( + (e: React.WheelEvent) => { + if (e.currentTarget.scrollTop === 0 && e.deltaY < 0) { + zoomIn(); + } + if ( + Math.abs(e.currentTarget.scrollHeight - e.currentTarget.clientHeight - e.currentTarget.scrollTop) <= 1 && + e.deltaY > 0 + ) { + zoomOut(); + } + }, + [zoomOut, zoomIn], + ); + + if (zoom < 0.4) { + return ; + } + + return ( + <> + + + + {name || Unnamed} + + {nodeTypeReadable[type]} + + + } + colorScheme={"red"} + variant={"ghost"} + size={"sm"} + onClick={onDelete} + isDisabled={isDisabled} + /> + + + {children} + + + + ); + }, +); + +type BasicKurtosisNodeProps = { + type: KurtosisNodeData["type"]; + name?: string; +}; +const BasicKurtosisNode = ({ type, name }: BasicKurtosisNodeProps) => { + return ( + + + + {name || Unnamed} + + + ); +}; diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisPackageNode.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisPackageNode.tsx new file mode 100644 index 0000000000..6d8ad5106c --- /dev/null +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisPackageNode.tsx @@ -0,0 +1,341 @@ +import { Button, Flex } from "@chakra-ui/react"; +import { isDefined } from "kurtosis-ui-components"; +import { memo, useEffect, useState } from "react"; +import { FiEdit } from "react-icons/fi"; +import { NodeProps, useReactFlow } from "reactflow"; +import YAML from "yaml"; +import { useKurtosisClient } from "../../../../../client/enclaveManager/KurtosisClientContext"; +import { KurtosisFormControl } from "../../form/KurtosisFormControl"; +import { StringArgumentInput } from "../../form/StringArgumentInput"; +import { validateName } from "../input/validators"; +import { ConfigurePackageNodeModal } from "../modals/ConfigurePackageNodeModal"; +import { KurtosisPackageNodeData, PlanFileArtifact, PlanTask, PlanYaml } from "../types"; +import { useVariableContext } from "../VariableContextProvider"; +import { KurtosisNode } from "./KurtosisNode"; + +type Mode = { type: "loading" } | { type: "error"; error: string } | { type: "ready" }; + +export const KurtosisPackageNode = memo( + ({ id, selected }: NodeProps) => { + const { getNodes, deleteElements, setNodes } = useReactFlow(); + const [showPackageConfigModal, setShowPackageConfigModal] = useState(false); + const [mode, setMode] = useState({ type: "ready" }); + const kurtosisClient = useKurtosisClient(); + const { data, updateData, removeData } = useVariableContext(); + const nodeData = data[id] as KurtosisPackageNodeData | undefined; + + useEffect(() => { + const packageId = nodeData?.packageId; + const args = nodeData?.args; + if (isDefined(packageId) && isDefined(args) && packageId !== "") { + let cancelled = false; + (async () => { + setMode({ type: "loading" }); + const enclave = await kurtosisClient.createEnclave("", "info"); + if (enclave.isErr) { + setMode({ type: "error", error: enclave.error }); + return; + } + if (!isDefined(enclave.value.enclaveInfo) || !isDefined(enclave.value.enclaveInfo.apiContainerInfo)) { + setMode({ type: "error", error: "APIC info missing from temporary enclave" }); + return; + } + const plan = await kurtosisClient.getStarlarkPackagePlanYaml( + enclave.value.enclaveInfo.apiContainerInfo, + packageId, + args, + ); + await kurtosisClient.destroy(enclave.value.enclaveInfo?.enclaveUuid); + if (cancelled) { + return; + } + if (plan.isErr) { + setMode({ type: "error", error: plan.error }); + return; + } + console.log(plan.value.planYaml); + const parsedPlan = YAML.parse(plan.value.planYaml) as PlanYaml; + + // Remove current children + const nodesToRemove = getNodes().filter((node) => node.parentNode === id); + deleteElements({ nodes: nodesToRemove }); + removeData(nodesToRemove); + + const serviceNamesToId = (parsedPlan.services || []).reduce( + (acc: Record, service) => ({ ...acc, [service.name]: `${id}:${service.uuid}` }), + {}, + ); + const taskLookup = (parsedPlan.tasks || []).reduce( + (acc: Record, task) => ({ ...acc, [task.uuid]: task }), + {}, + ); + const artifactLookup = (parsedPlan.filesArtifacts || []).reduce( + (acc: Record, filesArtifact) => ({ ...acc, [filesArtifact.uuid]: filesArtifact }), + {}, + ); + + const plannedArtifacts = (parsedPlan.filesArtifacts || []).filter( + (artifact) => + !(parsedPlan.tasks || []).some( + (task) => task.taskType !== "exec" && (task.store || []).some((store) => store.uuid === artifact.uuid), + ), + ); + + const artifactToNodeId = (parsedPlan.filesArtifacts || []).reduce( + (acc: Record, artifact) => ({ + ...acc, + [artifact.uuid]: + parsedPlan.tasks?.find( + (task) => task.taskType !== "exec" && task.store?.some((store) => store.uuid === artifact.uuid), + )?.uuid || artifact.uuid, + }), + {}, + ); + + const artifactTypes = (parsedPlan.filesArtifacts || []).reduce( + (acc: Record, artifact) => ({ + ...acc, + [artifact.uuid]: + taskLookup[artifactToNodeId[artifact.uuid]]?.taskType === "sh" + ? "shell" + : taskLookup[artifactToNodeId[artifact.uuid]]?.taskType === "python" + ? "python" + : "artifact", + }), + {}, + ); + + const nodesToAdd: { type: string; id: string }[] = [ + ...(parsedPlan.services || []).map((service, i) => ({ + type: "serviceNode", + id: `${id}:${service.uuid}`, + })), + ...(parsedPlan.tasks || []).map((task, i) => ({ + type: task.taskType === "exec" ? "execNode" : task.taskType === "python" ? "pythonNode" : "shellNode", + id: `${id}:${task.uuid}`, + })), + ...plannedArtifacts.map((artifact, i) => ({ + type: "artifactNode", + id: `${id}:${artifact.uuid}`, + })), + ]; + + const futureReferencePattern = /\{\{\s*kurtosis\.([^.]+)\.(\S+?)\s*}}/; + const convertFutureReferences = (input: string): string => { + // All future references are assumed to be for services + let result = input; + let match = result.match(futureReferencePattern); + while (isDefined(match)) { + result = result.replaceAll(match[0], `{{service.${id}:${match[1]}.${match[2]}}}`); + match = result.match(futureReferencePattern); + } + return result; + }; + + (parsedPlan.services || []).forEach((service) => + updateData(`${id}:${service.uuid}`, { + type: "service", + name: service.name, + isFromPackage: true, + env: (service.envVars || []).map(({ key, value }) => ({ + key: convertFutureReferences(key), + value: convertFutureReferences(value), + })), + image: { + type: "image", + image: service.image.name, + registryUsername: "", + registryPassword: "", + registry: "", + buildContextDir: "", + targetStage: "", + flakeLocationDir: "", + flakeOutput: "", + }, + ports: (service.ports || []).map((port) => ({ + name: port.name, + port: port.number, + applicationProtocol: port.applicationProtocol || "", + transportProtocol: port.transportProtocol, + })), + isValid: true, + files: (service.files || []).flatMap((file) => + file.filesArtifacts.map((artifact) => ({ + name: `{{${artifactTypes[artifact.uuid]}.${id}:${artifactToNodeId[artifact.uuid]}.store.${ + artifact.name + }}}`, + mountPoint: file.mountPath, + })), + ), + cmd: convertFutureReferences((service.command || []).join(" ")), + entrypoint: convertFutureReferences((service.entrypoint || []).join(" ")), + }), + ); + (parsedPlan.tasks || []).forEach((task) => { + if (task.taskType === "exec") { + const serviceVariable = `{{service.${serviceNamesToId[task.serviceName]}.name}}`; + updateData(`${id}:${task.uuid}`, { + type: "exec", + name: "", + isValid: true, + isFromPackage: true, + service: serviceVariable, + command: (task.command || []).join(" "), + acceptableCodes: (task.acceptableCodes || []).map((code) => ({ value: code })), + }); + } + if (task.taskType === "python") { + updateData(`${id}:${task.uuid}`, { + type: "python", + name: `Python ${task.uuid}`, + isValid: true, + isFromPackage: true, + command: (task.command || []).join(" "), + image: { + type: "image", + image: task.image, + registryUsername: "", + registryPassword: "", + registry: "", + buildContextDir: "", + targetStage: "", + flakeLocationDir: "", + flakeOutput: "", + }, + packages: [], + args: task.pythonArgs.map((arg) => ({ arg })), + files: (task.files || []).flatMap((file) => + file.filesArtifacts.map((artifact) => ({ + name: `{{${artifactTypes[artifact.uuid]}.${id}:${artifactToNodeId[artifact.uuid]}.store.${ + artifact.name + }}}`, + mountPoint: file.mountPath, + })), + ), + store: (task.store || []).map((store) => ({ + name: store.name, + path: artifactLookup[store.uuid].files[0], + })), + wait_enabled: "false", + wait: "", + }); + } + if (task.taskType === "sh") { + updateData(`${id}:${task.uuid}`, { + type: "shell", + name: `Shell ${task.uuid}`, + isValid: true, + isFromPackage: true, + command: (task.command || []).join(" "), + image: { + type: "image", + image: task.image, + registryUsername: "", + registryPassword: "", + registry: "", + buildContextDir: "", + targetStage: "", + flakeLocationDir: "", + flakeOutput: "", + }, + env: [], + files: (task.files || []).flatMap((file) => + file.filesArtifacts.map((artifact) => ({ + name: `{{${artifactTypes[artifact.uuid]}.${id}:${artifactToNodeId[artifact.uuid]}.store.${ + artifact.name + }}}`, + mountPoint: file.mountPath, + })), + ), + store: (task.store || []).map((store) => ({ + name: store.name, + path: artifactLookup[store.uuid].files[0], + })), + wait_enabled: "false", + wait: "", + }); + } + }); + plannedArtifacts.forEach((artifact) => + updateData(`${id}:${artifact.uuid}`, { + type: "artifact", + name: artifact.name, + isFromPackage: true, + isValid: true, + files: artifact.files.reduce((acc, file) => ({ ...acc, [file]: "" }), {}), + }), + ); + + setNodes((nodes) => [ + ...nodes, + ...nodesToAdd.map((node, i) => ({ + ...node, + parentNode: id, + data: {}, + position: { x: 50 + 700 * (i % 3), y: 200 + 700 * Math.floor(i / 3) }, + })), + ]); + + setMode({ type: "ready" }); + })(); + return () => { + cancelled = true; + }; + } + }, [ + nodeData?.packageId, + nodeData?.args, + deleteElements, + getNodes, + id, + kurtosisClient, + removeData, + setNodes, + updateData, + ]); + + if (!isDefined(nodeData)) { + return null; + } + + return ( + setShowPackageConfigModal(false)} + initialValues={nodeData.args} + /> + } + backgroundColor={"transparent"} + > + + name={"name"} label={"Node Name"} isRequired flex={"1"}> + + + + name={"packageId"} + label={`Package ${nodeData.packageId}`} + isRequired + flex={"1"} + > + + + + + ); + }, + (oldProps, newProps) => oldProps.id === newProps.id && oldProps.selected === newProps.selected, +); diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisPythonNode.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisPythonNode.tsx similarity index 63% rename from enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisPythonNode.tsx rename to enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisPythonNode.tsx index 9dad24819e..a5c2bdd139 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisPythonNode.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisPythonNode.tsx @@ -2,19 +2,20 @@ import { Flex, Tab, TabList, TabPanel, TabPanels, Tabs } from "@chakra-ui/react" import { isDefined } from "kurtosis-ui-components"; import { memo } from "react"; import { NodeProps } from "reactflow"; -import { BooleanArgumentInput } from "../form/BooleanArgumentInput"; -import { CodeEditorInput } from "../form/CodeEditorInput"; -import { KurtosisFormControl } from "../form/KurtosisFormControl"; -import { ListArgumentInput } from "../form/ListArgumentInput"; -import { StringArgumentInput } from "../form/StringArgumentInput"; -import { KurtosisFormInputProps } from "../form/types"; -import { ImageConfigInput } from "./input/ImageConfigInput"; -import { MentionStringArgumentInput } from "./input/MentionStringArgumentInput"; -import { MountArtifactFileInput } from "./input/MountArtifactFileInput"; -import { validateDurationString, validateName } from "./input/validators"; +import { BooleanArgumentInput } from "../../form/BooleanArgumentInput"; +import { CodeEditorInput } from "../../form/CodeEditorInput"; +import { KurtosisFormControl } from "../../form/KurtosisFormControl"; +import { ListArgumentInput } from "../../form/ListArgumentInput"; +import { StringArgumentInput } from "../../form/StringArgumentInput"; +import { KurtosisFormInputProps } from "../../form/types"; +import { ImageConfigInput } from "../input/ImageConfigInput"; +import { MentionStringArgumentInput } from "../input/MentionStringArgumentInput"; +import { MountArtifactFileInput } from "../input/MountArtifactFileInput"; +import { StoreConfigurationInput } from "../input/StoreConfigurationInput"; +import { validateDurationString, validateName } from "../input/validators"; +import { KurtosisFileMount, KurtosisPythonNodeData } from "../types"; +import { useVariableContext } from "../VariableContextProvider"; import { KurtosisNode } from "./KurtosisNode"; -import { KurtosisFileMount, KurtosisPythonNodeData } from "./types"; -import { useVariableContext } from "./VariableContextProvider"; export const KurtosisPythonNode = memo( ({ id, selected }: NodeProps) => { @@ -28,14 +29,29 @@ export const KurtosisPythonNode = memo( return ( - name={"pythonName"} label={"Python Name"} isRequired> - + + name={"name"} + label={"Python Name"} + isRequired + isDisabled={nodeData.isFromPackage} + > + - name={"image.image"} label={"Container Image"}> - + + name={"image.image"} + label={"Container Image"} + isDisabled={nodeData.isFromPackage} + > + - + Code Packages @@ -46,8 +62,13 @@ export const KurtosisPythonNode = memo( - name={"command"} label={"Code to run"} isRequired> - + + name={"command"} + label={"Code to run"} + isRequired + isDisabled={nodeData.isFromPackage} + > + @@ -55,6 +76,7 @@ export const KurtosisPythonNode = memo( name={"packages"} label={"Packages"} isRequired + isDisabled={nodeData.isFromPackage} helperText={"Names of packages that need to be installed prior to running this code"} > @@ -63,6 +85,7 @@ export const KurtosisPythonNode = memo( name={"packages"} size={"sm"} isRequired + disabled={nodeData.isFromPackage} validate={validateName} /> @@ -71,12 +94,14 @@ export const KurtosisPythonNode = memo( name={"args"} label={"Arguments"} + isDisabled={nodeData.isFromPackage} helperText={"Arguments to be passed to the Python script"} > name={"args"} FieldComponent={PythonArgInput} createNewValue={() => ({ arg: "" })} + disabled={nodeData.isFromPackage} isRequired /> @@ -85,27 +110,32 @@ export const KurtosisPythonNode = memo( name={"files"} label={"Input Files"} + isDisabled={nodeData.isFromPackage} helperText={"Choose where to mount artifacts on this execution tasks filesystem"} > ({ mountPoint: "", - artifactName: "", + name: "", })} /> name={"store"} label={"Output File/Directory"} + isDisabled={nodeData.isFromPackage} helperText={ "Choose which files to expose from this execution task. You can use either an absolute path, a directory, or a glob." } > - + ({ name: "", path: "" })} + minLength={1} /> @@ -115,19 +145,23 @@ export const KurtosisPythonNode = memo( name={"wait_enabled"} label={"Wait enabled"} isRequired + isDisabled={nodeData.isFromPackage} helperText={"Whether kurtosis should wait a preset time for this step to complete."} > - name={"wait_enabled"} /> + + name={"wait_enabled"} + disabled={nodeData.isFromPackage} + /> name={"wait"} label={"Wait"} - isDisabled={nodeData.wait_enabled === "false"} + isDisabled={nodeData.wait_enabled === "false" || nodeData.isFromPackage} helperText={"Whether kurtosis should wait a preset time for this step to complete."} > name={"wait"} - isDisabled={nodeData.wait_enabled === "false"} + disabled={nodeData.wait_enabled === "false" || nodeData.isFromPackage} size={"sm"} placeholder={"180s"} validate={nodeData.wait_enabled === "false" ? undefined : validateDurationString} diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisServiceNode.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisServiceNode.tsx new file mode 100644 index 0000000000..06f6912dcd --- /dev/null +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisServiceNode.tsx @@ -0,0 +1,142 @@ +import { Flex, Tab, TabList, TabPanel, TabPanels, Tabs } from "@chakra-ui/react"; +import { isDefined } from "kurtosis-ui-components"; +import { memo } from "react"; +import { NodeProps } from "reactflow"; +import { DictArgumentInput } from "../../form/DictArgumentInput"; +import { KurtosisFormControl } from "../../form/KurtosisFormControl"; +import { ListArgumentInput } from "../../form/ListArgumentInput"; +import { StringArgumentInput } from "../../form/StringArgumentInput"; +import { ImageConfigInput } from "../input/ImageConfigInput"; +import { MentionStringArgumentInput } from "../input/MentionStringArgumentInput"; +import { MountArtifactFileInput } from "../input/MountArtifactFileInput"; +import { PortConfigurationField } from "../input/PortConfigurationInput"; +import { validateName } from "../input/validators"; +import { KurtosisFileMount, KurtosisPort, KurtosisServiceNodeData } from "../types"; +import { useVariableContext } from "../VariableContextProvider"; +import { KurtosisNode } from "./KurtosisNode"; + +export const KurtosisServiceNode = memo( + ({ id, selected }: NodeProps) => { + const { data } = useVariableContext(); + const nodeData = data[id] as KurtosisServiceNodeData; + + if (!isDefined(nodeData)) { + return null; + } + + return ( + + + + name={"name"} + label={"Service Name"} + isRequired + isDisabled={nodeData.isFromPackage} + > + + + + name={"image.image"} + label={"Container Image"} + isRequired + isDisabled={nodeData.isFromPackage} + > + + + + + + Environment + Ports + Files + Advanced + + + + + name={"env"} + label={"Environment Variables"} + isDisabled={nodeData.isFromPackage} + > + + name={"env"} + disabled={nodeData.isFromPackage} + KeyFieldComponent={StringArgumentInput} + ValueFieldComponent={MentionStringArgumentInput} + /> + + + + + name={"ports"} + label={"Ports"} + isDisabled={nodeData.isFromPackage} + > + ({ + name: "", + applicationProtocol: "", + transportProtocol: "TCP", + port: 0, + })} + /> + + + + + name={"files"} + label={"Files"} + helperText={"Choose where to mount artifacts on this services filesystem"} + isDisabled={nodeData.isFromPackage} + > + ({ + mountPoint: "", + name: "", + })} + /> + + + + + + name={"entrypoint"} + label={"Entrypoint"} + helperText={ + "The ENTRYPOINT statement hardcoded in a container image's Dockerfile might not be suitable for your needs." + } + isDisabled={nodeData.isFromPackage} + > + + + + name={"cmd"} + label={"CMD"} + helperText={ + "The CMD statement hardcoded in a container image's Dockerfile might not be suitable for your needs." + } + isDisabled={nodeData.isFromPackage} + > + + + + + + + + ); + }, + (oldProps, newProps) => oldProps.id === newProps.id && oldProps.selected === newProps.selected, +); diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisShellNode.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisShellNode.tsx similarity index 55% rename from enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisShellNode.tsx rename to enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisShellNode.tsx index f144c4f1e4..bb309e4e95 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/KurtosisShellNode.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/nodes/KurtosisShellNode.tsx @@ -2,19 +2,20 @@ import { Flex, Tab, TabList, TabPanel, TabPanels, Tabs } from "@chakra-ui/react" import { isDefined } from "kurtosis-ui-components"; import { memo } from "react"; import { NodeProps } from "reactflow"; -import { BooleanArgumentInput } from "../form/BooleanArgumentInput"; -import { CodeEditorInput } from "../form/CodeEditorInput"; -import { DictArgumentInput } from "../form/DictArgumentInput"; -import { KurtosisFormControl } from "../form/KurtosisFormControl"; -import { ListArgumentInput } from "../form/ListArgumentInput"; -import { StringArgumentInput } from "../form/StringArgumentInput"; -import { ImageConfigInput } from "./input/ImageConfigInput"; -import { MentionStringArgumentInput } from "./input/MentionStringArgumentInput"; -import { MountArtifactFileInput } from "./input/MountArtifactFileInput"; -import { validateDurationString, validateName } from "./input/validators"; +import { BooleanArgumentInput } from "../../form/BooleanArgumentInput"; +import { CodeEditorInput } from "../../form/CodeEditorInput"; +import { DictArgumentInput } from "../../form/DictArgumentInput"; +import { KurtosisFormControl } from "../../form/KurtosisFormControl"; +import { ListArgumentInput } from "../../form/ListArgumentInput"; +import { StringArgumentInput } from "../../form/StringArgumentInput"; +import { ImageConfigInput } from "../input/ImageConfigInput"; +import { MentionStringArgumentInput } from "../input/MentionStringArgumentInput"; +import { MountArtifactFileInput } from "../input/MountArtifactFileInput"; +import { StoreConfigurationInput } from "../input/StoreConfigurationInput"; +import { validateDurationString, validateName } from "../input/validators"; +import { KurtosisFileMount, KurtosisShellNodeData } from "../types"; +import { useVariableContext } from "../VariableContextProvider"; import { KurtosisNode } from "./KurtosisNode"; -import { KurtosisFileMount, KurtosisShellNodeData } from "./types"; -import { useVariableContext } from "./VariableContextProvider"; export const KurtosisShellNode = memo( ({ id, selected }: NodeProps) => { @@ -28,33 +29,57 @@ export const KurtosisShellNode = memo( return ( - name={"shellName"} label={"Shell Name"} isRequired> - + + name={"name"} + label={"Shell Name"} + isRequired + isDisabled={nodeData.isFromPackage} + > + - name={"image.image"} label={"Container Image"}> - + + name={"image.image"} + label={"Container Image"} + isDisabled={nodeData.isFromPackage} + > + - + Script Environment Files Advanced - - name={"command"} label={"Script to run"} isRequired> - + + name={"command"} + label={"Script to run"} + isRequired + isDisabled={nodeData.isFromPackage} + > + - name={"env"} label={"Environment Variables"}> + + name={"env"} + label={"Environment Variables"} + isDisabled={nodeData.isFromPackage} + > name={"env"} KeyFieldComponent={StringArgumentInput} ValueFieldComponent={MentionStringArgumentInput} + disabled={nodeData.isFromPackage} /> @@ -63,14 +88,16 @@ export const KurtosisShellNode = memo( name={"files"} label={"Input Files"} helperText={"Choose where to mount artifacts on this execution tasks filesystem"} + isDisabled={nodeData.isFromPackage} > ({ mountPoint: "", - artifactName: "", + name: "", })} + disabled={nodeData.isFromPackage} /> @@ -80,11 +107,13 @@ export const KurtosisShellNode = memo( "Choose which files to expose from this execution task. You can use either an absolute path, a directory, or a glob." } isRequired + isDisabled={nodeData.isFromPackage} > - + ({ name: "", path: "" })} + minLength={1} /> @@ -94,19 +123,23 @@ export const KurtosisShellNode = memo( name={"wait_enabled"} label={"Wait enabled"} isRequired + isDisabled={nodeData.isFromPackage} helperText={"Whether kurtosis should wait a preset time for this step to complete."} > - name={"wait_enabled"} /> + + name={"wait_enabled"} + disabled={nodeData.isFromPackage} + /> name={"wait"} label={"Wait"} - isDisabled={nodeData.wait_enabled === "false"} + isDisabled={nodeData.wait_enabled === "false" || nodeData.isFromPackage} helperText={"Whether kurtosis should wait a preset time for this step to complete."} > name={"wait"} - isDisabled={nodeData.wait_enabled === "false"} + disabled={nodeData.wait_enabled === "false" || nodeData.isFromPackage} size={"sm"} placeholder={"180s"} validate={nodeData.wait_enabled === "false" ? undefined : validateDurationString} diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/types.ts b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/types.ts index aec5580094..7af5302381 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/types.ts +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/types.ts @@ -5,7 +5,7 @@ export type Variable = { }; export type KurtosisPort = { - portName: string; + name: string; port: number; transportProtocol: "TCP" | "UDP"; applicationProtocol: string; @@ -15,7 +15,7 @@ export type KurtosisEnvironmentVar = { key: string; value: string }; export type KurtosisFileMount = { mountPoint: string; - artifactName: string; + name: string; }; export type KurtosisAcceptableCode = { @@ -38,31 +38,49 @@ export type KurtosisImageConfig = { export type KurtosisServiceNodeData = { type: "service"; - serviceName: string; + name: string; + isFromPackage?: boolean; image: KurtosisImageConfig; env: KurtosisEnvironmentVar[]; ports: KurtosisPort[]; files: KurtosisFileMount[]; - execStepEnabled: "true" | "false"; - execStepCommand: string; - execStepAcceptableCodes: KurtosisAcceptableCode[]; + entrypoint: string; + cmd: string; isValid: boolean; }; + +export type KurtosisExecNodeData = { + type: "exec"; + name: string; + isFromPackage?: boolean; + isValid: boolean; + service: string; + command: string; + acceptableCodes: KurtosisAcceptableCode[]; +}; + export type KurtosisArtifactNodeData = { type: "artifact"; - artifactName: string; + name: string; + isFromPackage?: boolean; files: Record; isValid: boolean; }; +export type KurtosisStore = { + name: string; + path: string; +}; + export type KurtosisShellNodeData = { type: "shell"; - shellName: string; + name: string; + isFromPackage?: boolean; command: string; image: KurtosisImageConfig; env: KurtosisEnvironmentVar[]; files: KurtosisFileMount[]; - store: string; + store: KurtosisStore[]; wait_enabled: "true" | "false"; wait: string; isValid: boolean; @@ -73,20 +91,103 @@ export type KurtosisPythonArg = { arg: string }; export type KurtosisPythonNodeData = { type: "python"; - pythonName: string; + name: string; + isFromPackage?: boolean; command: string; image: KurtosisImageConfig; packages: KurtosisPythonPackage[]; args: KurtosisPythonArg[]; files: KurtosisFileMount[]; - store: string; + store: KurtosisStore[]; wait_enabled: "true" | "false"; wait: string; isValid: boolean; }; +export type KurtosisPackageNodeData = { + type: "package"; + name: string; + isFromPackage?: boolean; + packageId: string; + locator: string; + args: Record; + isValid: boolean; +}; + export type KurtosisNodeData = | KurtosisArtifactNodeData | KurtosisServiceNodeData + | KurtosisExecNodeData | KurtosisShellNodeData - | KurtosisPythonNodeData; + | KurtosisPythonNodeData + | KurtosisPackageNodeData; + +export type PlanPort = { + name: string; + number: number; + transportProtocol: "TCP" | "UDP"; + applicationProtocol?: string; +}; + +type PlanArtifactReference = { + name: string; + uuid: string; +}; + +type PlanFile = { + mountPath: string; + filesArtifacts: PlanArtifactReference[]; +}; + +export type PlanService = { + name: string; + uuid: string; + image: { name: string }; + envVars?: KurtosisEnvironmentVar[]; + ports?: PlanPort[]; + command?: string[]; + entrypoint?: string[]; + files: PlanFile[]; +}; + +type PlanExecTask = { + taskType: "exec"; + uuid: string; + command: string[]; + serviceName: string; + acceptableCodes?: number[]; +}; + +type PlanPythonTask = { + taskType: "python"; + uuid: string; + command?: string[]; + image: string; + files?: PlanFile[]; + store?: PlanArtifactReference[]; + pythonArgs: string[]; +}; + +type PlanShTask = { + taskType: "sh"; + uuid: string; + command?: string[]; + image: string; + files?: PlanFile[]; + store?: PlanArtifactReference[]; +}; + +export type PlanTask = PlanExecTask | PlanPythonTask | PlanShTask; + +export type PlanFileArtifact = { + name: string; + uuid: string; + files: string[]; +}; + +export type PlanYaml = { + packageId: string; + services?: PlanService[]; + tasks?: PlanTask[]; + filesArtifacts?: PlanFileArtifact[]; +}; diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/utils.ts b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/utils.ts index b9d7c7f84e..26d451ecd1 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/utils.ts +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/enclaveBuilder/utils.ts @@ -2,7 +2,13 @@ import { isDefined, RemoveFunctions, stringifyError } from "kurtosis-ui-componen import { Edge, Node } from "reactflow"; import { Result } from "true-myth"; import { EnclaveFullInfo } from "../../types"; -import { KurtosisImageConfig, KurtosisNodeData, KurtosisServiceNodeData, Variable } from "./types"; +import { + KurtosisImageConfig, + KurtosisNodeData, + KurtosisPackageNodeData, + KurtosisServiceNodeData, + Variable, +} from "./types"; export const EMUI_BUILD_STATE_KEY = "EMUI_BUILD_STATE"; @@ -35,22 +41,6 @@ export function getInitialGraphStateFromEnclave( } } -export function getNodeName(kurtosisNodeData: KurtosisNodeData): string { - if (kurtosisNodeData.type === "service") { - return kurtosisNodeData.serviceName; - } - if (kurtosisNodeData.type === "artifact") { - return kurtosisNodeData.artifactName; - } - if (kurtosisNodeData.type === "shell") { - return kurtosisNodeData.shellName; - } - if (kurtosisNodeData.type === "python") { - return kurtosisNodeData.pythonName; - } - throw new Error(`Unknown node type.`); -} - function normaliseNameToStarlarkVariable(name: string) { return name.replace(/\s|-/g, "_").toLowerCase(); } @@ -70,40 +60,55 @@ export function getVariablesFromNodes(nodes: Record): return [ { id: `service.${id}.name`, - displayName: `${data.serviceName}.name`, - value: `${normaliseNameToStarlarkVariable(data.serviceName)}.name`, + displayName: `${data.name}`, + value: `${ + data.isFromPackage ? `plan.get_service(name="${data.name}")` : normaliseNameToStarlarkVariable(data.name) + }.name`, }, { id: `service.${id}.hostname`, - displayName: `${data.serviceName}.hostname`, - value: `${normaliseNameToStarlarkVariable(data.serviceName)}.hostname`, + displayName: `${data.name}.hostname`, + value: `${ + data.isFromPackage ? `plan.get_service(name="${data.name}")` : normaliseNameToStarlarkVariable(data.name) + }.hostname`, + }, + { + id: `service.${id}.ip_address`, + displayName: `${data.name}.ip_address`, + value: `${ + data.isFromPackage ? `plan.get_service(name="${data.name}")` : normaliseNameToStarlarkVariable(data.name) + }.ip_address`, }, ...data.ports.flatMap((port, i) => [ { id: `service.${id}.ports.${i}`, - displayName: `${data.serviceName}.ports.${port.portName}`, - value: `"{}://{}:{}".format(${normaliseNameToStarlarkVariable(data.serviceName)}.ports["${ - port.portName - }"].application_protocol, ${normaliseNameToStarlarkVariable( - data.serviceName, - )}.hostname, ${normaliseNameToStarlarkVariable(data.serviceName)}.ports["${port.portName}"].number)`, + displayName: `${data.name}.ports.${port.name}`, + value: `"{}://{}:{}".format(${ + data.isFromPackage ? `plan.get_service(name="${data.name}")` : normaliseNameToStarlarkVariable(data.name) + }.ports["${port.name}"].application_protocol, ${ + data.isFromPackage ? `plan.get_service(name="${data.name}")` : normaliseNameToStarlarkVariable(data.name) + }.hostname, ${ + data.isFromPackage ? `plan.get_service(name="${data.name}")` : normaliseNameToStarlarkVariable(data.name) + }.ports["${port.name}"].number)`, }, { id: `service.${id}.ports.${i}.port`, - displayName: `${data.serviceName}.ports.${port.portName}.port`, - value: `str(${normaliseNameToStarlarkVariable(data.serviceName)}.ports["${port.portName}"].number)`, + displayName: `${data.name}.ports.${port.name}.port`, + value: `str(${ + data.isFromPackage ? `plan.get_service(name="${data.name}")` : normaliseNameToStarlarkVariable(data.name) + }.ports["${port.name}"].number)`, }, { id: `service.${id}.ports.${i}.applicationProtocol`, - displayName: `${data.serviceName}.ports.${port.portName}.application_protocol`, - value: `${normaliseNameToStarlarkVariable(data.serviceName)}.ports["${ - port.portName - }"].application_protocol`, + displayName: `${data.name}.ports.${port.name}.application_protocol`, + value: `${ + data.isFromPackage ? `plan.get_service(name="${data.name}")` : normaliseNameToStarlarkVariable(data.name) + }.ports["${port.name}"].application_protocol`, }, ]), ...data.env.map((env, i) => ({ id: `service.${id}.env.${i}.value`, - displayName: `${data.serviceName}.env.${env.key}`, + displayName: `${data.name}.env.${env.key}`, value: `"${env.value}"`, })), ]; @@ -111,23 +116,25 @@ export function getVariablesFromNodes(nodes: Record): if (data.type === "artifact") { return [ { - id: `artifact.${id}`, - displayName: `${data.artifactName}`, - value: `${normaliseNameToStarlarkVariable(data.artifactName)}`, + id: `artifact.${id}.store.${data.name}`, + displayName: `${data.name}`, + value: `${normaliseNameToStarlarkVariable(data.name)}`, }, ]; } if (data.type === "shell") { return [ - { - id: `shell.${id}`, - displayName: `${data.shellName}`, - value: `${normaliseNameToStarlarkVariable(data.shellName)}.files_artifacts[0]`, - }, + ...data.store.map((store, i) => ({ + id: `shell.${id}.store.${store.name}`, + displayName: `${data.name}.${store.name}`, + value: data.isFromPackage + ? `"${store.name}"` + : `${normaliseNameToStarlarkVariable(data.name)}.files_artifacts[${i}]`, + })), ...data.env.map((env, i) => ({ id: `shell.${id}.env.${i}.value`, - displayName: `${data.shellName}.env.${env.key}`, + displayName: `${data.name}.env.${env.key}`, value: `"${env.value}"`, })), ]; @@ -135,14 +142,16 @@ export function getVariablesFromNodes(nodes: Record): if (data.type === "python") { return [ - { - id: `python.${id}`, - displayName: `${data.pythonName}`, - value: `${normaliseNameToStarlarkVariable(data.pythonName)}.files_artifacts[0]`, - }, + ...data.store.map((store, i) => ({ + id: `python.${id}.store.${store.name}`, + displayName: `${data.name}.${store.name}`, + value: data.isFromPackage + ? `"${store.name}"` + : `${normaliseNameToStarlarkVariable(data.name)}.files_artifacts[${i}]`, + })), ...data.args.map((arg, i) => ({ id: `python.${id}.args.${i}.arg`, - displayName: `${data.pythonName}.args[${i}]`, + displayName: `${data.name}.args[${i}]`, value: `"${arg.arg}"`, })), ]; @@ -162,10 +171,18 @@ export function getNodeDependencies(nodes: Record): Re }; Object.entries(nodes).forEach(([id, data]) => { if (data.type === "service") { - const nameMatches = data.serviceName.match(variablePattern); + const nameMatches = data.name.match(variablePattern); if (nameMatches) { getDependenciesFor(id).add(nameMatches[2]); } + const cmdMatches = data.cmd.match(variablePattern); + if (cmdMatches) { + getDependenciesFor(id).add(cmdMatches[2]); + } + const entrypointMatches = data.entrypoint.match(variablePattern); + if (entrypointMatches) { + getDependenciesFor(id).add(entrypointMatches[2]); + } data.env.forEach((env) => { const envMatches = env.key.match(variablePattern) || env.value.match(variablePattern); if (envMatches) { @@ -173,26 +190,30 @@ export function getNodeDependencies(nodes: Record): Re } }); data.ports.forEach((port) => { - const portMatches = port.portName.match(variablePattern) || port.applicationProtocol.match(variablePattern); + const portMatches = port.name.match(variablePattern) || port.applicationProtocol.match(variablePattern); if (portMatches) { getDependenciesFor(id).add(portMatches[2]); } }); data.files.forEach((file) => { - const fileMatches = file.mountPoint.match(variablePattern) || file.artifactName.match(variablePattern); + const fileMatches = file.mountPoint.match(variablePattern) || file.name.match(variablePattern); if (fileMatches) { getDependenciesFor(id).add(fileMatches[2]); } }); - if (data.execStepEnabled === "true") { - const commandMatches = data.execStepCommand.match(variablePattern); - if (commandMatches) { - getDependenciesFor(id).add(commandMatches[2]); - } + } + if (data.type === "exec") { + const serviceMatches = data.service.match(variablePattern); + if (serviceMatches) { + getDependenciesFor(id).add(serviceMatches[2]); + } + const commandMatches = data.command.match(variablePattern); + if (commandMatches) { + getDependenciesFor(id).add(commandMatches[2]); } } if (data.type === "shell") { - const nameMatches = data.shellName.match(variablePattern); + const nameMatches = data.name.match(variablePattern); if (nameMatches) { getDependenciesFor(id).add(nameMatches[2]); } @@ -203,14 +224,14 @@ export function getNodeDependencies(nodes: Record): Re } }); data.files.forEach((file) => { - const fileMatches = file.mountPoint.match(variablePattern) || file.artifactName.match(variablePattern); + const fileMatches = file.mountPoint.match(variablePattern) || file.name.match(variablePattern); if (fileMatches) { getDependenciesFor(id).add(fileMatches[2]); } }); } if (data.type === "python") { - const nameMatches = data.pythonName.match(variablePattern); + const nameMatches = data.name.match(variablePattern); if (nameMatches) { getDependenciesFor(id).add(nameMatches[2]); } @@ -221,7 +242,7 @@ export function getNodeDependencies(nodes: Record): Re } }); data.files.forEach((file) => { - const fileMatches = file.mountPoint.match(variablePattern) || file.artifactName.match(variablePattern); + const fileMatches = file.mountPoint.match(variablePattern) || file.name.match(variablePattern); if (fileMatches) { getDependenciesFor(id).add(fileMatches[2]); } @@ -237,11 +258,17 @@ export function generateStarlarkFromGraph( data: Record, existingEnclave?: RemoveFunctions, ): string { + const nodeLookup = nodes.reduce((acc: Record, cur) => ({ ...acc, [cur.id]: cur }), {}); + const primaryNodes = nodes.filter((node) => !isDefined(node.parentNode)); + const primaryEdges = edges + .map((edge) => ({ ...edge, source: nodeLookup[edge.source].parentNode || edge.source })) + .filter((e) => e.target !== e.source); + // Topological sort const sortedNodes: Node[] = []; - let remainingEdges = [...edges].filter((e) => e.target !== e.source); - while (remainingEdges.length > 0 || sortedNodes.length !== nodes.length) { - const nodesToRemove = nodes + let remainingEdges = [...primaryEdges]; + while (remainingEdges.length > 0 || sortedNodes.length !== primaryNodes.length) { + const nodesToRemove = primaryNodes .filter((node) => remainingEdges.every((edge) => edge.target !== node.id)) // eslint-disable-line no-loop-func .filter((node) => !sortedNodes.includes(node)); @@ -258,7 +285,7 @@ export function generateStarlarkFromGraph( {} as Record, ); const interpolateValue = (input: string): string => { - let formatString = input; + let formatString = input.replaceAll('"', '\\"'); let variableMatches = formatString.match(variablePattern); if (!isDefined(variableMatches)) { return `"${formatString}"`; @@ -277,6 +304,40 @@ export function generateStarlarkFromGraph( return `"${formatString}".format(${references.join(", ")})`; }; + function objectToStarlark(o: any, indent: number) { + const padLeft = "".padStart(indent, " "); + if (!isDefined(o)) { + return "None"; + } + if (Array.isArray(o)) { + let result = `[`; + o.forEach((arrayValue) => { + result += `${objectToStarlark(arrayValue, indent + 4)},\n`; + }); + result += `${padLeft}],\n`; + return result; + } + if (typeof o === "number") { + return `${o}`; + } + if (typeof o === "string") { + return interpolateValue(o); + } + if (typeof o === "boolean") { + return o ? "True" : "False"; + } + if (typeof o === "object") { + let result = "{"; + Object.entries(o).forEach(([key, value]) => { + result += `\n${padLeft}${interpolateValue(key)}: ${objectToStarlark(value, indent + 4)},`; + }); + result += `${padLeft}}`; + return result; + } + + throw new Error(`Unable to convert the object ${o} to starlark`); + } + const renderImageConfig = (config: KurtosisImageConfig): string => { switch (config.type) { case "image": @@ -299,18 +360,31 @@ export function generateStarlarkFromGraph( } }; - let starlark = "def run(plan):\n"; + let starlark = ""; + const packageNodeData = sortedNodes + .map((n) => data[n.id]) + .filter((d) => d.type === "package") as KurtosisPackageNodeData[]; + for (const nodeData of packageNodeData) { + const module_name = `${normaliseNameToStarlarkVariable(nodeData.name)}_module`; + // Todo handle other paths + starlark += `${module_name} = import_module(${interpolateValue(nodeData.locator)})\n`; + } + if (packageNodeData.length > 0) { + starlark += "\n"; + } + + starlark += "def run(plan):\n"; for (const node of sortedNodes) { const nodeData = data[node.id]; if (nodeData.type === "service") { - const serviceName = normaliseNameToStarlarkVariable(nodeData.serviceName); + const serviceName = normaliseNameToStarlarkVariable(nodeData.name); starlark += ` ${serviceName} = plan.add_service(\n`; - starlark += ` name = ${interpolateValue(nodeData.serviceName)},\n`; + starlark += ` name = ${interpolateValue(nodeData.name)},\n`; starlark += ` config = ServiceConfig (\n`; starlark += ` image = ${renderImageConfig(nodeData.image)},\n`; starlark += ` ports = {\n`; - for (const { portName, port, applicationProtocol, transportProtocol } of nodeData.ports) { - starlark += ` ${interpolateValue(portName)}: PortSpec(\n`; + for (const { name, port, applicationProtocol, transportProtocol } of nodeData.ports) { + starlark += ` ${interpolateValue(name)}: PortSpec(\n`; starlark += ` number = ${port},\n`; starlark += ` transport_protocol = "${transportProtocol}",\n`; starlark += ` application_protocol = ${interpolateValue(applicationProtocol)},\n`; @@ -323,33 +397,32 @@ export function generateStarlarkFromGraph( } starlark += ` },\n`; starlark += ` files = {\n`; - for (const { mountPoint, artifactName } of nodeData.files) { - starlark += ` ${interpolateValue(mountPoint)}: ${interpolateValue(artifactName)},\n`; + for (const { mountPoint, name } of nodeData.files) { + starlark += ` ${interpolateValue(mountPoint)}: ${interpolateValue(name)},\n`; } starlark += ` },\n`; starlark += ` ),\n`; starlark += ` )\n\n`; + } - if (nodeData.execStepEnabled === "true") { - const execName = `${serviceName}_exec`; - starlark += ` ${execName} = plan.exec(\n`; - starlark += ` service_name = ${interpolateValue(nodeData.serviceName)},\n`; - starlark += ` recipe = ExecRecipe(\n`; - starlark += ` command = [${nodeData.execStepCommand.split(" ").map(interpolateValue).join(", ")}],`; - starlark += ` ),\n`; - if (nodeData.execStepAcceptableCodes.length > 0) { - starlark += ` acceptable_codes = [${nodeData.execStepAcceptableCodes - .map(({ value }) => value) - .join(", ")}],\n`; - } - starlark += ` )\n\n`; + if (nodeData.type === "exec") { + const serviceName = normaliseNameToStarlarkVariable(interpolateValue(nodeData.service).replace(/\.name$/, "")); + const execName = `${serviceName}_exec`; + starlark += ` ${execName} = plan.exec(\n`; + starlark += ` service_name = ${interpolateValue(nodeData.service)},\n`; + starlark += ` recipe = ExecRecipe(\n`; + starlark += ` command = [${nodeData.command.split(" ").map(interpolateValue).join(", ")}],`; + starlark += ` ),\n`; + if (nodeData.acceptableCodes.length > 0) { + starlark += ` acceptable_codes = [${nodeData.acceptableCodes.map(({ value }) => value).join(", ")}],\n`; } + starlark += ` )\n\n`; } if (nodeData.type === "artifact") { - const artifactName = normaliseNameToStarlarkVariable(nodeData.artifactName); + const artifactName = normaliseNameToStarlarkVariable(nodeData.name); starlark += ` ${artifactName} = plan.render_templates(\n`; - starlark += ` name = "${nodeData.artifactName}",\n`; + starlark += ` name = "${nodeData.name}",\n`; starlark += ` config = {\n`; for (const [fileName, fileText] of Object.entries(nodeData.files)) { starlark += ` "${fileName}": struct(\n`; @@ -362,7 +435,7 @@ export function generateStarlarkFromGraph( } if (nodeData.type === "shell") { - const shellName = normaliseNameToStarlarkVariable(nodeData.shellName); + const shellName = normaliseNameToStarlarkVariable(nodeData.name); starlark += ` ${shellName} = plan.run_sh(\n`; starlark += ` run = """${escapeString(nodeData.command)}""",\n`; const image = renderImageConfig(nodeData.image); @@ -375,13 +448,17 @@ export function generateStarlarkFromGraph( } starlark += ` },\n`; starlark += ` files = {\n`; - for (const { mountPoint, artifactName } of nodeData.files) { - starlark += ` ${interpolateValue(mountPoint)}: ${interpolateValue(artifactName)},\n`; + for (const { mountPoint, name } of nodeData.files) { + starlark += ` ${interpolateValue(mountPoint)}: ${interpolateValue(name)},\n`; } starlark += ` },\n`; - starlark += ` store = [\n`; - starlark += ` StoreSpec(src = ${interpolateValue(nodeData.store)}, name="${shellName}"),\n`; - starlark += ` ],\n`; + if (nodeData.store.length > 0) { + starlark += ` store = [\n`; + for (const { name, path } of nodeData.store) { + starlark += ` StoreSpec(src = ${interpolateValue(path)}, name="${name}"),\n`; + } + starlark += ` ],\n`; + } const wait = interpolateValue(nodeData.wait); if (nodeData.wait_enabled === "false" || wait !== '""') { starlark += ` wait=${nodeData.wait_enabled === "true" ? wait : "None"},\n`; @@ -390,7 +467,7 @@ export function generateStarlarkFromGraph( } if (nodeData.type === "python") { - const pythonName = normaliseNameToStarlarkVariable(nodeData.pythonName); + const pythonName = normaliseNameToStarlarkVariable(nodeData.name); starlark += ` ${pythonName} = plan.run_python(\n`; starlark += ` run = """${escapeString(nodeData.command)}""",\n`; const image = renderImageConfig(nodeData.image); @@ -408,13 +485,15 @@ export function generateStarlarkFromGraph( } starlark += ` ],\n`; starlark += ` files = {\n`; - for (const { mountPoint, artifactName } of nodeData.files) { - starlark += ` ${interpolateValue(mountPoint)}: ${interpolateValue(artifactName)},\n`; + for (const { mountPoint, name } of nodeData.files) { + starlark += ` ${interpolateValue(mountPoint)}: ${interpolateValue(name)},\n`; } starlark += ` },\n`; - if (nodeData.store !== "") { + if (nodeData.store.length > 0) { starlark += ` store = [\n`; - starlark += ` StoreSpec(src = ${interpolateValue(nodeData.store)}, name="${pythonName}"),\n`; + for (const { name, path } of nodeData.store) { + starlark += ` StoreSpec(src = ${interpolateValue(path)}, name="${name}"),\n`; + } starlark += ` ],\n`; } const wait = interpolateValue(nodeData.wait); @@ -423,14 +502,20 @@ export function generateStarlarkFromGraph( } starlark += ` )\n\n`; } + + if (nodeData.type === "package") { + const packageName = normaliseNameToStarlarkVariable(nodeData.name); + starlark += ` ${packageName} = ${packageName}_module.run(plan, **${objectToStarlark(nodeData.args, 8)}`; + starlark += ` )\n\n`; + } } // Delete any services from any existing enclave that aren't defined anymore if (isDefined(existingEnclave) && existingEnclave.services?.isOk) { for (const existingService of Object.values(existingEnclave.services.value.serviceInfo)) { - const serviceNoLongerExists = sortedNodes.every((node) => { + const serviceNoLongerExists = nodes.every((node) => { const nodeData = data[node.id]; - return nodeData.type !== "service" || nodeData.serviceName !== existingService.name; + return !isDefined(nodeData) || nodeData.type !== "service" || nodeData.name !== existingService.name; }); if (serviceNoLongerExists) { starlark += ` plan.remove_service(name = "${existingService.name}")\n`; diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/form/BooleanArgumentInput.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/form/BooleanArgumentInput.tsx index aaeddad9b1..1197a3b114 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/form/BooleanArgumentInput.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/form/BooleanArgumentInput.tsx @@ -19,21 +19,20 @@ export const BooleanArgumentInput = ({ return ( ); } else { return ( - + ({ ({ isRequired={true} size={"sm"} width={"222px"} + disabled={otherProps.disabled} /> ({ name={`${otherProps.name}.${i}.value` as any} validate={otherProps.validate} isRequired={true} + disabled={otherProps.disabled} size={"sm"} width={"222px"} /> - @@ -88,6 +97,7 @@ export const DictArgumentInput = ({ leftIcon={} size={"sm"} colorScheme={"kurtosisGreen"} + isDisabled={otherProps.disabled} variant={"outline"} > Add diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/form/IntegerArgumentInput.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/form/IntegerArgumentInput.tsx index cbbdd7fb9f..a4c37987be 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/form/IntegerArgumentInput.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/form/IntegerArgumentInput.tsx @@ -10,7 +10,6 @@ export const IntegerArgumentInput = (props: KurtosisFo return ( { if (isNaN(value)) { @@ -23,6 +22,7 @@ export const IntegerArgumentInput = (props: KurtosisFo } }, })} + isReadOnly={props.disabled} placeholder={props.placeholder} width={props.width} size={props.size || "lg"} diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/form/KurtosisFormControl.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/form/KurtosisFormControl.tsx index 78ac90cc92..ab6c2ad8c7 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/form/KurtosisFormControl.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/form/KurtosisFormControl.tsx @@ -66,12 +66,14 @@ type KurtosisSubtypeFormControlProps = PropsWithChildr name: FieldPath; disabled?: boolean; isRequired?: boolean; -}>; +}> & + FormControlProps; export const KurtosisSubtypeFormControl = ({ name, disabled, isRequired, children, + ...formControlProps }: KurtosisSubtypeFormControlProps) => { const { formState: { errors }, @@ -82,7 +84,13 @@ export const KurtosisSubtypeFormControl = ({ .reduce((e, part) => (isDefined(e) ? e[part] : undefined), errors as Record) as FieldError | undefined; return ( - + {children} ); diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/form/ListArgumentInput.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/form/ListArgumentInput.tsx index 6fa774def5..19842642a3 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/form/ListArgumentInput.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/form/ListArgumentInput.tsx @@ -10,16 +10,18 @@ import { KurtosisFormInputProps } from "./types"; type ListArgumentInputProps = KurtosisFormInputProps & { FieldComponent: FC>; createNewValue: () => object; + minLength?: number; }; export const ListArgumentInput = ({ FieldComponent, createNewValue, + minLength, ...otherProps }: ListArgumentInputProps) => { const toast = useToast(); const { getValues, setValue } = useFormContext(); - const { fields, append, remove } = useFieldArray({ name: otherProps.name }); + const { fields, append, remove } = useFieldArray({ name: otherProps.name, rules: { minLength: minLength } }); const handleValuePaste = (value: string) => { try { @@ -45,10 +47,23 @@ export const ListArgumentInput = ({ disabled={otherProps.disabled} isRequired={otherProps.isRequired} name={`${otherProps.name as `args.${string}`}.${i}`} + flex={1} > - + - @@ -60,6 +75,7 @@ export const ListArgumentInput = ({ colorScheme={"kurtosisGreen"} size={"sm"} variant={"outline"} + disabled={otherProps.disabled} > Add diff --git a/enclave-manager/web/packages/app/src/emui/enclaves/components/form/OptionArgumentInput.tsx b/enclave-manager/web/packages/app/src/emui/enclaves/components/form/OptionArgumentInput.tsx index 309adb5551..1c57387ee9 100644 --- a/enclave-manager/web/packages/app/src/emui/enclaves/components/form/OptionArgumentInput.tsx +++ b/enclave-manager/web/packages/app/src/emui/enclaves/components/form/OptionArgumentInput.tsx @@ -22,8 +22,7 @@ export const OptionsArgumentInput = ({ ({ const { register } = useFormContext(); return ( - {options.map((option) => (