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: added a way to restart services #1920

Closed
wants to merge 8 commits into from
Closed
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
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,7 @@ jobs:
# Service stop and start
- run: "${KURTOSIS_BINPATH} service stop test-enclave test1"
- run: "${KURTOSIS_BINPATH} service start test-enclave test1"
- run: "${KURTOSIS_BINPATH} service restart test-enclave test1"

# Service inspect
- run: "${KURTOSIS_BINPATH} service inspect test-enclave test1"
Expand Down
1 change: 1 addition & 0 deletions cli/cli/command_str_consts/command_str_consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const (
ServiceRmCmdStr = "rm"
ServiceShellCmdStr = "shell"
ServiceStartCmdStr = "start"
ServiceRestartCmdStr = "restart"
ServiceStopCmdStr = "stop"
ServiceInspectCmdStr = "inspect"
StarlarkRunCmdStr = "run"
Expand Down
127 changes: 127 additions & 0 deletions cli/cli/commands/service/restart/restart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package restart

import (
"context"
"fmt"
"github.com/kurtosis-tech/kurtosis/api/golang/core/lib/starlark_run_config"
"github.com/sirupsen/logrus"

"github.com/kurtosis-tech/kurtosis/api/golang/core/lib/enclaves"
"github.com/kurtosis-tech/kurtosis/api/golang/core/lib/services"
"github.com/kurtosis-tech/kurtosis/api/golang/engine/kurtosis_engine_rpc_api_bindings"
"github.com/kurtosis-tech/kurtosis/api/golang/engine/lib/kurtosis_context"
"github.com/kurtosis-tech/kurtosis/cli/cli/command_framework/highlevel/enclave_id_arg"
"github.com/kurtosis-tech/kurtosis/cli/cli/command_framework/highlevel/engine_consuming_kurtosis_command"
"github.com/kurtosis-tech/kurtosis/cli/cli/command_framework/highlevel/service_identifier_arg"
"github.com/kurtosis-tech/kurtosis/cli/cli/command_framework/lowlevel/args"
"github.com/kurtosis-tech/kurtosis/cli/cli/command_framework/lowlevel/flags"
"github.com/kurtosis-tech/kurtosis/cli/cli/command_str_consts"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface"
"github.com/kurtosis-tech/kurtosis/metrics-library/golang/lib/metrics_client"
"github.com/kurtosis-tech/stacktrace"
)

const (
enclaveIdentifierArgKey = "enclave"
isEnclaveIdArgOptional = false
isEnclaveIdArgGreedy = false

serviceIdentifierArgKey = "service"
isServiceIdentifierArgOptional = false
isServiceIdentifierArgGreedy = true

kurtosisBackendCtxKey = "kurtosis-backend"
engineClientCtxKey = "engine-client"

starlarkScript = `
def run(plan, args):
plan.stop_service(name=args["service_name"])
plan.start_service(name=args["service_name"])
`
)

var ServiceRestartCmd = &engine_consuming_kurtosis_command.EngineConsumingKurtosisCommand{
CommandStr: command_str_consts.ServiceRestartCmdStr,
ShortDescription: "Restarts one or many services",
LongDescription: "Restarts services with the given service identifiers in the given enclave",
KurtosisBackendContextKey: kurtosisBackendCtxKey,
EngineClientContextKey: engineClientCtxKey,
Args: []*args.ArgConfig{
enclave_id_arg.NewEnclaveIdentifierArg(
enclaveIdentifierArgKey,
engineClientCtxKey,
isEnclaveIdArgOptional,
isEnclaveIdArgGreedy,
),
service_identifier_arg.NewServiceIdentifierArg(
serviceIdentifierArgKey,
enclaveIdentifierArgKey,
isServiceIdentifierArgOptional,
isServiceIdentifierArgGreedy,
),
},
Flags: []*flags.FlagConfig{},
RunFunc: run,
}

func run(
ctx context.Context,
_ backend_interface.KurtosisBackend,
_ kurtosis_engine_rpc_api_bindings.EngineServiceClient,
_ metrics_client.MetricsClient,
_ *flags.ParsedFlags,
args *args.ParsedArgs,
) error {
enclaveIdentifier, err := args.GetNonGreedyArg(enclaveIdentifierArgKey)
if err != nil {
return stacktrace.Propagate(err, "An error occurred getting the enclave identifier value using key '%v'", enclaveIdentifierArgKey)
}

serviceIdentifiers, err := args.GetGreedyArg(serviceIdentifierArgKey)
if err != nil {
return stacktrace.Propagate(err, "An error occurred getting the service identifiers values using key '%v'", serviceIdentifierArgKey)
}

kurtosisCtx, err := kurtosis_context.NewKurtosisContextFromLocalEngine()
if err != nil {
return stacktrace.Propagate(err, "An error occurred creating Kurtosis Context from local engine")
}

enclaveCtx, err := kurtosisCtx.GetEnclaveContext(ctx, enclaveIdentifier)
if err != nil {
return stacktrace.Propagate(err, "An error occurred getting an enclave context from enclave info for enclave '%v'", enclaveIdentifier)
}

for _, serviceIdentifier := range serviceIdentifiers {
logrus.Infof("Restarting service '%v'", serviceIdentifier)
serviceContext, err := enclaveCtx.GetServiceContext(serviceIdentifier)
if err != nil {
return stacktrace.NewError("Couldn't validate whether the service exists for identifier '%v'", serviceIdentifier)
}

serviceName := serviceContext.GetServiceName()

if err := restartServiceStarlarkCommand(ctx, enclaveCtx, serviceName); err != nil {
return stacktrace.Propagate(err, "An error occurred restarting service '%v' from enclave '%v'", serviceIdentifier, enclaveIdentifier)
}
}
return nil
}

func restartServiceStarlarkCommand(ctx context.Context, enclaveCtx *enclaves.EnclaveContext, serviceName services.ServiceName) error {
serviceNameString := fmt.Sprintf(`{"service_name": "%s"}`, serviceName)
runResult, err := enclaveCtx.RunStarlarkScriptBlocking(ctx, starlarkScript, starlark_run_config.NewRunStarlarkConfig(starlark_run_config.WithSerializedParams(serviceNameString)))
if err != nil {
return stacktrace.Propagate(err, "An unexpected error occurred on Starlark for restarting service")
}
if runResult.ExecutionError != nil {
return stacktrace.NewError("An error occurred during Starlark script execution for restarting service: %s", runResult.ExecutionError.GetErrorMessage())
}
if runResult.InterpretationError != nil {
return stacktrace.NewError("An error occurred during Starlark script interpretation for restarting service: %s", runResult.InterpretationError.GetErrorMessage())
}
if len(runResult.ValidationErrors) > 0 {
return stacktrace.NewError("An error occurred during Starlark script validation for restarting service: %v", runResult.ValidationErrors)
}
return nil
}
2 changes: 2 additions & 0 deletions cli/cli/commands/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/kurtosis-tech/kurtosis/cli/cli/commands/service/exec"
"github.com/kurtosis-tech/kurtosis/cli/cli/commands/service/inspect"
"github.com/kurtosis-tech/kurtosis/cli/cli/commands/service/logs"
"github.com/kurtosis-tech/kurtosis/cli/cli/commands/service/restart"
"github.com/kurtosis-tech/kurtosis/cli/cli/commands/service/rm"
"github.com/kurtosis-tech/kurtosis/cli/cli/commands/service/shell"
"github.com/kurtosis-tech/kurtosis/cli/cli/commands/service/start"
Expand All @@ -35,4 +36,5 @@ func init() {
ServiceCmd.AddCommand(start.ServiceStartCmd.MustGetCobraCommand())
ServiceCmd.AddCommand(stop.ServiceStopCmd.MustGetCobraCommand())
ServiceCmd.AddCommand(inspect.ServiceInspectCmd.MustGetCobraCommand())
ServiceCmd.AddCommand(restart.ServiceRestartCmd.MustGetCobraCommand())
}
13 changes: 13 additions & 0 deletions docs/docs/cli-reference/service-restart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: service restart
sidebar_label: service restart
slug: /service-restart
---

Services can be restarted like so:

```bash
kurtosis service restart $THE_ENCLAVE_IDENTIFIER $THE_SERVICE_IDENTIFIER
```

where `$THE_ENCLAVE_IDENTIFIER` and the `$THE_SERVICE_IDENTIFIER` are [resource identifiers](../advanced-concepts/resource-identifier.md) for the enclave and service, respectively.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we mention that a user can pass more than one service identifier?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will do that!

Loading