From 66eed34a4d02dd74d485d6b44abc4a5385868195 Mon Sep 17 00:00:00 2001 From: riyasng12 Date: Thu, 11 Jan 2024 15:41:12 +0530 Subject: [PATCH] feat: added feature to pass public ports from cli to package --- cli/cmd/chains/kusama/cmd.go | 4 + cli/cmd/chains/kusama/run.go | 248 +++++++++++--------------------- cli/cmd/chains/polkadot/cmd.go | 4 + cli/cmd/chains/polkadot/run.go | 250 +++++++++++---------------------- cli/cmd/chains/utils/types.go | 177 ++++++++++++++++++++++- cli/common/constants.go | 1 + cli/common/errors.go | 1 + cli/common/types.go | 54 +++++-- cli/go.mod | 2 +- 9 files changed, 379 insertions(+), 362 deletions(-) diff --git a/cli/cmd/chains/kusama/cmd.go b/cli/cmd/chains/kusama/cmd.go index 87fe6586..9d949d07 100644 --- a/cli/cmd/chains/kusama/cmd.go +++ b/cli/cmd/chains/kusama/cmd.go @@ -29,6 +29,10 @@ const ( runKusamaGrafana = "launch_grafana" ) +var ( + kusamaParachains = []string{"altair", "bajun", "bifrost", "calamari", "encointer", "khala", "kintsugi-btc", "litmus", "mangata", "moonriver", "robonomics", "subzero", "turing"} +) + var KusamaCmd = common.NewDiveCommandBuilder(). SetUse("kusama"). SetShort("Build, initialize and start a Kusama node"). diff --git a/cli/cmd/chains/kusama/run.go b/cli/cmd/chains/kusama/run.go index 9d5ada93..2007398c 100644 --- a/cli/cmd/chains/kusama/run.go +++ b/cli/cmd/chains/kusama/run.go @@ -2,6 +2,7 @@ package kusama import ( "fmt" + "slices" "github.com/kurtosis-tech/kurtosis/api/golang/core/lib/enclaves" "github.com/kurtosis-tech/kurtosis/api/golang/core/lib/starlark_run_config" @@ -40,6 +41,17 @@ func RunKusama(cli *common.Cli) (*common.DiveMultipleServiceResponse, error) { return nil, err } + err = serviceConfig.ValidateConfig() + if err != nil { + return nil, common.WrapMessageToErrorf(common.ErrInvalidConfig, err.Error()) + } + + for _, paraChain := range serviceConfig.Para { + if !slices.Contains(kusamaParachains, paraChain.Name) { + return nil, common.WrapMessageToErrorf(common.ErrInvalidConfig, "Invalid ParaChain Name for Kusama") + } + } + encodedServiceConfigDataString, err := serviceConfig.EncodeToString() if err != nil { @@ -72,23 +84,24 @@ func RunKusama(cli *common.Cli) (*common.DiveMultipleServiceResponse, error) { func startRelayAndParaChain(cli *common.Cli, enclaveContext *enclaves.EnclaveContext, serviceConfig *utils.PolkadotServiceConfig, para string) (*common.DiveMultipleServiceResponse, error) { - param := fmt.Sprintf(`{"args": %s}`, para) - kusamaResponseData := &common.DiveMultipleServiceResponse{} paraResult := &common.DiveMultipleServiceResponse{} finalResult := &common.DiveMultipleServiceResponse{} explorerResult := &common.DiveMultipleServiceResponse{} metricsResult := &common.DiveMultipleServiceResponse{} - runConfig := getKusamaRunConfig(serviceConfig, enclaveContext, param) + param, err := serviceConfig.GetParamsForRelay() + if err != nil { + return nil, err + } + runConfig := getKusamaRunConfig(serviceConfig, enclaveContext, param) response, _, err := enclaveContext.RunStarlarkRemotePackage(cli.Context().GetContext(), common.PolkadotRemotePackagePath, runConfig) if err != nil { return nil, common.WrapMessageToError(common.ErrStarlarkRunFailed, err.Error()) } responseData, services, skippedInstructions, err := common.GetSerializedData(cli, response) - if err != nil { errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) if errRemove != nil { @@ -118,7 +131,7 @@ func startRelayAndParaChain(cli *common.Cli, enclaveContext *enclaves.EnclaveCon if err != nil { return nil, err } - finalResult = concatenateDiveResults(result, paraResult) + finalResult = result.ConcatenateDiveResults(paraResult) } else { return nil, common.WrapMessageToError(common.ErrStarlarkResponse, "Kusama is already Running.") @@ -133,24 +146,24 @@ func startRelayAndParaChain(cli *common.Cli, enclaveContext *enclaves.EnclaveCon if err != nil { return nil, err } - finalResult = concatenateDiveResults(result, paraResult) + finalResult = result.ConcatenateDiveResults(paraResult) } } - if metrics { - metricsResult, err = startMetrics(cli, enclaveContext, para, finalResult) - finalResult = concatenateDiveResults(finalResult, metricsResult) + if serviceConfig.HasPrometheus() { + metricsResult, err = startMetrics(cli, enclaveContext, finalResult) + finalResult = finalResult.ConcatenateDiveResults(metricsResult) if err != nil { return nil, err } } - if explorer { + if serviceConfig.Explorer { explorerResult, err = startExplorer(cli, enclaveContext) if err != nil { return nil, err } - finalResult = concatenateDiveResults(finalResult, explorerResult) + finalResult = finalResult.ConcatenateDiveResults(explorerResult) } return finalResult, nil @@ -159,68 +172,44 @@ func startRelayAndParaChain(cli *common.Cli, enclaveContext *enclaves.EnclaveCon func startParaChains(cli *common.Cli, enclaveContext *enclaves.EnclaveContext, serviceConfig *utils.PolkadotServiceConfig, para string, ipAddress string) (*common.DiveMultipleServiceResponse, error) { paraResult := &common.DiveMultipleServiceResponse{} allParaResult := &common.DiveMultipleServiceResponse{} - var err error if serviceConfig.ChainType == localChain { - param := fmt.Sprintf(`{"args": %s, "relay_chain_ip":"%s"}`, para, ipAddress) - paraResult, err = runParaChain(cli, enclaveContext, serviceConfig, param) + var paraChains []string + for _, paraChain := range serviceConfig.Para { + paraChainConfig, err := paraChain.EncodeToString() + if err != nil { + return nil, common.WrapMessageToError(common.ErrDataMarshall, err.Error()) + } + + paraChains = append(paraChains, paraChainConfig) + } + param := fmt.Sprintf(`{"chain_type":"%s", "parachains": %s, "relay_chain_ip": "%s"}`, serviceConfig.ChainType, paraChains, ipAddress) + runParaConfig := getParaRunConfig(serviceConfig, enclaveContext, param) + paraResult, err = startService(cli, enclaveContext, runParaConfig, "Parachain") if err != nil { return nil, err } - allParaResult = concatenateDiveResults(allParaResult, paraResult) + allParaResult = allParaResult.ConcatenateDiveResults(paraResult) } else { for _, paraNode := range serviceConfig.Para { paraChainConfig, err := paraNode.EncodeToString() if err != nil { return nil, common.WrapMessageToError(common.ErrDataMarshall, err.Error()) } - param := fmt.Sprintf(`{"parachain":%s, "args":%s}`, paraChainConfig, para) - paraResult, err = runParaChain(cli, enclaveContext, serviceConfig, param) + param := fmt.Sprintf(`{"chain_type": "%s", "relaychain_name": "%s", "parachain":%s}`, serviceConfig.ChainType, serviceConfig.RelayChain.Name, paraChainConfig) + runParaConfig := getParaRunConfig(serviceConfig, enclaveContext, param) + paraResult, err = startService(cli, enclaveContext, runParaConfig, "Parachain") if err != nil { return nil, err } - allParaResult = concatenateDiveResults(allParaResult, paraResult) + allParaResult = allParaResult.ConcatenateDiveResults(paraResult) } } return allParaResult, nil } -func runParaChain(cli *common.Cli, enclaveContext *enclaves.EnclaveContext, serviceConfig *utils.PolkadotServiceConfig, para string) (*common.DiveMultipleServiceResponse, error) { - - runParaConfig := getParaRunConfig(serviceConfig, enclaveContext, para) - paraResponse, _, err := enclaveContext.RunStarlarkRemotePackage(cli.Context().GetContext(), common.PolkadotRemotePackagePath, runParaConfig) - if err != nil { - return nil, common.WrapMessageToError(common.ErrStarlarkRunFailed, err.Error()) - } - - paraResponseData, paraServices, skippedParaInstructions, err := common.GetSerializedData(cli, paraResponse) - if err != nil { - errRemove := cli.Context().RemoveServicesByServiceNames(paraServices, common.EnclaveName) - if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Failed to clean up services.") - } - return nil, common.WrapMessageToError(err, "Failed to serialize the response data.") - } - - if cli.Context().CheckSkippedInstructions(skippedParaInstructions) { - return nil, common.WrapMessageToError(common.ErrStarlarkResponse, "Parachain is already running.") - } - - KusamaParaResponseData := &common.DiveMultipleServiceResponse{} - resultPara, err := KusamaParaResponseData.Decode([]byte(paraResponseData)) - if err != nil { - errRemove := cli.Context().RemoveServicesByServiceNames(paraServices, common.EnclaveName) - if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Failed to clean up services.") - } - return nil, common.WrapMessageToErrorf(common.ErrDataUnMarshall, "%s.%s", err, "Failed to decode reponse data.") - - } - return resultPara, nil -} - func configureService(serviceConfig *utils.PolkadotServiceConfig) error { if len(paraChain) != 0 { @@ -240,7 +229,7 @@ func configureService(serviceConfig *utils.PolkadotServiceConfig) error { if network != "" { serviceConfig.ChainType = network if network == "testnet" || network == "mainnet" { - configureFullNodes(serviceConfig) + serviceConfig.ConfigureFullNodes(network) } } @@ -249,7 +238,17 @@ func configureService(serviceConfig *utils.PolkadotServiceConfig) error { } if metrics { - configureMetrics(serviceConfig) + serviceConfig.ConfigureMetrics() + } + + for i := range serviceConfig.RelayChain.Nodes { + serviceConfig.RelayChain.Nodes[i].AssignPorts(serviceConfig.RelayChain.Nodes[i].Prometheus) + } + + for _, paraChain := range serviceConfig.Para { + for i := range paraChain.Nodes { + paraChain.Nodes[i].AssignPorts(paraChain.Nodes[i].Prometheus) + } } if noRelay && serviceConfig.ChainType == "local" { @@ -265,34 +264,6 @@ func configureService(serviceConfig *utils.PolkadotServiceConfig) error { return nil } -func configureFullNodes(serviceConfig *utils.PolkadotServiceConfig) { - - if network == "testnet" { - serviceConfig.RelayChain.Name = "rococo" - } else if network == "mainnet" { - serviceConfig.RelayChain.Name = "kusama" - } - - serviceConfig.RelayChain.Nodes = []utils.NodeConfig{} - - serviceConfig.RelayChain.Nodes = append(serviceConfig.RelayChain.Nodes, utils.NodeConfig{ - Name: "alice", - NodeType: "full", - Prometheus: false, - }) -} - -func configureMetrics(serviceConfig *utils.PolkadotServiceConfig) { - for i := range serviceConfig.RelayChain.Nodes { - serviceConfig.RelayChain.Nodes[i].Prometheus = true - } - if len(serviceConfig.Para) != 0 { - for i := range serviceConfig.Para[0].Nodes { - serviceConfig.Para[0].Nodes[i].Prometheus = true - } - } -} - func flagCheck() error { if configFilePath != "" { @@ -375,130 +346,69 @@ func uploadFiles(cli *common.Cli, enclaveCtx *enclaves.EnclaveContext) error { } func startExplorer(cli *common.Cli, enclaveCtx *enclaves.EnclaveContext) (*common.DiveMultipleServiceResponse, error) { - explorerResponseData := &common.DiveMultipleServiceResponse{} - para := `{"ws_url":"ws://127.0.0.1:9944"}` runConfig := common.GetStarlarkRunConfig(para, common.DivePolkaDotExplorerPath, runKusamaExplorer) - explorerResponse, _, err := enclaveCtx.RunStarlarkRemotePackage(cli.Context().GetContext(), common.PolkadotRemotePackagePath, runConfig) - if err != nil { - return nil, common.WrapMessageToError(common.ErrStarlarkRunFailed, err.Error()) - } - - responseData, services, skippedInstructions, err := common.GetSerializedData(cli, explorerResponse) + explorerResponseData, err := startService(cli, enclaveCtx, runConfig, "Explorer") if err != nil { - errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) - if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Explorer Run Failed. Cleanup of services failed.") - } - return nil, common.WrapMessageToError(err, "Explorer Run Failed. Failed to serilize response data.") - } - - if cli.Context().CheckSkippedInstructions(skippedInstructions) { - return nil, common.WrapMessageToError(common.ErrStarlarkResponse, "Explorer is already running.") - } - - result, err := explorerResponseData.Decode([]byte(responseData)) - - if err != nil { - errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) - if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Explorer Run Failed. Cleanup of services failed.") - } - return nil, common.WrapMessageToErrorf(common.ErrDataUnMarshall, "%s.%s", err, "Explorer Run Failed. Failed to decode response data.") + return nil, err } - - return result, nil + return explorerResponseData, nil } -func startMetrics(cli *common.Cli, enclaveCtx *enclaves.EnclaveContext, para string, final_result *common.DiveMultipleServiceResponse) (*common.DiveMultipleServiceResponse, error) { - prometheus := &common.DiveMultipleServiceResponse{} - grafana := &common.DiveMultipleServiceResponse{} - +func startMetrics(cli *common.Cli, enclaveCtx *enclaves.EnclaveContext, final_result *common.DiveMultipleServiceResponse) (*common.DiveMultipleServiceResponse, error) { service_details, err := final_result.EncodeToString() if err != nil { return nil, common.WrapMessageToError(common.ErrDataMarshall, err.Error()) } - paraPrometheus := fmt.Sprintf(`{"args":%s, "service_details":%s}`, para, service_details) - runConfig := common.GetStarlarkRunConfig(paraPrometheus, common.DivePolkaDotPrometheusPath, runKusamaPrometheus) - prometheusResponse, _, err := enclaveCtx.RunStarlarkRemotePackage(cli.Context().GetContext(), common.PolkadotRemotePackagePath, runConfig) + paraPrometheus := fmt.Sprintf(`{"service_details":%s}`, service_details) + + runConfigPrometheus := common.GetStarlarkRunConfig(paraPrometheus, common.DivePolkaDotPrometheusPath, runKusamaPrometheus) + prometheusResult, err := startService(cli, enclaveCtx, runConfigPrometheus, "Prometheus") if err != nil { - return nil, common.WrapMessageToError(common.ErrStarlarkRunFailed, err.Error()) + return nil, err } - prometheusResponseData, services, skippedInstructions, err := common.GetSerializedData(cli, prometheusResponse) + runConfigGrafana := common.GetStarlarkRunConfig(`{}`, common.DivePolkaDotGrafanaPath, runKusamaGrafana) + grafanaResult, err := startService(cli, enclaveCtx, runConfigGrafana, "Grafana") if err != nil { - errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) - if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Prometheus Run Failed. Cleanup of services failed.") - } - return nil, common.WrapMessageToError(err, "Prometheus Run Failed. Failed to serilize response data.") + return nil, err } - if cli.Context().CheckSkippedInstructions(skippedInstructions) { - return nil, common.WrapMessageToError(common.ErrStarlarkResponse, "Prometheus is already Running.") - } + result := prometheusResult.ConcatenateDiveResults(grafanaResult) + return result, nil +} - prometheusResult, err := prometheus.Decode([]byte(prometheusResponseData)) - if err != nil { - errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) - if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Prometheus Run Failed. Cleanup of services failed.") - } - return nil, common.WrapMessageToErrorf(common.ErrDataUnMarshall, "%s.%s", err, "Prometheus Run Failed. Failed to decode reponse data.") - } +func startService(cli *common.Cli, enclaveCtx *enclaves.EnclaveContext, runConfig *starlark_run_config.StarlarkRunConfig, serviceName string) (*common.DiveMultipleServiceResponse, error) { + starlarkResponseData := &common.DiveMultipleServiceResponse{} - paraGrafana := `{"args":{}}` - runConfigGrafana := common.GetStarlarkRunConfig(paraGrafana, common.DivePolkaDotGrafanaPath, runKusamaGrafana) - grafanaResponse, _, err := enclaveCtx.RunStarlarkRemotePackage(cli.Context().GetContext(), common.PolkadotRemotePackagePath, runConfigGrafana) + response, _, err := enclaveCtx.RunStarlarkRemotePackage(cli.Context().GetContext(), common.PolkadotRemotePackagePath, runConfig) if err != nil { return nil, common.WrapMessageToError(common.ErrStarlarkRunFailed, err.Error()) } - grafanaResponseData, services, skippedInstructions, err := common.GetSerializedData(cli, grafanaResponse) + responseData, services, skippedInstructions, err := common.GetSerializedData(cli, response) if err != nil { errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Grafana Run Failed. Cleanup of services failed.") + return nil, common.WrapMessageToErrorf(errRemove, "%s Run Failed. Cleanup of services failed.", serviceName) } - return nil, common.WrapMessageToError(err, "Grafana Run Failed. Failed to serialize response data.") + return nil, common.WrapMessageToErrorf(err, "%s Run Failed. Failed to serilize response data.", serviceName) } if cli.Context().CheckSkippedInstructions(skippedInstructions) { - return nil, common.WrapMessageToError(common.ErrStarlarkResponse, "Grafana is already running.") + return nil, common.WrapMessageToErrorf(common.ErrStarlarkResponse, "%s is already running.", serviceName) } - grafanaResult, err := grafana.Decode([]byte(grafanaResponseData)) + result, err := starlarkResponseData.Decode([]byte(responseData)) + if err != nil { errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Grafana Run Failed. Cleanup of services failed.") + return nil, common.WrapMessageToErrorf(errRemove, "%s Run Failed. Cleanup of services failed.", serviceName) } - return nil, common.WrapMessageToErrorf(common.ErrDataUnMarshall, "%s.%s", err, "Grafana Run Failed. Failed to decode response data.") + return nil, common.WrapMessageToErrorf(common.ErrDataUnMarshall, "%s Run Failed. Failed to decode response data.", serviceName) } - result := concatenateDiveResults(prometheusResult, grafanaResult) return result, nil } - -func concatenateDiveResults(result1, result2 *common.DiveMultipleServiceResponse) *common.DiveMultipleServiceResponse { - if result1 == nil { - return result2 - } else if result2 == nil { - return result1 - } - - concatenatedResult := &common.DiveMultipleServiceResponse{ - Dive: make(map[string]*common.DiveServiceResponse), - } - - for key, value := range result1.Dive { - concatenatedResult.Dive[key] = value - } - - for key, value := range result2.Dive { - concatenatedResult.Dive[key] = value - } - - return concatenatedResult -} diff --git a/cli/cmd/chains/polkadot/cmd.go b/cli/cmd/chains/polkadot/cmd.go index c67ed3cc..5311721e 100644 --- a/cli/cmd/chains/polkadot/cmd.go +++ b/cli/cmd/chains/polkadot/cmd.go @@ -29,6 +29,10 @@ const ( runPolkadotGrafana = "launch_grafana" ) +var ( + polkadotParachains = []string{"acala", "ajuna", "bifrost", "centrifuge", "clover", "frequency", "integritee", "interlay", "karura", "kilt", "kylin", "litentry", "manta", "moonbeam", "moonsama", "nodle", "parallel", "pendulum", "phala", "polkadex", "subsocial", "zeitgeist"} +) + var PolkadotCmd = common.NewDiveCommandBuilder(). SetUse("polkadot"). SetShort("Build, initialize and start a Polkadot node"). diff --git a/cli/cmd/chains/polkadot/run.go b/cli/cmd/chains/polkadot/run.go index f1cb1e67..1c9a3b59 100644 --- a/cli/cmd/chains/polkadot/run.go +++ b/cli/cmd/chains/polkadot/run.go @@ -2,6 +2,7 @@ package polkadot import ( "fmt" + "slices" "github.com/kurtosis-tech/kurtosis/api/golang/core/lib/enclaves" "github.com/kurtosis-tech/kurtosis/api/golang/core/lib/starlark_run_config" @@ -40,6 +41,17 @@ func RunPolkadot(cli *common.Cli) (*common.DiveMultipleServiceResponse, error) { return nil, err } + err = serviceConfig.ValidateConfig() + if err != nil { + return nil, common.WrapMessageToErrorf(common.ErrInvalidConfig, err.Error()) + } + + for _, paraChain := range serviceConfig.Para { + if !slices.Contains(polkadotParachains, paraChain.Name) { + return nil, common.WrapMessageToErrorf(common.ErrInvalidConfig, "Invalid ParaChain Name for PolkaDot") + } + } + encodedServiceConfigDataString, err := serviceConfig.EncodeToString() if err != nil { @@ -72,23 +84,24 @@ func RunPolkadot(cli *common.Cli) (*common.DiveMultipleServiceResponse, error) { func startRelayAndParaChain(cli *common.Cli, enclaveContext *enclaves.EnclaveContext, serviceConfig *utils.PolkadotServiceConfig, para string) (*common.DiveMultipleServiceResponse, error) { - param := fmt.Sprintf(`{"args": %s}`, para) - polkadotResponseData := &common.DiveMultipleServiceResponse{} paraResult := &common.DiveMultipleServiceResponse{} finalResult := &common.DiveMultipleServiceResponse{} explorerResult := &common.DiveMultipleServiceResponse{} metricsResult := &common.DiveMultipleServiceResponse{} - runConfig := getPolkadotRunConfig(serviceConfig, enclaveContext, param) + param, err := serviceConfig.GetParamsForRelay() + if err != nil { + return nil, err + } + runConfig := getPolkadotRunConfig(serviceConfig, enclaveContext, param) response, _, err := enclaveContext.RunStarlarkRemotePackage(cli.Context().GetContext(), common.PolkadotRemotePackagePath, runConfig) if err != nil { return nil, common.WrapMessageToError(common.ErrStarlarkRunFailed, err.Error()) } responseData, services, skippedInstructions, err := common.GetSerializedData(cli, response) - if err != nil { errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) if errRemove != nil { @@ -118,7 +131,7 @@ func startRelayAndParaChain(cli *common.Cli, enclaveContext *enclaves.EnclaveCon if err != nil { return nil, err } - finalResult = concatenateDiveResults(result, paraResult) + finalResult = result.ConcatenateDiveResults(paraResult) } else { return nil, common.WrapMessageToError(common.ErrStarlarkResponse, "Polkadot is already Running.") @@ -133,24 +146,24 @@ func startRelayAndParaChain(cli *common.Cli, enclaveContext *enclaves.EnclaveCon if err != nil { return nil, err } - finalResult = concatenateDiveResults(result, paraResult) + finalResult = result.ConcatenateDiveResults(paraResult) } } - if metrics { - metricsResult, err = startMetrics(cli, enclaveContext, para, finalResult) - finalResult = concatenateDiveResults(finalResult, metricsResult) + if serviceConfig.HasPrometheus() { + metricsResult, err = startMetrics(cli, enclaveContext, finalResult) + finalResult = finalResult.ConcatenateDiveResults(metricsResult) if err != nil { return nil, err } } - if explorer { + if serviceConfig.Explorer { explorerResult, err = startExplorer(cli, enclaveContext) if err != nil { return nil, err } - finalResult = concatenateDiveResults(finalResult, explorerResult) + finalResult = finalResult.ConcatenateDiveResults(explorerResult) } return finalResult, nil @@ -159,70 +172,44 @@ func startRelayAndParaChain(cli *common.Cli, enclaveContext *enclaves.EnclaveCon func startParaChains(cli *common.Cli, enclaveContext *enclaves.EnclaveContext, serviceConfig *utils.PolkadotServiceConfig, para string, ipAddress string) (*common.DiveMultipleServiceResponse, error) { paraResult := &common.DiveMultipleServiceResponse{} allParaResult := &common.DiveMultipleServiceResponse{} - var err error if serviceConfig.ChainType == localChain { - param := fmt.Sprintf(`{"args": %s, "relay_chain_ip":"%s"}`, para, ipAddress) - paraResult, err = runParaChain(cli, enclaveContext, serviceConfig, param) + var paraChains []string + for _, paraChain := range serviceConfig.Para { + paraChainConfig, err := paraChain.EncodeToString() + if err != nil { + return nil, common.WrapMessageToError(common.ErrDataMarshall, err.Error()) + } + + paraChains = append(paraChains, paraChainConfig) + } + param := fmt.Sprintf(`{"chain_type":"%s", "parachains": %s, "relay_chain_ip": "%s"}`, serviceConfig.ChainType, paraChains, ipAddress) + runParaConfig := getParaRunConfig(serviceConfig, enclaveContext, param) + paraResult, err = startService(cli, enclaveContext, runParaConfig, "Parachain") if err != nil { return nil, err } - allParaResult = concatenateDiveResults(allParaResult, paraResult) - + allParaResult = allParaResult.ConcatenateDiveResults(paraResult) } else { for _, paraNode := range serviceConfig.Para { paraChainConfig, err := paraNode.EncodeToString() if err != nil { return nil, common.WrapMessageToError(common.ErrDataMarshall, err.Error()) } - param := fmt.Sprintf(`{"parachain":%s, "args":%s}`, paraChainConfig, para) - paraResult, err = runParaChain(cli, enclaveContext, serviceConfig, param) + param := fmt.Sprintf(`{"chain_type": "%s", "relaychain_name": "%s", "parachain":%s}`, serviceConfig.ChainType, serviceConfig.RelayChain.Name, paraChainConfig) + runParaConfig := getParaRunConfig(serviceConfig, enclaveContext, param) + paraResult, err = startService(cli, enclaveContext, runParaConfig, "Parachain") if err != nil { return nil, err } - allParaResult = concatenateDiveResults(allParaResult, paraResult) + allParaResult = allParaResult.ConcatenateDiveResults(paraResult) } } return allParaResult, nil } -func runParaChain(cli *common.Cli, enclaveContext *enclaves.EnclaveContext, serviceConfig *utils.PolkadotServiceConfig, para string) (*common.DiveMultipleServiceResponse, error) { - - runParaConfig := getParaRunConfig(serviceConfig, enclaveContext, para) - paraResponse, _, err := enclaveContext.RunStarlarkRemotePackage(cli.Context().GetContext(), common.PolkadotRemotePackagePath, runParaConfig) - if err != nil { - return nil, common.WrapMessageToError(common.ErrStarlarkRunFailed, err.Error()) - } - - paraResponseData, paraServices, skippedParaInstructions, err := common.GetSerializedData(cli, paraResponse) - if err != nil { - errRemove := cli.Context().RemoveServicesByServiceNames(paraServices, common.EnclaveName) - if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Failed to clean up services.") - } - return nil, common.WrapMessageToError(err, "Failed to serialize the response data.") - } - - if cli.Context().CheckSkippedInstructions(skippedParaInstructions) { - return nil, common.WrapMessageToError(common.ErrStarlarkResponse, "Parachain is already running.") - } - - PolkadotParaResponseData := &common.DiveMultipleServiceResponse{} - resultPara, err := PolkadotParaResponseData.Decode([]byte(paraResponseData)) - if err != nil { - errRemove := cli.Context().RemoveServicesByServiceNames(paraServices, common.EnclaveName) - if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Failed to clean up services.") - } - return nil, common.WrapMessageToErrorf(common.ErrDataUnMarshall, "%s.%s", err, "Failed to decode reponse data.") - - } - - return resultPara, nil -} - func configureService(serviceConfig *utils.PolkadotServiceConfig) error { if len(paraChain) != 0 { @@ -242,7 +229,7 @@ func configureService(serviceConfig *utils.PolkadotServiceConfig) error { if network != "" { serviceConfig.ChainType = network if network == "testnet" || network == "mainnet" { - configureFullNodes(serviceConfig) + serviceConfig.ConfigureFullNodes(network) } } @@ -251,7 +238,17 @@ func configureService(serviceConfig *utils.PolkadotServiceConfig) error { } if metrics { - configureMetrics(serviceConfig) + serviceConfig.ConfigureMetrics() + } + + for i := range serviceConfig.RelayChain.Nodes { + serviceConfig.RelayChain.Nodes[i].AssignPorts(serviceConfig.RelayChain.Nodes[i].Prometheus) + } + + for _, paraChain := range serviceConfig.Para { + for i := range paraChain.Nodes { + paraChain.Nodes[i].AssignPorts(paraChain.Nodes[i].Prometheus) + } } if noRelay && serviceConfig.ChainType == "local" { @@ -267,34 +264,6 @@ func configureService(serviceConfig *utils.PolkadotServiceConfig) error { return nil } -func configureFullNodes(serviceConfig *utils.PolkadotServiceConfig) { - - if network == "testnet" { - serviceConfig.RelayChain.Name = "rococo" - } else if network == "mainnet" { - serviceConfig.RelayChain.Name = "polkadot" - } - - serviceConfig.RelayChain.Nodes = []utils.NodeConfig{} - - serviceConfig.RelayChain.Nodes = append(serviceConfig.RelayChain.Nodes, utils.NodeConfig{ - Name: "alice", - NodeType: "full", - Prometheus: false, - }) -} - -func configureMetrics(serviceConfig *utils.PolkadotServiceConfig) { - for i := range serviceConfig.RelayChain.Nodes { - serviceConfig.RelayChain.Nodes[i].Prometheus = true - } - if len(serviceConfig.Para) != 0 { - for i := range serviceConfig.Para[0].Nodes { - serviceConfig.Para[0].Nodes[i].Prometheus = true - } - } -} - func flagCheck() error { if configFilePath != "" { @@ -377,130 +346,69 @@ func uploadFiles(cli *common.Cli, enclaveCtx *enclaves.EnclaveContext) error { } func startExplorer(cli *common.Cli, enclaveCtx *enclaves.EnclaveContext) (*common.DiveMultipleServiceResponse, error) { - explorerResponseData := &common.DiveMultipleServiceResponse{} - para := `{"ws_url":"ws://127.0.0.1:9944"}` runConfig := common.GetStarlarkRunConfig(para, common.DivePolkaDotExplorerPath, runPolkadotExplorer) - explorerResponse, _, err := enclaveCtx.RunStarlarkRemotePackage(cli.Context().GetContext(), common.PolkadotRemotePackagePath, runConfig) - if err != nil { - return nil, common.WrapMessageToError(common.ErrStarlarkRunFailed, err.Error()) - } - - responseData, services, skippedInstructions, err := common.GetSerializedData(cli, explorerResponse) - if err != nil { - errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) - if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Explorer Run Failed. Cleanup of services failed.") - } - return nil, common.WrapMessageToError(err, "Explorer Run Failed. Failed to serilize response data.") - } - - if cli.Context().CheckSkippedInstructions(skippedInstructions) { - return nil, common.WrapMessageToError(common.ErrStarlarkResponse, "Explorer is already running.") - } - - result, err := explorerResponseData.Decode([]byte(responseData)) - + explorerResponseData, err := startService(cli, enclaveCtx, runConfig, "Explorer") if err != nil { - errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) - if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Explorer Run Failed. Cleanup of services failed.") - } - return nil, common.WrapMessageToErrorf(common.ErrDataUnMarshall, "%s.%s", err, "Explorer Run Failed. Failed to decode response data.") + return nil, err } - - return result, nil + return explorerResponseData, nil } -func startMetrics(cli *common.Cli, enclaveCtx *enclaves.EnclaveContext, para string, final_result *common.DiveMultipleServiceResponse) (*common.DiveMultipleServiceResponse, error) { - prometheus := &common.DiveMultipleServiceResponse{} - grafana := &common.DiveMultipleServiceResponse{} - +func startMetrics(cli *common.Cli, enclaveCtx *enclaves.EnclaveContext, final_result *common.DiveMultipleServiceResponse) (*common.DiveMultipleServiceResponse, error) { service_details, err := final_result.EncodeToString() if err != nil { return nil, common.WrapMessageToError(common.ErrDataMarshall, err.Error()) } - paraPrometheus := fmt.Sprintf(`{"args":%s, "service_details":%s}`, para, service_details) - runConfig := common.GetStarlarkRunConfig(paraPrometheus, common.DivePolkaDotPrometheusPath, runPolkadotPrometheus) - prometheusResponse, _, err := enclaveCtx.RunStarlarkRemotePackage(cli.Context().GetContext(), common.PolkadotRemotePackagePath, runConfig) + paraPrometheus := fmt.Sprintf(`{"service_details":%s}`, service_details) + + runConfigPrometheus := common.GetStarlarkRunConfig(paraPrometheus, common.DivePolkaDotPrometheusPath, runPolkadotPrometheus) + prometheusResult, err := startService(cli, enclaveCtx, runConfigPrometheus, "Prometheus") if err != nil { - return nil, common.WrapMessageToError(common.ErrStarlarkRunFailed, err.Error()) + return nil, err } - prometheusResponseData, services, skippedInstructions, err := common.GetSerializedData(cli, prometheusResponse) + runConfigGrafana := common.GetStarlarkRunConfig(`{}`, common.DivePolkaDotGrafanaPath, runPolkadotGrafana) + grafanaResult, err := startService(cli, enclaveCtx, runConfigGrafana, "Grafana") if err != nil { - errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) - if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Prometheus Run Failed. Cleanup of services failed.") - } - return nil, common.WrapMessageToError(err, "Prometheus Run Failed. Failed to serilize response data.") + return nil, err } - if cli.Context().CheckSkippedInstructions(skippedInstructions) { - return nil, common.WrapMessageToError(common.ErrStarlarkResponse, "Prometheus is already Running.") - } + result := prometheusResult.ConcatenateDiveResults(grafanaResult) + return result, nil +} - prometheusResult, err := prometheus.Decode([]byte(prometheusResponseData)) - if err != nil { - errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) - if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Prometheus Run Failed. Cleanup of services failed.") - } - return nil, common.WrapMessageToErrorf(common.ErrDataUnMarshall, "%s.%s", err, "Prometheus Run Failed. Failed to decode reponse data.") - } +func startService(cli *common.Cli, enclaveCtx *enclaves.EnclaveContext, runConfig *starlark_run_config.StarlarkRunConfig, serviceName string) (*common.DiveMultipleServiceResponse, error) { + starlarkResponseData := &common.DiveMultipleServiceResponse{} - paraGrafana := `{"args":{}}` - runConfigGrafana := common.GetStarlarkRunConfig(paraGrafana, common.DivePolkaDotGrafanaPath, runPolkadotGrafana) - grafanaResponse, _, err := enclaveCtx.RunStarlarkRemotePackage(cli.Context().GetContext(), common.PolkadotRemotePackagePath, runConfigGrafana) + response, _, err := enclaveCtx.RunStarlarkRemotePackage(cli.Context().GetContext(), common.PolkadotRemotePackagePath, runConfig) if err != nil { return nil, common.WrapMessageToError(common.ErrStarlarkRunFailed, err.Error()) } - grafanaResponseData, services, skippedInstructions, err := common.GetSerializedData(cli, grafanaResponse) + responseData, services, skippedInstructions, err := common.GetSerializedData(cli, response) if err != nil { errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Grafana Run Failed. Cleanup of services failed.") + return nil, common.WrapMessageToErrorf(errRemove, "%s Run Failed. Cleanup of services failed.", serviceName) } - return nil, common.WrapMessageToError(err, "Grafana Run Failed. Failed to serialize response data.") + return nil, common.WrapMessageToErrorf(err, "%s Run Failed. Failed to serilize response data.", serviceName) } if cli.Context().CheckSkippedInstructions(skippedInstructions) { - return nil, common.WrapMessageToError(common.ErrStarlarkResponse, "Grafana is already running.") + return nil, common.WrapMessageToErrorf(common.ErrStarlarkResponse, "%s is already running.", serviceName) } - grafanaResult, err := grafana.Decode([]byte(grafanaResponseData)) + result, err := starlarkResponseData.Decode([]byte(responseData)) + if err != nil { errRemove := cli.Context().RemoveServicesByServiceNames(services, common.EnclaveName) if errRemove != nil { - return nil, common.WrapMessageToError(errRemove, "Grafana Run Failed. Cleanup of services failed.") + return nil, common.WrapMessageToErrorf(errRemove, "%s Run Failed. Cleanup of services failed.", serviceName) } - return nil, common.WrapMessageToErrorf(common.ErrDataUnMarshall, "%s.%s", err, "Grafana Run Failed. Failed to decode response data.") + return nil, common.WrapMessageToErrorf(common.ErrDataUnMarshall, "%s Run Failed. Failed to decode response data.", serviceName) } - result := concatenateDiveResults(prometheusResult, grafanaResult) return result, nil } - -func concatenateDiveResults(result1, result2 *common.DiveMultipleServiceResponse) *common.DiveMultipleServiceResponse { - if result1 == nil { - return result2 - } else if result2 == nil { - return result1 - } - - concatenatedResult := &common.DiveMultipleServiceResponse{ - Dive: make(map[string]*common.DiveServiceResponse), - } - - for key, value := range result1.Dive { - concatenatedResult.Dive[key] = value - } - - for key, value := range result2.Dive { - concatenatedResult.Dive[key] = value - } - - return concatenatedResult -} diff --git a/cli/cmd/chains/utils/types.go b/cli/cmd/chains/utils/types.go index 355287d4..97f97fad 100644 --- a/cli/cmd/chains/utils/types.go +++ b/cli/cmd/chains/utils/types.go @@ -2,6 +2,8 @@ package utils import ( "encoding/json" + "fmt" + "slices" "github.com/hugobyte/dive-core/cli/common" ) @@ -160,8 +162,15 @@ func (sc *HardhatServiceConfig) EncodeToString() (string, error) { type NodeConfig struct { Name string `json:"name"` - NodeType string `json:"node-type"` + NodeType string `json:"node_type"` Prometheus bool `json:"prometheus"` + Ports Ports `json:"ports"` +} + +type Ports struct { + RPCPort int `json:"rpc_port"` + Lib2LibPort int `json:"lib2lib_port"` + PrometheusPort int `json:"prometheus_port,omitempty"` } type RelayChainConfig struct { @@ -175,14 +184,23 @@ type ParaNodeConfig struct { } type PolkadotServiceConfig struct { - ChainType string `json:"chain-type"` + ChainType string `json:"chain_type"` RelayChain RelayChainConfig `json:"relaychain"` - Para []ParaNodeConfig `json:"para"` + Para []ParaNodeConfig `json:"parachains"` Explorer bool `json:"explorer"` } -func (sc *ParaNodeConfig) EncodeToString() (string, error) { - encodedBytes, err := json.Marshal(sc) +func (pc *ParaNodeConfig) EncodeToString() (string, error) { + encodedBytes, err := json.Marshal(pc) + if err != nil { + return "", common.WrapMessageToError(common.ErrDataMarshall, err.Error()) + } + + return string(encodedBytes), nil +} + +func (rc *RelayChainConfig) EncodeToString() (string, error) { + encodedBytes, err := json.Marshal(rc) if err != nil { return "", common.WrapMessageToError(common.ErrDataMarshall, err.Error()) } @@ -209,6 +227,17 @@ func (sc *PolkadotServiceConfig) LoadConfigFromFile(cliContext *common.Cli, file if err != nil { return common.WrapMessageToError(err, "Failed To Load Configuration") } + + for i := range sc.RelayChain.Nodes { + sc.RelayChain.Nodes[i].AssignPorts(sc.RelayChain.Nodes[i].Prometheus) + } + + for _, parachain := range sc.Para { + for i := range parachain.Nodes { + sc.RelayChain.Nodes[i].AssignPorts(sc.RelayChain.Nodes[i].Prometheus) + } + } + return nil } @@ -217,12 +246,37 @@ func (sc *PolkadotServiceConfig) LoadDefaultConfig() error { sc.Explorer = false sc.RelayChain.Name = "rococo-local" sc.RelayChain.Nodes = []NodeConfig{ - {Name: "bob", NodeType: "full", Prometheus: false}, + {Name: "bob", NodeType: "validator", Prometheus: false}, {Name: "alice", NodeType: "validator", Prometheus: false}, } + for i := range sc.RelayChain.Nodes { + sc.RelayChain.Nodes[i].AssignPorts(sc.RelayChain.Nodes[i].Prometheus) + } + sc.Para = []ParaNodeConfig{} + return nil +} + +func (nc *NodeConfig) AssignPorts(prometheus bool) error { + var rpcPort, lib2libPort, prometheusPort int + var err error + rpcPort, err = common.GetAvailablePort() + if err != nil { + return err + } + lib2libPort, err = common.GetAvailablePort() + if err != nil { + return err + } + if prometheus { + prometheusPort, err = common.GetAvailablePort() + if err != nil { + return err + } + } + nc.Ports = Ports{RPCPort: rpcPort, Lib2LibPort: lib2libPort, PrometheusPort: prometheusPort} return nil } @@ -291,3 +345,114 @@ func (nc *NodeConfig) IsEmpty() error { return nil } + +func (sc *PolkadotServiceConfig) HasPrometheus() bool { + // Check relay chain nodes + if sc.RelayChain.Name != "" { + for _, node := range sc.RelayChain.Nodes { + if node.Prometheus { + return true + } + } + } + + // Check para nodes + for _, paraNode := range sc.Para { + for _, node := range paraNode.Nodes { + if node.Prometheus { + return true + } + } + } + + return false +} + +func (sc *PolkadotServiceConfig) ValidateConfig() error { + var validChainTypes = []string{"local", "testnet", "mainnet"} + var validRelayNodeType = []string{"validator", "full"} + var validParaNodeType = []string{"collator", "full"} + + if !slices.Contains(validChainTypes, sc.ChainType) { + return fmt.Errorf("invalid Chain Type: %s", sc.ChainType) + } + + if sc.ChainType == "local" && sc.RelayChain.Name != "rococo-local" { + return fmt.Errorf("invalid Chain Name for local: %s", sc.RelayChain.Name) + } + + if sc.RelayChain.Name != "" { + if sc.ChainType == "testnet" && !(sc.RelayChain.Name == "rococo" || sc.RelayChain.Name == "westend") { + return fmt.Errorf("invalid Chain Name for testnet: %s", sc.RelayChain.Name) + } + + if sc.ChainType == "mainnet" && !(sc.RelayChain.Name == "kusama" || sc.RelayChain.Name == "polkadot") { + return fmt.Errorf("invalid Chain Name for mainnet: %s", sc.RelayChain.Name) + } + } + + if sc.ChainType == "local" { + for _, node := range sc.RelayChain.Nodes { + if node.NodeType != "validator" { + return fmt.Errorf("invalid Node Type for Relay Chain Local: %s", node.NodeType) + } + } + } else { + for _, node := range sc.RelayChain.Nodes { + if !slices.Contains(validRelayNodeType, node.NodeType) { + return fmt.Errorf("invalid Node Type for Relay Chain: %s", node.NodeType) + } + } + } + + for _, paraChain := range sc.Para { + for _, node := range paraChain.Nodes { + if !slices.Contains(validParaNodeType, node.NodeType) { + return fmt.Errorf("invalid Node Type for Para Chain: %s", node.NodeType) + } + } + } + + return nil +} + +func (sc *PolkadotServiceConfig) GetParamsForRelay() (string, error) { + relay_nodes, err := sc.RelayChain.EncodeToString() + if err != nil { + return "", common.WrapMessageToError(common.ErrDataMarshall, err.Error()) + } + + if sc.ChainType == "local" { + return fmt.Sprintf(`{"relaychain": %s}`, relay_nodes), nil + } else { + return fmt.Sprintf(`{"chain_type": "%s", "relaychain": %s}`, sc.ChainType, relay_nodes), nil + } +} + +func (sc *PolkadotServiceConfig) ConfigureMetrics() { + for i := range sc.RelayChain.Nodes { + sc.RelayChain.Nodes[i].Prometheus = true + } + if len(sc.Para) != 0 { + for i := range sc.Para[0].Nodes { + sc.Para[0].Nodes[i].Prometheus = true + } + } +} + +func (sc *PolkadotServiceConfig) ConfigureFullNodes(network string) { + + if network == "testnet" { + sc.RelayChain.Name = "rococo" + } else if network == "mainnet" { + sc.RelayChain.Name = "kusama" + } + + sc.RelayChain.Nodes = []NodeConfig{} + + sc.RelayChain.Nodes = append(sc.RelayChain.Nodes, NodeConfig{ + Name: "alice", + NodeType: "full", + Prometheus: false, + }) +} diff --git a/cli/common/constants.go b/cli/common/constants.go index 824d61df..c971e726 100644 --- a/cli/common/constants.go +++ b/cli/common/constants.go @@ -89,6 +89,7 @@ const ( EmptyFieldsError MissingFlagsError InvalidFlagError + InvalidConfigError ) var DiveLogs bool diff --git a/cli/common/errors.go b/cli/common/errors.go index d1902c2b..a0279b25 100644 --- a/cli/common/errors.go +++ b/cli/common/errors.go @@ -38,6 +38,7 @@ var ( ErrEmptyFields = NewBase(EmptyFieldsError, "Missing Fields In The Config File") ErrMissingFlags = NewBase(MissingFlagsError, "Missing Flags") ErrInvalidFlag = NewBase(InvalidFlagError, "Invalid Flag Usage") + ErrInvalidConfig = NewBase(InvalidConfigError, "Invalid Config") ) func (c ErrorCode) New(msg string) error { diff --git a/cli/common/types.go b/cli/common/types.go index ad27bd38..1752856b 100644 --- a/cli/common/types.go +++ b/cli/common/types.go @@ -5,21 +5,22 @@ import ( ) type DiveServiceResponse struct { - ServiceName string `json:"service_name,omitempty"` - PublicEndpoint string `json:"endpoint_public,omitempty"` - PrivateEndpoint string `json:"endpoint,omitempty"` - KeyPassword string `json:"keypassword,omitempty"` - KeystorePath string `json:"keystore_path,omitempty"` - Network string `json:"network,omitempty"` - NetworkName string `json:"network_name,omitempty"` - NetworkId string `json:"nid,omitempty"` - ChainId string `json:"chain_id,omitempty"` - ChainKey string `json:"chain_key,omitempty"` - PrometheusEndpoint string `json:"endpoint_prometheus,omitempty"` - Prometheus bool `json:"prometheus,omitempty"` - IpAddress string `json:"ip_address,omitempty"` - Node string `json:"node-type,omitempty"` - PrometheusPort int `json:"prometheus_port,omitempty"` + ServiceName string `json:"service_name,omitempty"` + PublicEndpoint string `json:"endpoint_public,omitempty"` + PrivateEndpoint string `json:"endpoint,omitempty"` + KeyPassword string `json:"keypassword,omitempty"` + KeystorePath string `json:"keystore_path,omitempty"` + Network string `json:"network,omitempty"` + NetworkName string `json:"network_name,omitempty"` + NetworkId string `json:"nid,omitempty"` + ChainId string `json:"chain_id,omitempty"` + ChainKey string `json:"chain_key,omitempty"` + PrometheusEndpoint string `json:"endpoint_prometheus,omitempty"` + Prometheus bool `json:"prometheus,omitempty"` + IpAddress string `json:"ip_address,omitempty"` + Node string `json:"node-type,omitempty"` + PrometheusPort int `json:"prometheus_port,omitempty"` + PrometheusPublicPort int `json:"prometheus_public_port,omitempty"` } type DiveMultipleServiceResponse struct { @@ -68,6 +69,29 @@ func (dive *DiveMultipleServiceResponse) EncodeToString() (string, error) { return string(encodedBytes), nil } +func (dive *DiveMultipleServiceResponse) ConcatenateDiveResults(result2 *DiveMultipleServiceResponse) *DiveMultipleServiceResponse { + result1 := dive + if result1 == nil { + return result2 + } else if result2 == nil { + return result1 + } + + concatenatedResult := &DiveMultipleServiceResponse{ + Dive: make(map[string]*DiveServiceResponse), + } + + for key, value := range result1.Dive { + concatenatedResult.Dive[key] = value + } + + for key, value := range result2.Dive { + concatenatedResult.Dive[key] = value + } + + return concatenatedResult +} + type Services map[string]*DiveServiceResponse type DiveBridgeResponse map[string]interface{} diff --git a/cli/go.mod b/cli/go.mod index 2945750b..c405bdee 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -6,7 +6,7 @@ require ( github.com/briandowns/spinner v1.23.0 github.com/fatih/color v1.16.0 github.com/google/go-github v17.0.0+incompatible - github.com/kurtosis-tech/kurtosis/api/golang v0.85.42 + github.com/kurtosis-tech/kurtosis/api/golang v0.86.2 github.com/kurtosis-tech/stacktrace v0.0.0-20211028211901-1c67a77b5409 github.com/natefinch/lumberjack v2.0.0+incompatible github.com/sirupsen/logrus v1.9.3