Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: get all services #2367

Merged
merged 5 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,19 @@ func (itvs *InterpretationTimeValueStore) GetService(name service.ServiceName) (
}
return serviceStarlark, nil
}

func (itvs *InterpretationTimeValueStore) GetServices() ([]*kurtosis_types.Service, error) {
servicesStarlark, err := itvs.serviceValues.GetServices()
if err != nil {
tedim52 marked this conversation as resolved.
Show resolved Hide resolved
return nil, stacktrace.Propagate(err, "An error occurred fetching interpretation time service objects from db")
}
return servicesStarlark, nil
}

func (itvs *InterpretationTimeValueStore) RemoveService(name service.ServiceName) error {
err := itvs.serviceValues.RemoveService(name)
if err != nil {
return stacktrace.Propagate(err, "An error occurred removing interpretation time service object for service '%v'", name)
}
return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,49 @@ func (repository *serviceInterpretationValueRepository) GetService(name service.
}
logrus.Debugf("Successfully got value for '%v'", name)
return value, nil
}

func (repository *serviceInterpretationValueRepository) GetServices() ([]*kurtosis_types.Service, error) {
logrus.Debug("Getting all known interpretation time service values.")
var services []*kurtosis_types.Service

if err := repository.enclaveDb.View(func(tx *bolt.Tx) error {
bucket := tx.Bucket(serviceInterpretationValueBucketName)

return bucket.ForEach(func(serviceName, serializedValue []byte) error {
deserializedValue, interpretationErr := repository.starlarkValueSerde.Deserialize(string(serializedValue))
if interpretationErr != nil {
return stacktrace.Propagate(interpretationErr, "an error occurred while deserializing object associated with service '%v' in repository", serviceName)
}

kurtosisServiceValue, ok := deserializedValue.(*kurtosis_types.Service)
if !ok {
return stacktrace.NewError("an error occurred casting repository service value to kurtosis service value for service: %v", serviceName)
}

services = append(services, kurtosisServiceValue)
return nil
})
}); err != nil {
return nil, stacktrace.Propagate(err, "An error occurred while getting services values from repository.")
}
logrus.Debugf("Successfully retrieved interpretation time service values.")
return services, nil
}

func (repository *serviceInterpretationValueRepository) RemoveService(name service.ServiceName) error {
logrus.Debugf("Removing service value for '%v' from service value repository...", name)
if err := repository.enclaveDb.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(serviceInterpretationValueBucketName)

serviceNameKey := getKey(name)

return bucket.Delete(serviceNameKey)
}); err != nil {
return stacktrace.Propagate(err, "An error occurred while removing service '%v' from service value repository", name)
}
logrus.Debugf("Successfully removed service value for '%v'", name)
return nil
}

func getKey(name service.ServiceName) []byte {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package interpretation_time_value_store

import (
"fmt"
port_spec_core "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/port_spec"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/database_accessors/enclave_db"
Expand All @@ -16,7 +17,7 @@ import (

const (
starlarkThreadName = "thread-for-db-test"
serviceName = service.ServiceName("datastore-1")
serviceName = service.ServiceName("datastore")
serviceNameStarlarkStr = starlark.String(serviceName)
hostName = serviceNameStarlarkStr
ipAddress = starlark.String("172.23.34.44")
Expand Down Expand Up @@ -62,6 +63,84 @@ func TestPutGetFail_ForMissingServiceName(t *testing.T) {
require.Nil(t, actualService)
}

func TestGetServices(t *testing.T) {
repository := getServiceInterpretationTimeValueRepository(t)
require.NotNil(t, repository)

applicationProtocol := ""
maybeUrl := ""

port, interpretationErr := port_spec.CreatePortSpecUsingGoValues(
string(serviceName),
uint16(443),
port_spec_core.TransportProtocol_TCP,
&applicationProtocol,
"10s",
&maybeUrl,
)
require.Nil(t, interpretationErr)
ports := starlark.NewDict(1)
require.NoError(t, ports.SetKey(starlark.String("http"), port))

serviceOneName := fmt.Sprintf("%v-%v", serviceName, "1")
serviceOne, interpretationErr := kurtosis_types.CreateService(starlark.String(serviceOneName), hostName, ipAddress, ports)
require.Nil(t, interpretationErr)

serviceTwoName := fmt.Sprintf("%v-%v", serviceName, "2")
serviceTwo, interpretationErr := kurtosis_types.CreateService(starlark.String(serviceTwoName), hostName, ipAddress, ports)
require.Nil(t, interpretationErr)

err := repository.PutService(service.ServiceName(serviceOneName), serviceOne)
require.Nil(t, err)
err = repository.PutService(service.ServiceName(serviceTwoName), serviceTwo)
require.Nil(t, err)

actualServices, err := repository.GetServices()
require.NoError(t, err)
require.Len(t, actualServices, 2)

actualServiceOneName, err := actualServices[0].GetName()
require.Nil(t, err)
require.Equal(t, service.ServiceName(serviceOneName), actualServiceOneName)

actualServiceTwoName, err := actualServices[1].GetName()
require.Nil(t, err)
require.Equal(t, service.ServiceName(serviceTwoName), actualServiceTwoName)
}

func TestRemoveService(t *testing.T) {
repository := getServiceInterpretationTimeValueRepository(t)
require.NotNil(t, repository)

applicationProtocol := ""
maybeUrl := ""

port, interpretationErr := port_spec.CreatePortSpecUsingGoValues(
string(serviceName),
uint16(443),
port_spec_core.TransportProtocol_TCP,
&applicationProtocol,
"10s",
&maybeUrl,
)
require.Nil(t, interpretationErr)
ports := starlark.NewDict(1)
require.NoError(t, ports.SetKey(starlark.String("http"), port))

serviceOneName := fmt.Sprintf("%v-%v", serviceName, "1")
serviceOne, interpretationErr := kurtosis_types.CreateService(starlark.String(serviceOneName), hostName, ipAddress, ports)
require.Nil(t, interpretationErr)

err := repository.PutService(service.ServiceName(serviceOneName), serviceOne)
require.Nil(t, err)

err = repository.RemoveService(service.ServiceName(serviceOneName))
require.Nil(t, err)

_, err = repository.GetService(service.ServiceName(serviceOneName))
require.Error(t, err)
}
tedim52 marked this conversation as resolved.
Show resolved Hide resolved

func getServiceInterpretationTimeValueRepository(t *testing.T) *serviceInterpretationValueRepository {
file, err := os.CreateTemp("/tmp", "*.db")
defer func() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/exec"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/get_files_artifact"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/get_service"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/get_services"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/kurtosis_print"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/remove_service"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/render_templates"
Expand Down Expand Up @@ -71,11 +72,12 @@ func KurtosisPlanInstructions(
add_service.NewAddService(serviceNetwork, runtimeValueStore, packageId, packageContentProvider, packageReplaceOptions, interpretationTimeValueStore, imageDownloadMode),
add_service.NewAddServices(serviceNetwork, runtimeValueStore, packageId, packageContentProvider, packageReplaceOptions, interpretationTimeValueStore, imageDownloadMode),
get_service.NewGetService(interpretationTimeValueStore),
get_services.NewGetServices(interpretationTimeValueStore),
get_files_artifact.NewGetFilesArtifact(),
verify.NewVerify(runtimeValueStore),
exec.NewExec(serviceNetwork, runtimeValueStore),
kurtosis_print.NewPrint(serviceNetwork, runtimeValueStore),
remove_service.NewRemoveService(serviceNetwork),
remove_service.NewRemoveService(serviceNetwork, interpretationTimeValueStore),
render_templates.NewRenderTemplatesInstruction(serviceNetwork, runtimeValueStore),
request.NewRequest(serviceNetwork, runtimeValueStore),
start_service.NewStartService(serviceNetwork),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package get_services

import (
"context"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service"
"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/interpretation_time_value_store"
"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"
)

const (
GetServicesBuiltinName = "get_services"
descriptionStr = "Fetching services"
)

func NewGetServices(interpretationTimeStore *interpretation_time_value_store.InterpretationTimeValueStore) *kurtosis_plan_instruction.KurtosisPlanInstruction {
return &kurtosis_plan_instruction.KurtosisPlanInstruction{
KurtosisBaseBuiltin: &kurtosis_starlark_framework.KurtosisBaseBuiltin{
Name: GetServicesBuiltinName,
Arguments: []*builtin_argument.BuiltinArgument{},
Deprecation: nil,
},
Capabilities: func() kurtosis_plan_instruction.KurtosisPlanInstructionCapabilities {
return &GetServicesCapabilities{
interpretationTimeStore: interpretationTimeStore,
serviceNames: []service.ServiceName{}, // populated at interpretation time
description: "", // populated at interpretation time
}
},
DefaultDisplayArguments: map[string]bool{},
}
}

type GetServicesCapabilities struct {
interpretationTimeStore *interpretation_time_value_store.InterpretationTimeValueStore
serviceNames []service.ServiceName
description string
}

func (builtin *GetServicesCapabilities) Interpret(_ string, arguments *builtin_argument.ArgumentValuesSet) (starlark.Value, *startosis_errors.InterpretationError) {
builtin.description = builtin_argument.GetDescriptionOrFallBack(arguments, descriptionStr)

services, err := builtin.interpretationTimeStore.GetServices()
if err != nil {
return nil, startosis_errors.WrapWithInterpretationError(err, "An error occurred while fetching service.")
}
servicesList := &starlark.List{}
for _, serviceVal := range services {
name, err := serviceVal.GetName()
if err != nil {
return nil, startosis_errors.WrapWithInterpretationError(err, "An error occurred getting name of service: %v", serviceVal)
}
builtin.serviceNames = append(builtin.serviceNames, name)

_ = servicesList.Append(serviceVal)
}

return servicesList, nil
}

func (builtin *GetServicesCapabilities) Validate(_ *builtin_argument.ArgumentValuesSet, validatorEnvironment *startosis_validator.ValidatorEnvironment) *startosis_errors.ValidationError {
// validate if all services exist in the validation environment
for _, serviceName := range builtin.serviceNames {
if exists := validatorEnvironment.DoesServiceNameExist(serviceName); exists == startosis_validator.ComponentNotFound {
return startosis_errors.NewValidationError("Service '%v' required by '%v' instruction doesn't exist", serviceName, GetServicesBuiltinName)
}
}
return nil
}

func (builtin *GetServicesCapabilities) Execute(_ context.Context, _ *builtin_argument.ArgumentValuesSet) (string, error) {
// note: this is a no op
return descriptionStr, nil
}

func (builtin *GetServicesCapabilities) TryResolveWith(instructionsAreEqual bool, _ *enclave_plan_persistence.EnclavePlanInstruction, enclaveComponents *enclave_structure.EnclaveComponents) enclave_structure.InstructionResolutionStatus {
if instructionsAreEqual {
return enclave_structure.InstructionIsEqual
}
return enclave_structure.InstructionIsUnknown
}

func (builtin *GetServicesCapabilities) FillPersistableAttributes(builder *enclave_plan_persistence.EnclavePlanInstructionBuilder) {
builder.SetType(GetServicesBuiltinName)
}

func (builtin *GetServicesCapabilities) UpdatePlan(planYaml *plan_yaml.PlanYaml) error {
// get services does not affect the plan
return nil
}

func (builtin *GetServicesCapabilities) Description() string {
return builtin.description
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ 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/interpretation_time_value_store"
"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"
Expand All @@ -24,7 +25,7 @@ const (
descriptionFormatStr = "Removing service '%v'"
)

func NewRemoveService(serviceNetwork service_network.ServiceNetwork) *kurtosis_plan_instruction.KurtosisPlanInstruction {
func NewRemoveService(serviceNetwork service_network.ServiceNetwork, interpretationTimeStore *interpretation_time_value_store.InterpretationTimeValueStore) *kurtosis_plan_instruction.KurtosisPlanInstruction {
return &kurtosis_plan_instruction.KurtosisPlanInstruction{
KurtosisBaseBuiltin: &kurtosis_starlark_framework.KurtosisBaseBuiltin{
Name: RemoveServiceBuiltinName,
Expand All @@ -44,7 +45,8 @@ func NewRemoveService(serviceNetwork service_network.ServiceNetwork) *kurtosis_p

Capabilities: func() kurtosis_plan_instruction.KurtosisPlanInstructionCapabilities {
return &RemoveServiceCapabilities{
serviceNetwork: serviceNetwork,
serviceNetwork: serviceNetwork,
interpretationTimeStore: interpretationTimeStore,

serviceName: "", // populated at interpretation time
description: "", // populated at interpretation time
Expand All @@ -58,7 +60,8 @@ func NewRemoveService(serviceNetwork service_network.ServiceNetwork) *kurtosis_p
}

type RemoveServiceCapabilities struct {
serviceNetwork service_network.ServiceNetwork
serviceNetwork service_network.ServiceNetwork
interpretationTimeStore *interpretation_time_value_store.InterpretationTimeValueStore

serviceName service.ServiceName
description string
Expand All @@ -71,6 +74,10 @@ func (builtin *RemoveServiceCapabilities) Interpret(_ string, arguments *builtin
}

builtin.serviceName = service.ServiceName(serviceName.GoString())
err = builtin.interpretationTimeStore.RemoveService(builtin.serviceName)
if err != nil {
return nil, startosis_errors.WrapWithInterpretationError(err, "An error occurred removing '%v' from interpretation time store", builtin.serviceName)
}
builtin.description = builtin_argument.GetDescriptionOrFallBack(arguments, fmt.Sprintf(descriptionFormatStr, builtin.serviceName))
return starlark.None, nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package test_engine
import (
"fmt"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/interpretation_time_value_store"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/remove_service"
"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction"
"github.com/stretchr/testify/mock"
Expand All @@ -13,7 +14,8 @@ import (

type removeServiceTestCase struct {
*testing.T
serviceNetwork *service_network.MockServiceNetwork
serviceNetwork *service_network.MockServiceNetwork
interpretationTimeStore *interpretation_time_value_store.InterpretationTimeValueStore
}

func (suite *KurtosisPlanInstructionTestSuite) TestRemoveService() {
Expand All @@ -26,13 +28,14 @@ func (suite *KurtosisPlanInstructionTestSuite) TestRemoveService() {
)

suite.run(&removeServiceTestCase{
T: suite.T(),
serviceNetwork: suite.serviceNetwork,
T: suite.T(),
serviceNetwork: suite.serviceNetwork,
interpretationTimeStore: suite.interpretationTimeValueStore,
})
}

func (t *removeServiceTestCase) GetInstruction() *kurtosis_plan_instruction.KurtosisPlanInstruction {
return remove_service.NewRemoveService(t.serviceNetwork)
return remove_service.NewRemoveService(t.serviceNetwork, t.interpretationTimeStore)
}

func (t *removeServiceTestCase) GetStarlarkCode() string {
Expand Down
Loading