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 67899f15df..a857101c35 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_builtins.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_builtins.go @@ -90,5 +90,6 @@ func KurtosisTypeConstructors() []*starlark.Builtin { starlark.NewBuiltin(port_spec.PortSpecTypeName, port_spec.NewPortSpecType().CreateBuiltin()), starlark.NewBuiltin(service_config.ServiceConfigTypeName, service_config.NewServiceConfigType().CreateBuiltin()), starlark.NewBuiltin(update_service_config.UpdateServiceConfigTypeName, update_service_config.NewUpdateServiceConfigType().CreateBuiltin()), + starlark.NewBuiltin(service_config.ReadyConditionsTypeName, service_config.NewReadyConditionsType().CreateBuiltin()), } } diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/validators.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/validators.go index 6eff28dc3a..dff80b4f97 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/validators.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/validators.go @@ -6,6 +6,7 @@ import ( "reflect" "regexp" "strings" + "time" ) func NonEmptyString(value starlark.Value, argNameForLogging string) *startosis_errors.InterpretationError { @@ -79,3 +80,21 @@ func StringRegexp(value starlark.Value, argNameForLogging string, mustMatchRegex valueStr.GoString(), ) } + +func Duration(value starlark.Value, attributeName string) *startosis_errors.InterpretationError { + valueStarlarkStr, ok := value.(starlark.String) + if !ok { + return startosis_errors.NewInterpretationError("The '%s' attribute is not a valid string type (was '%s').", attributeName, reflect.TypeOf(value)) + } + + if valueStarlarkStr.GoString() == "" { + return nil + } + + _, parseErr := time.ParseDuration(valueStarlarkStr.GoString()) + if parseErr != nil { + return startosis_errors.WrapWithInterpretationError(parseErr, "The value '%v' of '%s' attribute is not a valid duration string format", valueStarlarkStr.GoString(), attributeName) + } + + return nil +} diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/ready_conditions_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/ready_conditions_framework_test.go new file mode 100644 index 0000000000..9711be4bb4 --- /dev/null +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/ready_conditions_framework_test.go @@ -0,0 +1,120 @@ +package test_engine + +import ( + "fmt" + "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/service_config" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/recipe" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.starlark.net/starlark" + "testing" + "time" +) + +type readyConditionsTestCase struct { + *testing.T +} + +func newReadyConditionsTestCase(t *testing.T) *readyConditionsTestCase { + return &readyConditionsTestCase{ + T: t, + } +} + +func (t *readyConditionsTestCase) GetId() string { + return service_config.ReadyConditionsTypeName +} + +func (t *readyConditionsTestCase) GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor { + return service_config.NewReadyConditionsType() +} + +func (t *readyConditionsTestCase) GetStarlarkCode() string { + return fmt.Sprintf("%s(%s=%s(%s=%q, %s=%q, %s=%s), %s=%q, %s=%q, %s=%s, %s=%q, %s=%q)", + service_config.ReadyConditionsTypeName, + service_config.RecipeAttr, + recipe.GetHttpRecipeTypeName, + recipe.PortIdAttr, + TestReadyConditionsRecipePortId, + recipe.EndpointAttr, + TestReadyConditionsRecipeEndpoint, + recipe.ExtractKeyPrefix, + TestReadyConditionsRecipeExtract, + service_config.FieldAttr, + TestReadyConditionsField, + service_config.AssertionAttr, + TestReadyConditionsAssertion, + service_config.TargetAttr, + TestReadyConditionsTarget, + service_config.IntervalAttr, + TestReadyConditionsInterval, + service_config.TimeoutAttr, + TestReadyConditionsTimeout, + ) +} + +func (t *readyConditionsTestCase) Assert(typeValue starlark.Value) { + receivedReadyConditions, ok := typeValue.(*service_config.ReadyConditions) + require.True(t, ok) + + uncastedRecipe, err := receivedReadyConditions.GetRecipe() + if assert.Nil(t, err) { + castedRecipe, ok := uncastedRecipe.(*recipe.HttpRequestRecipe) + require.True(t, ok) + + portIdAttrValue, err := castedRecipe.Attr(recipe.PortIdAttr) + if assert.Nil(t, err) { + portId, ok := portIdAttrValue.(starlark.String) + require.True(t, ok) + require.Equal(t, TestReadyConditionsRecipePortId, portId.GoString()) + } + + endpointAttrValue, err := castedRecipe.Attr(recipe.EndpointAttr) + if assert.Nil(t, err) { + endpoint, ok := endpointAttrValue.(starlark.String) + require.True(t, ok) + require.Equal(t, TestReadyConditionsRecipeEndpoint, endpoint.GoString()) + } + + extractAttrValue, err := castedRecipe.Attr(recipe.ExtractKeyPrefix) + if assert.Nil(t, err) { + extract, ok := extractAttrValue.(*starlark.Dict) + require.True(t, ok) + expectedExtractLen := 0 + require.Equal(t, expectedExtractLen, extract.Len()) + } + } + + field, err := receivedReadyConditions.GetField() + if assert.Nil(t, err) { + require.Equal(t, TestReadyConditionsField, field) + } + + assertion, err := receivedReadyConditions.GetAssertion() + if assert.Nil(t, err) { + require.Equal(t, TestReadyConditionsAssertion, assertion) + } + + target, err := receivedReadyConditions.GetTarget() + if assert.Nil(t, err) { + require.Equal(t, TestReadyConditionsTarget, target.String()) + } + + interval, err := receivedReadyConditions.GetInterval() + if assert.Nil(t, err) { + expectedInterval, err := time.ParseDuration(TestReadyConditionsInterval) + if assert.Nil(t, err) { + require.Equal(t, expectedInterval, interval) + } + } + + timeout, err := receivedReadyConditions.GetTimeout() + if assert.Nil(t, err) { + expectedTimeout, err := time.ParseDuration(TestReadyConditionsTimeout) + if assert.Nil(t, err) { + require.Equal(t, expectedTimeout, timeout) + } + } + +} diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/starlark_framework_engine_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/starlark_framework_engine_test.go index 77ad005a08..615568493c 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/starlark_framework_engine_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/starlark_framework_engine_test.go @@ -57,6 +57,7 @@ func TestAllRegisteredBuiltins(t *testing.T) { testKurtosisTypeConstructor(t, newServiceConfigFullTestCase(t)) testKurtosisTypeConstructor(t, newUniformPacketDelayDistributionTestCase(t)) testKurtosisTypeConstructor(t, newUpdateServiceConfigTestCase(t)) + testKurtosisTypeConstructor(t, newReadyConditionsTestCase(t)) } func testKurtosisPlanInstruction(t *testing.T, builtin KurtosisPlanInstructionBaseTest) { diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/static_constants_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/static_constants_test.go index aa577536db..c6a1ef4751 100644 --- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/static_constants_test.go +++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/static_constants_test.go @@ -66,4 +66,13 @@ var ( TestCpuAllocation = uint64(2000) TestMemoryAllocation = uint64(1024) + + TestReadyConditionsRecipePortId = "http" + TestReadyConditionsRecipeEndpoint = "/endpoint?input=data" + TestReadyConditionsRecipeExtract = "{}" + TestReadyConditionsField = "code" + TestReadyConditionsAssertion = "==" + TestReadyConditionsTarget = "200" + TestReadyConditionsInterval = "1s" + TestReadyConditionsTimeout = "100ms" ) diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/ready_conditions.go b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/ready_conditions.go new file mode 100644 index 0000000000..d13c449642 --- /dev/null +++ b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/ready_conditions.go @@ -0,0 +1,207 @@ +package service_config + +import ( + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/assert" + "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/recipe" + "github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors" + "go.starlark.net/starlark" + "reflect" + "time" +) + +const ( + ReadyConditionsTypeName = "ReadyConditions" + + RecipeAttr = "recipe" + FieldAttr = "field" + AssertionAttr = "assertion" + TargetAttr = "target_value" + IntervalAttr = "interval" + TimeoutAttr = "timeout" + + defaultInterval = 1 * time.Second + defaultTimeout = 15 * time.Minute //TODO we could move these two to the service helpers method +) + +func NewReadyConditionsType() *kurtosis_type_constructor.KurtosisTypeConstructor { + return &kurtosis_type_constructor.KurtosisTypeConstructor{ + KurtosisBaseBuiltin: &kurtosis_starlark_framework.KurtosisBaseBuiltin{ + Name: ReadyConditionsTypeName, + Arguments: []*builtin_argument.BuiltinArgument{ + { + Name: RecipeAttr, + IsOptional: false, + ZeroValueProvider: builtin_argument.ZeroValueProvider[starlark.Value], + Validator: validateRecipe, + }, + { + Name: FieldAttr, + IsOptional: false, + ZeroValueProvider: builtin_argument.ZeroValueProvider[starlark.String], + Validator: func(value starlark.Value) *startosis_errors.InterpretationError { + return builtin_argument.NonEmptyString(value, FieldAttr) + }, + }, + { + Name: AssertionAttr, + IsOptional: false, + ZeroValueProvider: builtin_argument.ZeroValueProvider[starlark.String], + Validator: assert.ValidateAssertionToken, + }, + { + Name: TargetAttr, + IsOptional: false, + ZeroValueProvider: builtin_argument.ZeroValueProvider[starlark.Comparable], + Validator: func(value starlark.Value) *startosis_errors.InterpretationError { + return builtin_argument.NonEmptyString(value, FieldAttr) + }, + }, + { + Name: IntervalAttr, + IsOptional: true, + ZeroValueProvider: builtin_argument.ZeroValueProvider[starlark.String], + Validator: func(value starlark.Value) *startosis_errors.InterpretationError { + return builtin_argument.Duration(value, IntervalAttr) + }, + }, + { + Name: TimeoutAttr, + IsOptional: true, + ZeroValueProvider: builtin_argument.ZeroValueProvider[starlark.String], + Validator: func(value starlark.Value) *startosis_errors.InterpretationError { + return builtin_argument.Duration(value, TimeoutAttr) + }, + }, + }, + }, + Instantiate: instantiateReadyConditions, + } +} + +func instantiateReadyConditions(arguments *builtin_argument.ArgumentValuesSet) (kurtosis_type_constructor.KurtosisValueType, *startosis_errors.InterpretationError) { + kurtosisValueType, err := kurtosis_type_constructor.CreateKurtosisStarlarkTypeDefault(ReadyConditionsTypeName, arguments) + if err != nil { + return nil, err + } + return &ReadyConditions{ + KurtosisValueTypeDefault: kurtosisValueType, + }, nil +} + +// ReadyConditions is a starlark.Value that holds all the information needed for ensuring service readiness +type ReadyConditions struct { + *kurtosis_type_constructor.KurtosisValueTypeDefault +} + +func (readyConditions *ReadyConditions) GetRecipe() (recipe.Recipe, *startosis_errors.InterpretationError) { + var genericRecipe recipe.Recipe + + httpRecipe, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[*recipe.HttpRequestRecipe](readyConditions.KurtosisValueTypeDefault, RecipeAttr) + genericRecipe = httpRecipe + if !found { + return nil, startosis_errors.NewInterpretationError("Required attribute '%s' could not be found on type '%s'", + RecipeAttr, ReadyConditionsTypeName) + } + //TODO we should rework the recipe types to inherit a single common type, this will avoid the double parsing here. + if interpretationErr != nil { + execRecipe, _, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[*recipe.ExecRecipe](readyConditions.KurtosisValueTypeDefault, RecipeAttr) + if interpretationErr != nil { + return nil, interpretationErr + } + genericRecipe = execRecipe + } + + return genericRecipe, nil +} + +func (readyConditions *ReadyConditions) GetField() (string, *startosis_errors.InterpretationError) { + field, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.String](readyConditions.KurtosisValueTypeDefault, FieldAttr) + if interpretationErr != nil { + return "", interpretationErr + } + if !found { + return "", startosis_errors.NewInterpretationError("Required attribute '%s' could not be found on type '%s'", + FieldAttr, ReadyConditionsTypeName) + } + fieldStr := field.GoString() + + return fieldStr, nil +} + +func (readyConditions *ReadyConditions) GetAssertion() (string, *startosis_errors.InterpretationError) { + assertion, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.String](readyConditions.KurtosisValueTypeDefault, AssertionAttr) + if interpretationErr != nil { + return "", interpretationErr + } + if !found { + return "", startosis_errors.NewInterpretationError("Required attribute '%s' could not be found on type '%s'", + AssertionAttr, ReadyConditionsTypeName) + } + assertionStr := assertion.GoString() + + return assertionStr, nil +} + +func (readyConditions *ReadyConditions) GetTarget() (starlark.Comparable, *startosis_errors.InterpretationError) { + target, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.Comparable](readyConditions.KurtosisValueTypeDefault, TargetAttr) + if interpretationErr != nil { + return nil, interpretationErr + } + if !found { + return nil, startosis_errors.NewInterpretationError("Required attribute '%s' could not be found on type '%s'", + TargetAttr, ReadyConditionsTypeName) + } + + return target, nil +} + +func (readyConditions *ReadyConditions) GetInterval() (time.Duration, *startosis_errors.InterpretationError) { + interval := defaultInterval + + intervalStr, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.String](readyConditions.KurtosisValueTypeDefault, IntervalAttr) + if interpretationErr != nil { + return interval, interpretationErr + } + if found { + parsedInterval, parseErr := time.ParseDuration(intervalStr.GoString()) + if parseErr != nil { + return interval, startosis_errors.WrapWithInterpretationError(parseErr, "An error occurred when parsing interval '%v'", intervalStr.GoString()) + } + interval = parsedInterval + } + + return interval, nil +} + +func (readyConditions *ReadyConditions) GetTimeout() (time.Duration, *startosis_errors.InterpretationError) { + timeout := defaultTimeout + + timeoutStr, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.String](readyConditions.KurtosisValueTypeDefault, TimeoutAttr) + if interpretationErr != nil { + return timeout, interpretationErr + } + if found { + parsedTimeout, parseErr := time.ParseDuration(timeoutStr.GoString()) + if parseErr != nil { + return timeout, startosis_errors.WrapWithInterpretationError(parseErr, "An error occurred when parsing timeout '%v'", timeoutStr.GoString()) + } + timeout = parsedTimeout + } + + return timeout, nil +} + +func validateRecipe(value starlark.Value) *startosis_errors.InterpretationError { + _, ok := value.(*recipe.HttpRequestRecipe) + if !ok { + //TODO we should rework the recipe types to inherit a single common type, this will avoid the double parsing here. + _, ok := value.(*recipe.ExecRecipe) + if !ok { + return startosis_errors.NewInterpretationError("The '%s' attribute is not a Recipe (was '%s').", RecipeAttr, reflect.TypeOf(value)) + } + } + return 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 1a5a71c145..f6b76f96eb 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 @@ -27,6 +27,7 @@ const ( SubnetworkAttr = "subnetwork" CpuAllocationAttr = "cpu_allocation" MemoryAllocationAttr = "memory_allocation" + ReadyConditionsAttr = "ready_conditions" ) func NewServiceConfigType() *kurtosis_type_constructor.KurtosisTypeConstructor { @@ -111,14 +112,20 @@ func NewServiceConfigType() *kurtosis_type_constructor.KurtosisTypeConstructor { return builtin_argument.Uint64InRange(value, MemoryAllocationAttr, 6, math.MaxUint64) }, }, + { + Name: ReadyConditionsAttr, + IsOptional: true, + ZeroValueProvider: builtin_argument.ZeroValueProvider[*ReadyConditions], + Validator: nil, + }, }, }, - Instantiate: instantiate, + Instantiate: instantiateServiceConfig, } } -func instantiate(arguments *builtin_argument.ArgumentValuesSet) (kurtosis_type_constructor.KurtosisValueType, *startosis_errors.InterpretationError) { +func instantiateServiceConfig(arguments *builtin_argument.ArgumentValuesSet) (kurtosis_type_constructor.KurtosisValueType, *startosis_errors.InterpretationError) { kurtosisValueType, err := kurtosis_type_constructor.CreateKurtosisStarlarkTypeDefault(ServiceConfigTypeName, arguments) if err != nil { return nil, err @@ -268,6 +275,18 @@ func (config *ServiceConfig) ToKurtosisType() (*kurtosis_core_rpc_api_bindings.S return builder.Build(), nil } +func (config *ServiceConfig) GetReadyConditions() (*ReadyConditions, *startosis_errors.InterpretationError) { + readyConditions, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[*ReadyConditions](config.KurtosisValueTypeDefault, ReadyConditionsAttr) + if interpretationErr != nil { + return nil, interpretationErr + } + if !found { + return nil, nil + } + + return readyConditions, nil +} + func convertPortMapEntry(attrNameForLogging string, key starlark.Value, value starlark.Value, dictForLogging *starlark.Dict) (string, *kurtosis_core_rpc_api_bindings.Port, *startosis_errors.InterpretationError) { keyStr, ok := key.(starlark.String) if !ok { diff --git a/core/server/api_container/server/startosis_engine/recipe/http_request_recipe.go b/core/server/api_container/server/startosis_engine/recipe/http_request_recipe.go index be5d8e2789..63ac9281f9 100644 --- a/core/server/api_container/server/startosis_engine/recipe/http_request_recipe.go +++ b/core/server/api_container/server/startosis_engine/recipe/http_request_recipe.go @@ -27,11 +27,11 @@ const ( statusCodeKey = "code" bodyKey = "body" - extractKeyPrefix = "extract" + ExtractKeyPrefix = "extract" - portIdAttr = "port_id" + PortIdAttr = "port_id" serviceNameAttr = "service_name" - endpointAttr = "endpoint" + EndpointAttr = "endpoint" methodAttr = "method" contentTypeAttr = "content_type" @@ -78,10 +78,10 @@ func (recipe *HttpRequestRecipe) String() string { instanceName := recipe.GetInstanceName() buffer.WriteString(instanceName + "(") - buffer.WriteString(portIdAttr + "=") + buffer.WriteString(PortIdAttr + "=") buffer.WriteString(fmt.Sprintf("%q, ", recipe.portId)) - buffer.WriteString(endpointAttr + "=") + buffer.WriteString(EndpointAttr + "=") buffer.WriteString(fmt.Sprintf("%q, ", recipe.endpoint)) if recipe.method == postMethod { @@ -91,7 +91,7 @@ func (recipe *HttpRequestRecipe) String() string { buffer.WriteString(fmt.Sprintf("%q, ", recipe.contentType)) } - buffer.WriteString(extractKeyPrefix + "=") + buffer.WriteString(ExtractKeyPrefix + "=") extractors, err := convertMapToStarlarkDict(recipe.extractors) if err != nil { @@ -101,7 +101,7 @@ func (recipe *HttpRequestRecipe) String() string { if extractors.Len() > 0 { buffer.WriteString(fmt.Sprintf("%v)", extractors)) } else { - buffer.WriteString(fmt.Sprintf("%q)", "")) + buffer.WriteString(fmt.Sprintf("%s)", "{}")) } return buffer.String() } @@ -142,9 +142,9 @@ func (recipe *HttpRequestRecipe) GetInstanceName() string { // Attr implements the starlark.HasAttrs interface. func (recipe *HttpRequestRecipe) Attr(name string) (starlark.Value, error) { switch name { - case portIdAttr: + case PortIdAttr: return starlark.String(recipe.portId), nil - case extractKeyPrefix: + case ExtractKeyPrefix: return convertMapToStarlarkDict(recipe.extractors) case bodyKey: return starlark.String(recipe.body), nil @@ -152,7 +152,7 @@ func (recipe *HttpRequestRecipe) Attr(name string) (starlark.Value, error) { return starlark.String(recipe.contentType), nil case methodAttr: return starlark.String(recipe.method), nil - case endpointAttr: + case EndpointAttr: return starlark.String(recipe.endpoint), nil default: return nil, startosis_errors.NewInterpretationError("'%v' has no attribute '%v;", HttpRecipeTypeName, name) @@ -161,7 +161,7 @@ func (recipe *HttpRequestRecipe) Attr(name string) (starlark.Value, error) { // AttrNames implements the starlark.HasAttrs interface. func (recipe *HttpRequestRecipe) AttrNames() []string { - return []string{portIdAttr, serviceNameAttr, extractKeyPrefix, endpointAttr, contentTypeAttr, methodAttr, bodyKey} + return []string{PortIdAttr, serviceNameAttr, ExtractKeyPrefix, EndpointAttr, contentTypeAttr, methodAttr, bodyKey} } func MakeGetHttpRequestRecipe(_ *starlark.Thread, builtin *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { @@ -170,9 +170,9 @@ func MakeGetHttpRequestRecipe(_ *starlark.Thread, builtin *starlark.Builtin, arg var maybeExtractField starlark.Value if err := starlark.UnpackArgs(builtin.Name(), args, kwargs, - portIdAttr, &portId, - endpointAttr, &endpoint, - kurtosis_types.MakeOptional(extractKeyPrefix), &maybeExtractField, + PortIdAttr, &portId, + EndpointAttr, &endpoint, + kurtosis_types.MakeOptional(ExtractKeyPrefix), &maybeExtractField, ); err != nil { return nil, startosis_errors.NewInterpretationError(err.Error()) } @@ -181,7 +181,7 @@ func MakeGetHttpRequestRecipe(_ *starlark.Thread, builtin *starlark.Builtin, arg var err *startosis_errors.InterpretationError if maybeExtractField != nil { - extractedMap, err = kurtosis_types.SafeCastToMapStringString(maybeExtractField, extractKeyPrefix) + extractedMap, err = kurtosis_types.SafeCastToMapStringString(maybeExtractField, ExtractKeyPrefix) if err != nil { return nil, err } @@ -199,11 +199,11 @@ func MakePostHttpRequestRecipe(_ *starlark.Thread, builtin *starlark.Builtin, ar var maybeExtractField starlark.Value if err := starlark.UnpackArgs(builtin.Name(), args, kwargs, - portIdAttr, &portId, - endpointAttr, &endpoint, + PortIdAttr, &portId, + EndpointAttr, &endpoint, bodyKey, &body, contentTypeAttr, &contentType, - kurtosis_types.MakeOptional(extractKeyPrefix), &maybeExtractField, + kurtosis_types.MakeOptional(ExtractKeyPrefix), &maybeExtractField, ); err != nil { return nil, startosis_errors.NewInterpretationError("%v", err.Error()) } @@ -212,7 +212,7 @@ func MakePostHttpRequestRecipe(_ *starlark.Thread, builtin *starlark.Builtin, ar var err *startosis_errors.InterpretationError if maybeExtractField != nil { - extractedMap, err = kurtosis_types.SafeCastToMapStringString(maybeExtractField, extractKeyPrefix) + extractedMap, err = kurtosis_types.SafeCastToMapStringString(maybeExtractField, ExtractKeyPrefix) if err != nil { return nil, err } @@ -273,7 +273,7 @@ func (recipe *HttpRequestRecipe) Execute( return nil, stacktrace.Propagate(err, "An error occurred while running extractors on HTTP response body") } for extractorKey, extractorValue := range extractDict { - resultDict[fmt.Sprintf("%v.%v", extractKeyPrefix, extractorKey)] = extractorValue + resultDict[fmt.Sprintf("%v.%v", ExtractKeyPrefix, extractorKey)] = extractorValue } return resultDict, nil } @@ -339,7 +339,7 @@ func (recipe *HttpRequestRecipe) ResultMapToString(resultMap map[string]starlark body := resultMap[bodyKey] extractedFieldString := strings.Builder{} for resultKey, resultValue := range resultMap { - if strings.Contains(resultKey, extractKeyPrefix) { + if strings.Contains(resultKey, ExtractKeyPrefix) { extractedFieldString.WriteString(fmt.Sprintf("\n'%v': %v", resultKey, resultValue)) } } @@ -361,7 +361,7 @@ func (recipe *HttpRequestRecipe) CreateStarlarkReturnValue(resultUuid string) (* return nil, startosis_errors.NewInterpretationError("An error has occurred when creating return value for request recipe, setting field '%v'", statusCodeKey) } for extractorKey := range recipe.extractors { - fullExtractorKey := fmt.Sprintf("%v.%v", extractKeyPrefix, extractorKey) + fullExtractorKey := fmt.Sprintf("%v.%v", ExtractKeyPrefix, extractorKey) err = dict.SetKey(starlark.String(fullExtractorKey), starlark.String(fmt.Sprintf(magic_string_helper.RuntimeValueReplacementPlaceholderFormat, resultUuid, fullExtractorKey))) if err != nil { return nil, startosis_errors.NewInterpretationError("An error has occurred when creating return value for request recipe, setting field '%v'", fullExtractorKey) diff --git a/core/server/api_container/server/startosis_engine/recipe/http_request_recipe_test.go b/core/server/api_container/server/startosis_engine/recipe/http_request_recipe_test.go index d07ecebcf7..d0110758bd 100644 --- a/core/server/api_container/server/startosis_engine/recipe/http_request_recipe_test.go +++ b/core/server/api_container/server/startosis_engine/recipe/http_request_recipe_test.go @@ -15,11 +15,11 @@ func TestGetHttpRequestRecipe_String(t *testing.T) { builtin.Name() kwargs := []starlark.Tuple{ starlark.Tuple([]starlark.Value{ - starlark.String(endpointAttr), + starlark.String(EndpointAttr), starlark.String("?input=output"), }), starlark.Tuple([]starlark.Value{ - starlark.String(portIdAttr), + starlark.String(PortIdAttr), starlark.String("portId"), }), } @@ -35,15 +35,15 @@ func TestGetHttpRequestRecipe_String(t *testing.T) { require.Nil(t, err) kwargsWithExtractors := []starlark.Tuple{ starlark.Tuple([]starlark.Value{ - starlark.String(endpointAttr), + starlark.String(EndpointAttr), starlark.String("?input=output"), }), starlark.Tuple([]starlark.Value{ - starlark.String(portIdAttr), + starlark.String(PortIdAttr), starlark.String("portId"), }), starlark.Tuple([]starlark.Value{ - starlark.String(extractKeyPrefix), + starlark.String(ExtractKeyPrefix), extractors, }), } @@ -60,11 +60,11 @@ func TestPostHttpRequestRecipe_String(t *testing.T) { builtin := &starlark.Builtin{} kwargs := []starlark.Tuple{ starlark.Tuple([]starlark.Value{ - starlark.String(endpointAttr), + starlark.String(EndpointAttr), starlark.String("?input=output"), }), starlark.Tuple([]starlark.Value{ - starlark.String(portIdAttr), + starlark.String(PortIdAttr), starlark.String("portId"), }), starlark.Tuple([]starlark.Value{ @@ -88,15 +88,15 @@ func TestPostHttpRequestRecipe_String(t *testing.T) { require.Nil(t, err) kwargsWithExtractors := []starlark.Tuple{ starlark.Tuple([]starlark.Value{ - starlark.String(endpointAttr), + starlark.String(EndpointAttr), starlark.String("?input=output"), }), starlark.Tuple([]starlark.Value{ - starlark.String(portIdAttr), + starlark.String(PortIdAttr), starlark.String("portId"), }), starlark.Tuple([]starlark.Value{ - starlark.String(extractKeyPrefix), + starlark.String(ExtractKeyPrefix), extractors, }), starlark.Tuple([]starlark.Value{ @@ -121,7 +121,7 @@ func TestStartosisInterpreter_HttpRequestMissingRequiredFields(t *testing.T) { builtin := &starlark.Builtin{} kwargs := []starlark.Tuple{ starlark.Tuple([]starlark.Value{ - starlark.String(endpointAttr), + starlark.String(EndpointAttr), starlark.String("?input=output"), }), } @@ -138,15 +138,15 @@ func TestStartosisInterpreter_MissingRequiredFieldForHttpRecipeWithPostMethod(t require.Nil(t, err) kwargsWithoutBody := []starlark.Tuple{ starlark.Tuple([]starlark.Value{ - starlark.String(endpointAttr), + starlark.String(EndpointAttr), starlark.String("?input=output"), }), starlark.Tuple([]starlark.Value{ - starlark.String(portIdAttr), + starlark.String(PortIdAttr), starlark.String("portId"), }), starlark.Tuple([]starlark.Value{ - starlark.String(extractKeyPrefix), + starlark.String(ExtractKeyPrefix), extractors, }), starlark.Tuple([]starlark.Value{ diff --git a/internal_testsuites/golang/testsuite/startosis_subpackage_test/startosis_remote_subpackage_test.go b/internal_testsuites/golang/testsuite/startosis_subpackage_test/startosis_remote_subpackage_test.go index c43b8ac6e3..e483d347f2 100644 --- a/internal_testsuites/golang/testsuite/startosis_subpackage_test/startosis_remote_subpackage_test.go +++ b/internal_testsuites/golang/testsuite/startosis_subpackage_test/startosis_remote_subpackage_test.go @@ -11,7 +11,7 @@ import ( const ( remoteTestName = "subpackage-remote" - remotePackage = "github.com/kurtosis-tech/examples/quickstart" + remotePackage = "github.com/kurtosis-tech/awesome-kurtosis/quickstart" emptyParams = "{}" expectedOutputLength = 3