From b08691fa99ce7eb962f90f24a5cb94a9e1aa6e38 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Thu, 11 Jul 2024 19:42:04 +0200 Subject: [PATCH 01/26] Bump go version to 1.22.5 (#1027) * bump go to 1.22.5 --- go.mod | 2 +- k8s/Dockerfile.base | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index fab115262..7d0a104a5 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/smartcontractkit/chainlink-testing-framework -go 1.21 +go 1.22.5 require ( dario.cat/mergo v1.0.0 diff --git a/k8s/Dockerfile.base b/k8s/Dockerfile.base index 2d2229ca8..51cbce825 100644 --- a/k8s/Dockerfile.base +++ b/k8s/Dockerfile.base @@ -1,5 +1,5 @@ # base test for all k8s test runs -FROM golang:1.21-bullseye +FROM golang:1.22-bullseye ARG BASE_URL ARG HELM_VERSION From aefcba46e483e2b66c3a903f114a9bfc8d47d487 Mon Sep 17 00:00:00 2001 From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com> Date: Fri, 12 Jul 2024 01:26:27 +0530 Subject: [PATCH 02/26] Anvil cache pvc (#1026) * add separate volume/pvc for anvil cache * go mod tidy * increase foundry chart version * increase foundry chart version --- charts/foundry/Chart.yaml | 2 +- charts/foundry/templates/cache-pvc.yaml | 12 ++++++++++++ charts/foundry/templates/deployment.yaml | 7 ++++++- charts/foundry/templates/pvc.yaml | 12 ------------ charts/foundry/templates/state-pvc.yaml | 12 ++++++++++++ charts/foundry/values.yaml | 9 +++++++-- tools/ghsecrets/go.mod | 3 ++- 7 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 charts/foundry/templates/cache-pvc.yaml delete mode 100644 charts/foundry/templates/pvc.yaml create mode 100644 charts/foundry/templates/state-pvc.yaml diff --git a/charts/foundry/Chart.yaml b/charts/foundry/Chart.yaml index 2393e40a2..44d8216d4 100644 --- a/charts/foundry/Chart.yaml +++ b/charts/foundry/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: foundry description: A Helm chart for foundry, mostly used to run Anvil node type: application -version: 0.1.9 +version: 0.2.1 appVersion: 'latest' diff --git a/charts/foundry/templates/cache-pvc.yaml b/charts/foundry/templates/cache-pvc.yaml new file mode 100644 index 000000000..1c14e101a --- /dev/null +++ b/charts/foundry/templates/cache-pvc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "foundry.fullname" . }}-cache-pvc +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: {{ $.Values.cache.capacity }} + storageClassName: {{ $.Values.cache.storageClassName}} diff --git a/charts/foundry/templates/deployment.yaml b/charts/foundry/templates/deployment.yaml index fd088f1ae..428494a31 100644 --- a/charts/foundry/templates/deployment.yaml +++ b/charts/foundry/templates/deployment.yaml @@ -146,13 +146,18 @@ spec: volumeMounts: - name: state-storage mountPath: /state + - name: cache-storage + mountPath: /home {{- with .Values.volumeMounts }} {{- toYaml . | nindent 12 }} {{- end }} volumes: - name: state-storage persistentVolumeClaim: - claimName: {{ include "foundry.fullname" . }}-pvc + claimName: {{ include "foundry.fullname" . }}-state-pvc + - name: cache-storage + persistentVolumeClaim: + claimName: {{ include "foundry.fullname" . }}-cache-pvc {{- with .Values.volumes }} {{- toYaml . | nindent 8 }} {{- end }} diff --git a/charts/foundry/templates/pvc.yaml b/charts/foundry/templates/pvc.yaml deleted file mode 100644 index accfaa92d..000000000 --- a/charts/foundry/templates/pvc.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ include "foundry.fullname" . }}-pvc -spec: - accessModes: - - ReadWriteOnce - volumeMode: Filesystem - resources: - requests: - storage: {{ $.Values.capacity }} - storageClassName: {{ $.Values.storageClassName}} diff --git a/charts/foundry/templates/state-pvc.yaml b/charts/foundry/templates/state-pvc.yaml new file mode 100644 index 000000000..a57a5d62a --- /dev/null +++ b/charts/foundry/templates/state-pvc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "foundry.fullname" . }}-state-pvc +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: {{ $.Values.state.capacity }} + storageClassName: {{ $.Values.state.storageClassName}} diff --git a/charts/foundry/values.yaml b/charts/foundry/values.yaml index f95f5e78b..866167872 100644 --- a/charts/foundry/values.yaml +++ b/charts/foundry/values.yaml @@ -107,8 +107,13 @@ resources: {} # cpu: 100m # memory: 128Mi -capacity: 20Gi -storageClassName: gp3 +state: + capacity: 20Gi + storageClassName: gp3 +cache: + # bump this if running long running tests + capacity: 20Gi + storageClassName: gp3 autoscaling: enabled: false minReplicas: 1 diff --git a/tools/ghsecrets/go.mod b/tools/ghsecrets/go.mod index 9681ba629..e07c3e74b 100644 --- a/tools/ghsecrets/go.mod +++ b/tools/ghsecrets/go.mod @@ -2,8 +2,9 @@ module github.com/smartcontractkit/chainlink-testing-framework/tools/ghsecrets go 1.21.9 +require github.com/spf13/cobra v1.8.1 + require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect ) From 1acee97669ce03552ec87209aef0d35a3378e286 Mon Sep 17 00:00:00 2001 From: Lukasz <120112546+lukaszcl@users.noreply.github.com> Date: Mon, 15 Jul 2024 11:36:03 +0200 Subject: [PATCH 03/26] Refactor reading test secrets from env vars (#1028) * Update loading config fields from env vars Updated loading of config fields from environment variables to enhance reusability for CCIP integration * Update how env vars are read to make it usable in CCIP * Fix * Refactor * Clean up pyroscope config * fix lint * Use info level log --- config/env.go | 168 ++++++++++++++++++++ config/logging.go | 3 +- config/testconfig.go | 317 +++++++++----------------------------- config/testconfig_test.go | 2 +- 4 files changed, 244 insertions(+), 246 deletions(-) create mode 100644 config/env.go diff --git a/config/env.go b/config/env.go new file mode 100644 index 000000000..70ba314d9 --- /dev/null +++ b/config/env.go @@ -0,0 +1,168 @@ +package config + +import ( + "fmt" + "os" + "regexp" + "strconv" + "strings" + + "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" +) + +const ( + E2E_TEST_LOKI_TENANT_ID_ENV = "E2E_TEST_LOKI_TENANT_ID" + E2E_TEST_LOKI_ENDPOINT_ENV = "E2E_TEST_LOKI_ENDPOINT" + E2E_TEST_LOKI_BASIC_AUTH_ENV = "E2E_TEST_LOKI_BASIC_AUTH" + E2E_TEST_LOKI_BEARER_TOKEN_ENV = "E2E_TEST_LOKI_BEARER_TOKEN" // #nosec G101 + E2E_TEST_GRAFANA_BASE_URL_ENV = "E2E_TEST_GRAFANA_BASE_URL" + E2E_TEST_GRAFANA_DASHBOARD_URL_ENV = "E2E_TEST_GRAFANA_DASHBOARD_URL" + E2E_TEST_GRAFANA_BEARER_TOKEN_ENV = "E2E_TEST_GRAFANA_BEARER_TOKEN" // #nosec G101 + E2E_TEST_PYROSCOPE_ENABLED_ENV = "E2E_TEST_PYROSCOPE_ENABLED" + E2E_TEST_PYROSCOPE_SERVER_URL_ENV = "E2E_TEST_PYROSCOPE_SERVER_URL" + E2E_TEST_PYROSCOPE_KEY_ENV = "E2E_TEST_PYROSCOPE_KEY" + E2E_TEST_PYROSCOPE_ENVIRONMENT_ENV = "E2E_TEST_PYROSCOPE_ENVIRONMENT" + E2E_TEST_CHAINLINK_IMAGE_ENV = "E2E_TEST_CHAINLINK_IMAGE" + E2E_TEST_CHAINLINK_UPGRADE_IMAGE_ENV = "E2E_TEST_CHAINLINK_UPGRADE_IMAGE" + E2E_TEST_WALLET_KEY_ENV = `E2E_TEST_(.+)_WALLET_KEY$` + E2E_TEST_WALLET_KEYS_ENV = `E2E_TEST_(.+)_WALLET_KEY_(\d+)$` + E2E_TEST_RPC_HTTP_URL_ENV = `E2E_TEST_(.+)_RPC_HTTP_URL$` + E2E_TEST_RPC_HTTP_URLS_ENV = `E2E_TEST_(.+)_RPC_HTTP_URL_(\d+)$` + E2E_TEST_RPC_WS_URL_ENV = `E2E_TEST_(.+)_RPC_WS_URL$` + E2E_TEST_RPC_WS_URLS_ENV = `E2E_TEST_(.+)_RPC_WS_URL_(\d+)$` +) + +func MustReadEnvVar_String(name string) string { + value, err := readEnvVarValue(name, String) + if err != nil { + panic(err) + } + if value == nil { + return "" + } + return value.(string) +} + +func MustReadEnvVar_Boolean(name string) *bool { + value, err := readEnvVarValue(name, Boolean) + if err != nil { + panic(err) + } + if value == nil { + return nil + } + return ptr.Ptr(value.(bool)) +} + +func ReadEnvVarGroupedMap(singleEnvPattern, groupEnvPattern string) map[string][]string { + return mergeMaps(readEnvVarSingleMap(singleEnvPattern), readEnvVarGroupedMap(groupEnvPattern)) +} + +// readEnvVarValue reads an environment variable and returns the value parsed according to the specified type. +func readEnvVarValue(envVarName string, valueType EnvValueType) (interface{}, error) { + // Get the environment variable value + value, isSet := os.LookupEnv(envVarName) + if !isSet { + return nil, nil + } + if isSet && value == "" { + return "", nil // Return "" if the environment variable is not set + } + + // Parse the value according to the specified type + switch valueType { + case Integer: + intVal, err := strconv.Atoi(value) + if err != nil { + return nil, fmt.Errorf("error converting value to integer: %v", err) + } + return intVal, nil + case Boolean: + boolVal, err := strconv.ParseBool(value) + if err != nil { + return nil, fmt.Errorf("error converting value to boolean: %v", err) + } + return boolVal, nil + case Float: + floatVal, err := strconv.ParseFloat(value, 64) + if err != nil { + return nil, fmt.Errorf("error converting value to float: %v", err) + } + return floatVal, nil + default: // String or unrecognized type + return value, nil + } +} + +// readEnvVarGroupedMap scans all environment variables, matches them against +// a specified pattern, and returns a map of grouped values based on the pattern. +// The grouping is defined by the first capture group of the regex. +func readEnvVarGroupedMap(pattern string) map[string][]string { + re := regexp.MustCompile(pattern) + groupedVars := make(map[string][]string) + for _, env := range os.Environ() { + pair := strings.SplitN(env, "=", 2) + if len(pair) != 2 { + continue + } + key, value := pair[0], pair[1] + matches := re.FindStringSubmatch(key) + if len(matches) > 1 && value != "" { + group := matches[1] // Use the first capture group for grouping + groupedVars[group] = append(groupedVars[group], value) + } + } + return groupedVars +} + +func readEnvVarSingleMap(pattern string) map[string]string { + re := regexp.MustCompile(pattern) + singleVars := make(map[string]string) + for _, env := range os.Environ() { + pair := strings.SplitN(env, "=", 2) + if len(pair) != 2 { + continue + } + key, value := pair[0], pair[1] + matches := re.FindStringSubmatch(key) + if len(matches) > 1 && value != "" { + group := matches[1] // Use the first capture group for grouping + singleVars[group] = value + } + } + return singleVars +} + +// Merges a map[string]string with a map[string][]string and returns a new map[string][]string. +// Elements from the single map are inserted at index 0 in the slice of the new map. +func mergeMaps(single map[string]string, multi map[string][]string) map[string][]string { + newMap := make(map[string][]string) + + // First, copy all elements from the multi map to the new map + for key, values := range multi { + newMap[key] = make([]string, len(values)) + copy(newMap[key], values) + } + + // Next, insert or prepend the elements from the single map + for key, value := range single { + if existingValues, exists := newMap[key]; exists { + // Prepend the value from the single map + newMap[key] = append([]string{value}, existingValues...) + } else { + // Initialize a new slice if the key does not exist + newMap[key] = []string{value} + } + } + + return newMap +} + +type EnvValueType int + +const ( + String EnvValueType = iota + Integer + Boolean + Float +) diff --git a/config/logging.go b/config/logging.go index d9318cfae..81a563f72 100644 --- a/config/logging.go +++ b/config/logging.go @@ -1,9 +1,10 @@ package config import ( - "errors" "fmt" + "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/utils/net" ) diff --git a/config/testconfig.go b/config/testconfig.go index cd030b41d..08bf1c1af 100644 --- a/config/testconfig.go +++ b/config/testconfig.go @@ -3,8 +3,6 @@ package config import ( "fmt" "os" - "regexp" - "strconv" "strings" "github.com/joho/godotenv" @@ -51,335 +49,166 @@ type TestConfig struct { } // Read config values from environment variables -func (c *TestConfig) ReadConfigValuesFromEnvVars() error { +func (c *TestConfig) ReadFromEnvVar() error { logger := logging.GetTestLogger(nil) - walletKeys := mergeMaps(loadEnvVarSingleMap(`E2E_TEST_(.+)_WALLET_KEY$`), loadEnvVarGroupedMap(`E2E_TEST_(.+)_WALLET_KEY_(\d+)$`)) - if len(walletKeys) > 0 { - if c.Network == nil { - c.Network = &NetworkConfig{} - } - c.Network.WalletKeys = walletKeys - } - rpcHttpUrls := mergeMaps(loadEnvVarSingleMap(`E2E_TEST_(.+)_RPC_HTTP_URL$`), loadEnvVarGroupedMap(`E2E_TEST_(.+)_RPC_HTTP_URL_(\d+)$`)) - if len(rpcHttpUrls) > 0 { - if c.Network == nil { - c.Network = &NetworkConfig{} - } - c.Network.RpcHttpUrls = rpcHttpUrls - } - rpcWsUrls := mergeMaps(loadEnvVarSingleMap(`E2E_TEST_(.+)_RPC_WS_URL$`), loadEnvVarGroupedMap(`E2E_TEST_(.+)_RPC_WS_URL_(\d+)$`)) - if len(rpcWsUrls) > 0 { - if c.Network == nil { - c.Network = &NetworkConfig{} - } - c.Network.RpcWsUrls = rpcWsUrls - } - - chainlinkImage, err := readEnvVarValue("E2E_TEST_CHAINLINK_IMAGE", String) - if err != nil { - return err - } - if chainlinkImage != nil && chainlinkImage.(string) != "" { - if c.ChainlinkImage == nil { - c.ChainlinkImage = &ChainlinkImageConfig{} - } - image := chainlinkImage.(string) - logger.Debug().Msgf("Using E2E_TEST_CHAINLINK_IMAGE env var to override ChainlinkImage.Image") - c.ChainlinkImage.Image = &image - } - - chainlinkUpgradeImage, err := readEnvVarValue("E2E_TEST_CHAINLINK_UPGRADE_IMAGE", String) - if err != nil { - return err - } - if chainlinkUpgradeImage != nil && chainlinkUpgradeImage.(string) != "" { - if c.ChainlinkUpgradeImage == nil { - c.ChainlinkUpgradeImage = &ChainlinkImageConfig{} - } - image := chainlinkUpgradeImage.(string) - logger.Debug().Msgf("Using E2E_TEST_CHAINLINK_UPGRADE_IMAGE env var to override ChainlinkUpgradeImage.Image") - c.ChainlinkUpgradeImage.Image = &image - } - - lokiTenantID, err := readEnvVarValue("E2E_TEST_LOKI_TENANT_ID", String) - if err != nil { - return err - } - if lokiTenantID != nil && lokiTenantID.(string) != "" { + lokiTenantID := MustReadEnvVar_String(E2E_TEST_LOKI_TENANT_ID_ENV) + if lokiTenantID != "" { if c.Logging == nil { c.Logging = &LoggingConfig{} } if c.Logging.Loki == nil { c.Logging.Loki = &LokiConfig{} } - id := lokiTenantID.(string) - logger.Debug().Msgf("Using E2E_TEST_LOKI_TENANT_ID env var to override Logging.Loki.TenantId") - c.Logging.Loki.TenantId = &id + logger.Info().Msgf("Using %s env var to override Logging.Loki.TenantId", E2E_TEST_LOKI_TENANT_ID_ENV) + c.Logging.Loki.TenantId = &lokiTenantID } - lokiEndpoint, err := readEnvVarValue("E2E_TEST_LOKI_ENDPOINT", String) - if err != nil { - return err - } - if lokiEndpoint != nil && lokiEndpoint.(string) != "" { + lokiEndpoint := MustReadEnvVar_String(E2E_TEST_LOKI_ENDPOINT_ENV) + if lokiEndpoint != "" { if c.Logging == nil { c.Logging = &LoggingConfig{} } if c.Logging.Loki == nil { c.Logging.Loki = &LokiConfig{} } - endpoint := lokiEndpoint.(string) - logger.Debug().Msgf("Using E2E_TEST_LOKI_ENDPOINT env var to override Logging.Loki.Endpoint") - c.Logging.Loki.Endpoint = &endpoint + logger.Info().Msgf("Using %s env var to override Logging.Loki.Endpoint", E2E_TEST_LOKI_ENDPOINT_ENV) + c.Logging.Loki.Endpoint = &lokiEndpoint } - lokiBasicAuth, err := readEnvVarValue("E2E_TEST_LOKI_BASIC_AUTH", String) - if err != nil { - return err - } - if lokiBasicAuth != nil && lokiBasicAuth.(string) != "" { + lokiBasicAuth := MustReadEnvVar_String(E2E_TEST_LOKI_BASIC_AUTH_ENV) + if lokiBasicAuth != "" { if c.Logging == nil { c.Logging = &LoggingConfig{} } if c.Logging.Loki == nil { c.Logging.Loki = &LokiConfig{} } - basicAuth := lokiBasicAuth.(string) - logger.Debug().Msgf("Using E2E_TEST_LOKI_BASIC_AUTH env var to override Logging.Loki.BasicAuth") - c.Logging.Loki.BasicAuth = &basicAuth + logger.Info().Msgf("Using %s env var to override Logging.Loki.BasicAuth", E2E_TEST_LOKI_BASIC_AUTH_ENV) + c.Logging.Loki.BasicAuth = &lokiBasicAuth } - lokiBearerToken, err := readEnvVarValue("E2E_TEST_LOKI_BEARER_TOKEN", String) - if err != nil { - return err - } - if lokiBearerToken != nil && lokiBearerToken.(string) != "" { + lokiBearerToken := MustReadEnvVar_String(E2E_TEST_LOKI_BEARER_TOKEN_ENV) + if lokiBearerToken != "" { if c.Logging == nil { c.Logging = &LoggingConfig{} } if c.Logging.Loki == nil { c.Logging.Loki = &LokiConfig{} } - bearerToken := lokiBearerToken.(string) - logger.Debug().Msgf("Using E2E_TEST_LOKI_BEARER_TOKEN env var to override Logging.Loki.BearerToken") - c.Logging.Loki.BearerToken = &bearerToken + logger.Info().Msgf("Using %s env var to override Logging.Loki.BearerToken", E2E_TEST_LOKI_BEARER_TOKEN_ENV) + c.Logging.Loki.BearerToken = &lokiBearerToken } - grafanaBaseUrl, err := readEnvVarValue("E2E_TEST_GRAFANA_BASE_URL", String) - if err != nil { - return err - } - if grafanaBaseUrl != nil && grafanaBaseUrl.(string) != "" { + grafanaBaseUrl := MustReadEnvVar_String(E2E_TEST_GRAFANA_BASE_URL_ENV) + if grafanaBaseUrl != "" { if c.Logging == nil { c.Logging = &LoggingConfig{} } if c.Logging.Grafana == nil { c.Logging.Grafana = &GrafanaConfig{} } - baseUrl := grafanaBaseUrl.(string) - logger.Debug().Msgf("Using E2E_TEST_GRAFANA_BASE_URL env var to override Logging.Grafana.BaseUrl") - c.Logging.Grafana.BaseUrl = &baseUrl + logger.Info().Msgf("Using %s env var to override Logging.Grafana.BaseUrl", E2E_TEST_GRAFANA_BASE_URL_ENV) + c.Logging.Grafana.BaseUrl = &grafanaBaseUrl } - grafanaDashboardUrl, err := readEnvVarValue("E2E_TEST_GRAFANA_DASHBOARD_URL", String) - if err != nil { - return err - } - if grafanaDashboardUrl != nil && grafanaDashboardUrl.(string) != "" { + grafanaDashboardUrl := MustReadEnvVar_String(E2E_TEST_GRAFANA_DASHBOARD_URL_ENV) + if grafanaDashboardUrl != "" { if c.Logging == nil { c.Logging = &LoggingConfig{} } if c.Logging.Grafana == nil { c.Logging.Grafana = &GrafanaConfig{} } - dashboardUrl := grafanaDashboardUrl.(string) - logger.Debug().Msgf("Using E2E_TEST_GRAFANA_DASHBOARD_URL env var to override Logging.Grafana.DashboardUrl") - c.Logging.Grafana.DashboardUrl = &dashboardUrl + logger.Info().Msgf("Using %s env var to override Logging.Grafana.DashboardUrl", E2E_TEST_GRAFANA_DASHBOARD_URL_ENV) + c.Logging.Grafana.DashboardUrl = &grafanaDashboardUrl } - grafanaBearerToken, err := readEnvVarValue("E2E_TEST_GRAFANA_BEARER_TOKEN", String) - if err != nil { - return err - } - if grafanaBearerToken != nil && grafanaBearerToken.(string) != "" { + grafanaBearerToken := MustReadEnvVar_String(E2E_TEST_GRAFANA_BEARER_TOKEN_ENV) + if grafanaBearerToken != "" { if c.Logging == nil { c.Logging = &LoggingConfig{} } if c.Logging.Grafana == nil { c.Logging.Grafana = &GrafanaConfig{} } - bearerToken := grafanaBearerToken.(string) - logger.Debug().Msgf("Using E2E_TEST_GRAFANA_BEARER_TOKEN env var to override Logging.Grafana.BearerToken") - c.Logging.Grafana.BearerToken = &bearerToken + logger.Info().Msgf("Using %s env var to override Logging.Grafana.BearerToken", E2E_TEST_GRAFANA_BEARER_TOKEN_ENV) + c.Logging.Grafana.BearerToken = &grafanaBearerToken } - pyroscopeServerUrl, err := readEnvVarValue("E2E_TEST_PYROSCOPE_SERVER_URL", String) - if err != nil { - return err - } - if pyroscopeServerUrl != nil && pyroscopeServerUrl.(string) != "" { + pyroscopeEnabled := MustReadEnvVar_Boolean(E2E_TEST_PYROSCOPE_ENABLED_ENV) + if pyroscopeEnabled != nil { if c.Pyroscope == nil { c.Pyroscope = &PyroscopeConfig{} } - serverUrl := pyroscopeServerUrl.(string) - logger.Debug().Msgf("Using E2E_TEST_PYROSCOPE_SERVER_URL env var to override Pyroscope.ServerUrl") - c.Pyroscope.ServerUrl = &serverUrl + logger.Info().Msgf("Using %s env var to override Pyroscope.Enabled", E2E_TEST_PYROSCOPE_ENABLED_ENV) + c.Pyroscope.Enabled = pyroscopeEnabled } - pyroscopeKey, err := readEnvVarValue("E2E_TEST_PYROSCOPE_KEY", String) - if err != nil { - return err - } - if pyroscopeKey != nil && pyroscopeKey.(string) != "" { + pyroscopeServerUrl := MustReadEnvVar_String(E2E_TEST_PYROSCOPE_SERVER_URL_ENV) + if pyroscopeServerUrl != "" { if c.Pyroscope == nil { c.Pyroscope = &PyroscopeConfig{} } - key := pyroscopeKey.(string) - logger.Debug().Msgf("Using E2E_TEST_PYROSCOPE_KEY env var to override Pyroscope.Key") - c.Pyroscope.Key = &key + logger.Info().Msgf("Using %s env var to override Pyroscope.ServerUrl", E2E_TEST_PYROSCOPE_SERVER_URL_ENV) + c.Pyroscope.ServerUrl = &pyroscopeServerUrl } - pyroscopeEnvironment, err := readEnvVarValue("E2E_TEST_PYROSCOPE_ENVIRONMENT", String) - if err != nil { - return err - } - if pyroscopeEnvironment != nil && pyroscopeEnvironment.(string) != "" { + pyroscopeKey := MustReadEnvVar_String(E2E_TEST_PYROSCOPE_KEY_ENV) + if pyroscopeKey != "" { if c.Pyroscope == nil { c.Pyroscope = &PyroscopeConfig{} } - environment := pyroscopeEnvironment.(string) - logger.Debug().Msgf("Using E2E_TEST_PYROSCOPE_ENVIRONMENT env var to override Pyroscope.Environment") - c.Pyroscope.Environment = &environment + logger.Info().Msgf("Using %s env var to override Pyroscope.Key", E2E_TEST_PYROSCOPE_KEY_ENV) + c.Pyroscope.Key = &pyroscopeKey } - pyroscopeEnabled, err := readEnvVarValue("E2E_TEST_PYROSCOPE_ENABLED", Boolean) - if err != nil { - return err - } - if pyroscopeEnabled != nil { - if c.Pyroscope == nil { - c.Pyroscope = &PyroscopeConfig{} + walletKeys := ReadEnvVarGroupedMap(E2E_TEST_WALLET_KEY_ENV, E2E_TEST_WALLET_KEYS_ENV) + if len(walletKeys) > 0 { + if c.Network == nil { + c.Network = &NetworkConfig{} } - enabled := pyroscopeEnabled.(bool) - logger.Debug().Msgf("Using E2E_TEST_PYROSCOPE_ENABLED env var to override Pyroscope.Enabled") - c.Pyroscope.Enabled = &enabled + logger.Info().Msgf("Using %s and/or %s env vars to override Network.WalletKeys", E2E_TEST_WALLET_KEY_ENV, E2E_TEST_WALLET_KEYS_ENV) + c.Network.WalletKeys = walletKeys } - return nil -} - -// loadEnvVarGroupedMap scans all environment variables, matches them against -// a specified pattern, and returns a map of grouped values based on the pattern. -// The grouping is defined by the first capture group of the regex. -func loadEnvVarGroupedMap(pattern string) map[string][]string { - logger := logging.GetTestLogger(nil) - re := regexp.MustCompile(pattern) - groupedVars := make(map[string][]string) - for _, env := range os.Environ() { - pair := strings.SplitN(env, "=", 2) - if len(pair) != 2 { - continue - } - key, value := pair[0], pair[1] - matches := re.FindStringSubmatch(key) - if len(matches) > 1 && value != "" { - group := matches[1] // Use the first capture group for grouping - groupedVars[group] = append(groupedVars[group], value) - logger.Debug().Msgf("Will override test config from env var '%s'", key) + rpcHttpUrls := ReadEnvVarGroupedMap(E2E_TEST_RPC_HTTP_URL_ENV, E2E_TEST_RPC_HTTP_URLS_ENV) + if len(rpcHttpUrls) > 0 { + if c.Network == nil { + c.Network = &NetworkConfig{} } + logger.Info().Msgf("Using %s and/or %s env vars to override Network.RpcHttpUrls", E2E_TEST_RPC_HTTP_URL_ENV, E2E_TEST_RPC_HTTP_URLS_ENV) + c.Network.RpcHttpUrls = rpcHttpUrls } - return groupedVars -} -func loadEnvVarSingleMap(pattern string) map[string]string { - logger := logging.GetTestLogger(nil) - re := regexp.MustCompile(pattern) - singleVars := make(map[string]string) - for _, env := range os.Environ() { - pair := strings.SplitN(env, "=", 2) - if len(pair) != 2 { - continue - } - key, value := pair[0], pair[1] - matches := re.FindStringSubmatch(key) - if len(matches) > 1 && value != "" { - group := matches[1] // Use the first capture group for grouping - singleVars[group] = value - logger.Debug().Msgf("Will override test config from env var '%s'", key) + rpcWsUrls := ReadEnvVarGroupedMap(E2E_TEST_RPC_WS_URL_ENV, E2E_TEST_RPC_WS_URLS_ENV) + if len(rpcWsUrls) > 0 { + if c.Network == nil { + c.Network = &NetworkConfig{} } - } - return singleVars -} - -// Merges a map[string]string with a map[string][]string and returns a new map[string][]string. -// Elements from the single map are inserted at index 0 in the slice of the new map. -func mergeMaps(single map[string]string, multi map[string][]string) map[string][]string { - newMap := make(map[string][]string) - - // First, copy all elements from the multi map to the new map - for key, values := range multi { - newMap[key] = make([]string, len(values)) - copy(newMap[key], values) + logger.Info().Msgf("Using %s and/or %s env vars to override Network.RpcWsUrls", E2E_TEST_RPC_WS_URL_ENV, E2E_TEST_RPC_WS_URLS_ENV) + c.Network.RpcWsUrls = rpcWsUrls } - // Next, insert or prepend the elements from the single map - for key, value := range single { - if existingValues, exists := newMap[key]; exists { - // Prepend the value from the single map - newMap[key] = append([]string{value}, existingValues...) - } else { - // Initialize a new slice if the key does not exist - newMap[key] = []string{value} + chainlinkImage := MustReadEnvVar_String(E2E_TEST_CHAINLINK_IMAGE_ENV) + if chainlinkImage != "" { + if c.ChainlinkImage == nil { + c.ChainlinkImage = &ChainlinkImageConfig{} } + logger.Info().Msgf("Using %s env var to override ChainlinkImage.Image", E2E_TEST_CHAINLINK_IMAGE_ENV) + c.ChainlinkImage.Image = &chainlinkImage } - return newMap -} - -type EnvValueType int - -const ( - String EnvValueType = iota - Integer - Boolean - Float -) - -// readEnvVarValue reads an environment variable and returns the value parsed according to the specified type. -func readEnvVarValue(envVarName string, valueType EnvValueType) (interface{}, error) { - // Get the environment variable value - value, isSet := os.LookupEnv(envVarName) - if !isSet { - return nil, nil - } - if isSet && value == "" { - return "", nil // Return "" if the environment variable is not set - } - - // Parse the value according to the specified type - switch valueType { - case Integer: - intVal, err := strconv.Atoi(value) - if err != nil { - return nil, fmt.Errorf("error converting value to integer: %v", err) - } - return intVal, nil - case Boolean: - boolVal, err := strconv.ParseBool(value) - if err != nil { - return nil, fmt.Errorf("error converting value to boolean: %v", err) - } - return boolVal, nil - case Float: - floatVal, err := strconv.ParseFloat(value, 64) - if err != nil { - return nil, fmt.Errorf("error converting value to float: %v", err) + chainlinkUpgradeImage := MustReadEnvVar_String(E2E_TEST_CHAINLINK_UPGRADE_IMAGE_ENV) + if chainlinkUpgradeImage != "" { + if c.ChainlinkUpgradeImage == nil { + c.ChainlinkUpgradeImage = &ChainlinkImageConfig{} } - return floatVal, nil - default: // String or unrecognized type - return value, nil + logger.Info().Msgf("Using %s env var to override ChainlinkUpgradeImage.Image", E2E_TEST_CHAINLINK_UPGRADE_IMAGE_ENV) + c.ChainlinkUpgradeImage.Image = &chainlinkUpgradeImage } + + return nil } func LoadSecretEnvsFromFiles() error { diff --git a/config/testconfig_test.go b/config/testconfig_test.go index f94b46a7a..fd67c7d9c 100644 --- a/config/testconfig_test.go +++ b/config/testconfig_test.go @@ -98,7 +98,7 @@ func TestReadConfigValuesFromEnvVars(t *testing.T) { c := &TestConfig{} // Execute - err := c.ReadConfigValuesFromEnvVars() + err := c.ReadFromEnvVar() // Verify error handling if !errors.Is(err, localTt.expectedError) { From 4f782feed17656c916f42ecf340a9daa127c1819 Mon Sep 17 00:00:00 2001 From: Lukasz <120112546+lukaszcl@users.noreply.github.com> Date: Mon, 15 Jul 2024 16:42:08 +0200 Subject: [PATCH 04/26] Allow to read pyroscope environment from env (#1029) --- config/testconfig.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/config/testconfig.go b/config/testconfig.go index 08bf1c1af..65b7ade4b 100644 --- a/config/testconfig.go +++ b/config/testconfig.go @@ -163,6 +163,15 @@ func (c *TestConfig) ReadFromEnvVar() error { c.Pyroscope.Key = &pyroscopeKey } + pyroscopeEnvironment := MustReadEnvVar_String(E2E_TEST_PYROSCOPE_ENVIRONMENT_ENV) + if pyroscopeEnvironment != "" { + if c.Pyroscope == nil { + c.Pyroscope = &PyroscopeConfig{} + } + logger.Info().Msgf("Using %s env var to override Pyroscope.Environment", E2E_TEST_PYROSCOPE_ENVIRONMENT_ENV) + c.Pyroscope.Environment = &pyroscopeEnvironment + } + walletKeys := ReadEnvVarGroupedMap(E2E_TEST_WALLET_KEY_ENV, E2E_TEST_WALLET_KEYS_ENV) if len(walletKeys) > 0 { if c.Network == nil { From 258e4a65dcc10f1360c0862ff7f64900f2343ee3 Mon Sep 17 00:00:00 2001 From: Sergey Kudasov Date: Tue, 16 Jul 2024 00:53:05 +0200 Subject: [PATCH 05/26] bump to k8s v0.28.2 (#1021) * update to k8s v0.28.2 * fix deprecated functions --- go.mod | 78 ++++++++++++++------- go.sum | 129 +++++++++++++---------------------- k8s/client/client.go | 2 +- k8s/environment/artifacts.go | 2 +- 4 files changed, 103 insertions(+), 108 deletions(-) diff --git a/go.mod b/go.mod index 7d0a104a5..bc6eb61fc 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/aws/jsii-runtime-go v1.75.0 github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 - github.com/chaos-mesh/chaos-mesh/api/v1alpha1 v0.0.0-20220226050744-799408773657 + github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f github.com/docker/docker v25.0.2+incompatible github.com/docker/go-connections v0.5.0 github.com/ethereum/go-ethereum v1.13.8 @@ -21,7 +21,7 @@ require ( github.com/joho/godotenv v1.5.1 github.com/kelseyhightower/envconfig v1.4.0 github.com/lib/pq v1.10.9 - github.com/onsi/gomega v1.27.8 + github.com/onsi/gomega v1.27.10 github.com/otiai10/copy v1.14.0 github.com/pelletier/go-toml/v2 v2.2.2 github.com/pkg/errors v0.9.1 @@ -31,7 +31,7 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/seth v1.0.11 github.com/smartcontractkit/wasp v0.4.1 - github.com/spf13/cobra v1.6.1 + github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.28.0 @@ -43,7 +43,7 @@ require ( golang.org/x/text v0.14.0 k8s.io/api v0.28.2 k8s.io/apimachinery v0.28.2 - k8s.io/cli-runtime v0.25.11 + k8s.io/cli-runtime v0.28.2 k8s.io/client-go v0.28.2 k8s.io/kubectl v0.25.11 ) @@ -92,7 +92,7 @@ require ( github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/containerd/containerd v1.7.12 // indirect github.com/containerd/log v0.1.0 // indirect - github.com/coreos/go-semver v0.3.0 // indirect + github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect @@ -116,7 +116,7 @@ require ( github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/fvbommel/sortorder v1.0.2 // indirect + github.com/fvbommel/sortorder v1.1.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect @@ -152,7 +152,7 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/gnostic v0.6.9 // indirect + github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect @@ -244,7 +244,7 @@ require ( github.com/rivo/uniseg v0.4.4 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect - github.com/russross/blackfriday v1.6.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/sercand/kuberesolver/v5 v5.1.1 // indirect github.com/sergi/go-diff v1.3.1 // indirect @@ -265,11 +265,11 @@ require ( github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect github.com/uber/jaeger-lib v2.4.1+incompatible // indirect github.com/ugorji/go/codec v1.2.11 // indirect - github.com/xlab/treeprint v1.1.0 // indirect + github.com/xlab/treeprint v1.2.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - go.etcd.io/etcd/api/v3 v3.5.7 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect - go.etcd.io/etcd/client/v3 v3.5.7 // indirect + go.etcd.io/etcd/api/v3 v3.5.9 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect + go.etcd.io/etcd/client/v3 v3.5.9 // indirect go.mongodb.org/mongo-driver v1.12.0 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0015 // indirect go.opentelemetry.io/collector/semconv v0.81.0 // indirect @@ -277,7 +277,7 @@ require ( go.opentelemetry.io/otel v1.19.0 // indirect go.opentelemetry.io/otel/metric v1.19.0 // indirect go.opentelemetry.io/otel/trace v1.19.0 // indirect - go.starlark.net v0.0.0-20220817180228-f738f5508c12 // indirect + go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/goleak v1.2.1 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.3.0 // indirect @@ -290,7 +290,7 @@ require ( golang.org/x/term v0.15.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.15.0 // indirect - gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a // indirect @@ -300,17 +300,17 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.25.3 // indirect - k8s.io/component-base v0.26.2 // indirect + k8s.io/apiextensions-apiserver v0.28.1 // indirect + k8s.io/component-base v0.28.2 // indirect k8s.io/klog/v2 v2.100.1 // indirect k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect nhooyr.io/websocket v1.8.7 // indirect rsc.io/tmplfunc v0.0.3 // indirect - sigs.k8s.io/controller-runtime v0.13.0 // indirect + sigs.k8s.io/controller-runtime v0.16.2 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kustomize/api v0.12.1 // indirect - sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect + sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect + sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) @@ -319,12 +319,38 @@ require ( exclude github.com/hashicorp/consul v1.2.1 // K8s versions are infuriatingly inconsistent, so we pin them here. -replace ( - // replicating the replace directive on cosmos SDK - github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 +// replicating the replace directive on cosmos SDK +replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 - // K8s versions are infuriatingly inconsistent, so we pin them here. - k8s.io/api => k8s.io/api v0.25.11 - k8s.io/client-go => k8s.io/client-go v0.25.11 - k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d +replace ( + k8s.io/api => k8s.io/api v0.28.2 + k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.28.2 + k8s.io/apimachinery => k8s.io/apimachinery v0.28.2 + k8s.io/apiserver => k8s.io/apiserver v0.28.2 + k8s.io/cli-runtime => k8s.io/cli-runtime v0.28.2 + k8s.io/client-go => k8s.io/client-go v0.28.2 + k8s.io/cloud-provider => k8s.io/cloud-provider v0.28.2 + k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.28.2 + k8s.io/code-generator => k8s.io/code-generator v0.28.2 + k8s.io/component-base => k8s.io/component-base v0.28.2 + k8s.io/component-helpers => k8s.io/component-helpers v0.28.2 + k8s.io/controller-manager => k8s.io/controller-manager v0.28.2 + k8s.io/cri-api => k8s.io/cri-api v0.28.2 + k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.28.2 + k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.28.2 + k8s.io/endpointslice => k8s.io/endpointslice v0.28.2 + k8s.io/kms => k8s.io/kms v0.28.2 + k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.28.2 + k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.28.2 + k8s.io/kube-proxy => k8s.io/kube-proxy v0.28.2 + k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.28.2 + k8s.io/kubectl => k8s.io/kubectl v0.28.2 + k8s.io/kubelet => k8s.io/kubelet v0.28.2 + k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.28.2 + k8s.io/metrics => k8s.io/metrics v0.28.2 + k8s.io/mount-utils => k8s.io/mount-utils v0.28.2 + k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.28.2 + k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.28.2 + k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.28.2 + k8s.io/sample-controller => k8s.io/sample-controller v0.28.2 ) diff --git a/go.sum b/go.sum index 8474f557e..57a7dde24 100644 --- a/go.sum +++ b/go.sum @@ -13,17 +13,12 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= -cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -122,7 +117,6 @@ github.com/alicebob/miniredis/v2 v2.30.4/go.mod h1:b25qWj4fCEsBeAAR2mlb0ufImGC6u github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -185,8 +179,8 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= -github.com/chaos-mesh/chaos-mesh/api/v1alpha1 v0.0.0-20220226050744-799408773657 h1:CyuI+igIjadM/GRnE2o0q+WCwipDh0n2cUYFPAvxziM= -github.com/chaos-mesh/chaos-mesh/api/v1alpha1 v0.0.0-20220226050744-799408773657/go.mod h1:JRiumF+RFsH1mrrP8FUsi9tExPylKkO/oSRWeQEUdLE= +github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f h1:onZ3oc6l1Gz8pVpQ0c1U1Cb11kIMoDb3xtEy/iZbYZM= +github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f/go.mod h1:x11iCbZV6hzzSQWMq610B6Wl5Lg1dhwqcVfeiWQQnQQ= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= @@ -198,7 +192,6 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= @@ -227,8 +220,8 @@ github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= @@ -272,7 +265,6 @@ github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -284,9 +276,7 @@ github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -297,7 +287,6 @@ github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= -github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= @@ -319,14 +308,13 @@ github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBd github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo= -github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= +github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= +github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= @@ -337,7 +325,6 @@ github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.19.0 h1:BcCH3CN5tXt5aML+gwmbFwVptLLQA+eT866fCO9wVOM= github.com/getsentry/sentry-go v0.19.0/go.mod h1:y3+lGEFEFexZtpbG1GUE2WD/f9zGyKYwpEqryTOC/nE= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= @@ -368,8 +355,8 @@ github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= @@ -520,8 +507,6 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= -github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -595,7 +580,6 @@ github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWf github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= @@ -675,7 +659,6 @@ github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ionos-cloud/sdk-go/v6 v6.1.8 h1:493wE/BkZxJf7x79UCE0cYGPZoqQcPiEBALvt7uVGY0= @@ -742,7 +725,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -887,14 +869,14 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= -github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= +github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= +github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= -github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= @@ -987,7 +969,6 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1002,8 +983,6 @@ github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= -github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -1057,8 +1036,8 @@ github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -1066,7 +1045,6 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -1134,8 +1112,8 @@ github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gi github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= -github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= +github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= +github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= @@ -1154,12 +1132,12 @@ github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY= -go.etcd.io/etcd/api/v3 v3.5.7/go.mod h1:9qew1gCdDDLu+VwmeG+iFpL+QlpHTo7iubavdVDgCAA= -go.etcd.io/etcd/client/pkg/v3 v3.5.7 h1:y3kf5Gbp4e4q7egZdn5T7W9TSHUvkClN6u+Rq9mEOmg= -go.etcd.io/etcd/client/pkg/v3 v3.5.7/go.mod h1:o0Abi1MK86iad3YrWhgUsbGx1pmTS+hrORWc2CamuhY= -go.etcd.io/etcd/client/v3 v3.5.7 h1:u/OhpiuCgYY8awOHlhIhmGIGpxfBU/GZBUP3m/3/Iz4= -go.etcd.io/etcd/client/v3 v3.5.7/go.mod h1:sOWmj9DZUMyAngS7QQwCyAXXAL6WhgTOPLNS/NabQgw= +go.etcd.io/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs= +go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k= +go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE= +go.etcd.io/etcd/client/pkg/v3 v3.5.9/go.mod h1:y+CzeSmkMpWN2Jyu1npecjB9BBnABxGM4pN8cGuJeL4= +go.etcd.io/etcd/client/v3 v3.5.9 h1:r5xghnU7CwbUxD/fbUtRyJGaYNfDun8sp/gTr1hew6E= +go.etcd.io/etcd/client/v3 v3.5.9/go.mod h1:i/Eo5LrZ5IKqpbtpPDuaUnDOUv471oDg8cjQaUr2MbA= go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= @@ -1178,7 +1156,6 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q= go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= -go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= @@ -1189,11 +1166,10 @@ go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJ go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -go.starlark.net v0.0.0-20220817180228-f738f5508c12 h1:xOBJXWGEDwU5xSDxH6macxO11Us0AH2fTa9rmsbbF7g= -go.starlark.net v0.0.0-20220817180228-f738f5508c12/go.mod h1:VZcBMdr3cT3PnBoWunTabuSEXwVAH+ZJ5zxfs3AdASk= +go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= +go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= @@ -1309,7 +1285,6 @@ golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -1430,6 +1405,7 @@ golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= @@ -1513,8 +1489,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= -gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1564,7 +1540,6 @@ google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= @@ -1572,7 +1547,6 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a h1:myvhA4is3vrit1a6NZCWBIwN0kNEnX21DJOJX/NvIfI= @@ -1593,10 +1567,7 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1611,7 +1582,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1631,13 +1601,12 @@ gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1660,24 +1629,24 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.25.11 h1:4mjYDfE3yp22jrytjH0knwgzjXKkxHX4D01ZCAazvZM= -k8s.io/api v0.25.11/go.mod h1:bK4UvD4bthtutNlvensrfBX21PRQ/vs2cIYggHkOOAo= -k8s.io/apiextensions-apiserver v0.25.3 h1:bfI4KS31w2f9WM1KLGwnwuVlW3RSRPuIsfNF/3HzR0k= -k8s.io/apiextensions-apiserver v0.25.3/go.mod h1:ZJqwpCkxIx9itilmZek7JgfUAM0dnTsA48I4krPqRmo= +k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= +k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= +k8s.io/apiextensions-apiserver v0.28.2 h1:J6/QRWIKV2/HwBhHRVITMLYoypCoPY1ftigDM0Kn+QU= +k8s.io/apiextensions-apiserver v0.28.2/go.mod h1:5tnkxLGa9nefefYzWuAlWZ7RZYuN/765Au8cWLA6SRg= k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= -k8s.io/cli-runtime v0.25.11 h1:GE2yNZm1tN+MJtw1SGMOLesLF7Kp7NVAVqRSTbXfu4o= -k8s.io/cli-runtime v0.25.11/go.mod h1:r/nEINuHVEpgGhcd2WamU7hD1t/lMnSz8XM44Autltc= -k8s.io/client-go v0.25.11 h1:DJQ141UsbNRI6wYSlcYLP5J5BW5Wq7Bgm42Ztq2SW70= -k8s.io/client-go v0.25.11/go.mod h1:41Xs7p1SfhoReUnmjjYCfCNWFiq4xSkexwJfbxF2F7A= -k8s.io/component-base v0.26.2 h1:IfWgCGUDzrD6wLLgXEstJKYZKAFS2kO+rBRi0p3LqcI= -k8s.io/component-base v0.26.2/go.mod h1:DxbuIe9M3IZPRxPIzhch2m1eT7uFrSBJUBuVCQEBivs= +k8s.io/cli-runtime v0.28.2 h1:64meB2fDj10/ThIMEJLO29a1oujSm0GQmKzh1RtA/uk= +k8s.io/cli-runtime v0.28.2/go.mod h1:bTpGOvpdsPtDKoyfG4EG041WIyFZLV9qq4rPlkyYfDA= +k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= +k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= +k8s.io/component-base v0.28.2 h1:Yc1yU+6AQSlpJZyvehm/NkJBII72rzlEsd6MkBQ+G0E= +k8s.io/component-base v0.28.2/go.mod h1:4IuQPQviQCg3du4si8GpMrhAIegxpsgPngPRR/zWpzc= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d h1:VcFq5n7wCJB2FQMCIHfC+f+jNcGgNMar1uKd6rVlifU= -k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= -k8s.io/kubectl v0.25.11 h1:6bsft5Gan6BCvQ7cJbDRFjTm4Zfq8GuUYpsWAdVngYE= -k8s.io/kubectl v0.25.11/go.mod h1:8mIfgkFgT+yJ8/TlmPW1qoRh46H2si9q5nW8id7i9iM= +k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= +k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= +k8s.io/kubectl v0.28.2 h1:fOWOtU6S0smdNjG1PB9WFbqEIMlkzU5ahyHkc7ESHgM= +k8s.io/kubectl v0.28.2/go.mod h1:6EQWTPySF1fn7yKoQZHYf9TPwIl2AygHEcJoxFekr64= k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc= k8s.io/utils v0.0.0-20230711102312-30195339c3c7/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= @@ -1688,14 +1657,14 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= -sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ= -sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= +sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= +sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.12.1 h1:7YM7gW3kYBwtKvoY216ZzY+8hM+lV53LUayghNRJ0vM= -sigs.k8s.io/kustomize/api v0.12.1/go.mod h1:y3JUhimkZkR6sbLNwfJHxvo1TCLwuwm14sCYnkH6S1s= -sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk= -sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4= +sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0= +sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= +sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U= +sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag= sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= diff --git a/k8s/client/client.go b/k8s/client/client.go index 77e9047bd..6f1543dac 100644 --- a/k8s/client/client.go +++ b/k8s/client/client.go @@ -555,7 +555,7 @@ func (m *K8sClient) ExecuteInPod(namespace, podName, containerName string, comma } var stdout, stderr bytes.Buffer - err = exec.Stream(remotecommand.StreamOptions{ + err = exec.StreamWithContext(context.Background(), remotecommand.StreamOptions{ Stdin: nil, Stdout: &stdout, Stderr: &stderr, diff --git a/k8s/environment/artifacts.go b/k8s/environment/artifacts.go index 753968a45..08d3f43a7 100644 --- a/k8s/environment/artifacts.go +++ b/k8s/environment/artifacts.go @@ -94,7 +94,7 @@ func (a *Artifacts) dumpDB(pod coreV1.Pod, container coreV1.Container) (string, return "", err } outBuff, errBuff := &bytes.Buffer{}, &bytes.Buffer{} - err = exec.Stream(remotecommand.StreamOptions{ + err = exec.StreamWithContext(context.Background(), remotecommand.StreamOptions{ Stdin: &bytes.Reader{}, Stdout: outBuff, Stderr: errBuff, From 9d88f6d6168dc771e3f419d528dc27d8f39983bd Mon Sep 17 00:00:00 2001 From: Lukasz <120112546+lukaszcl@users.noreply.github.com> Date: Wed, 17 Jul 2024 16:25:53 +0200 Subject: [PATCH 06/26] Add envresolve tool (#1030) --- tools/envresolve/go.mod | 13 +++++++++++++ tools/envresolve/go.sum | 12 ++++++++++++ tools/envresolve/main.go | 31 +++++++++++++++++++++++++++++++ utils/env_vars.go | 30 ++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 tools/envresolve/go.mod create mode 100644 tools/envresolve/go.sum create mode 100644 tools/envresolve/main.go create mode 100644 utils/env_vars.go diff --git a/tools/envresolve/go.mod b/tools/envresolve/go.mod new file mode 100644 index 000000000..0c4fa8a65 --- /dev/null +++ b/tools/envresolve/go.mod @@ -0,0 +1,13 @@ +module github.com/smartcontractkit/chainlink-testing-framework/tools/envresolve + +go 1.22.5 + +require ( + github.com/smartcontractkit/chainlink-testing-framework v1.32.5-0.20240716133725-a3b8de948a76 + github.com/spf13/cobra v1.8.1 +) + +require ( + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect +) diff --git a/tools/envresolve/go.sum b/tools/envresolve/go.sum new file mode 100644 index 000000000..f3caa5881 --- /dev/null +++ b/tools/envresolve/go.sum @@ -0,0 +1,12 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/smartcontractkit/chainlink-testing-framework v1.32.5-0.20240716133725-a3b8de948a76 h1:U3hc8y9ave4rTINBhqtlVJpgUftEfQq4GO8avP64H5M= +github.com/smartcontractkit/chainlink-testing-framework v1.32.5-0.20240716133725-a3b8de948a76/go.mod h1:5MSx/ZFLZZCzovF0TZU28dy2XPGznlc/sa2pgUN/8D8= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tools/envresolve/main.go b/tools/envresolve/main.go new file mode 100644 index 000000000..144b1087e --- /dev/null +++ b/tools/envresolve/main.go @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/smartcontractkit/chainlink-testing-framework/utils" +) + +func main() { + var rootCmd = &cobra.Command{ + Use: "envresolve", + Short: "Resolve environment variables in a string. Example envresolve '{{ env.CHAINLINK_IMAGE }}'", + Run: func(cmd *cobra.Command, args []string) { + if len(args) < 1 { + fmt.Fprintln(cmd.OutOrStdout(), "Error: No input provided") + return + } + input := args[0] + + fmt.Fprintln(cmd.OutOrStdout(), utils.MustResolveEnvPlaceholder(input)) + }, + } + + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} diff --git a/utils/env_vars.go b/utils/env_vars.go new file mode 100644 index 000000000..3eb5f74f0 --- /dev/null +++ b/utils/env_vars.go @@ -0,0 +1,30 @@ +package utils + +import ( + "fmt" + "os" + "regexp" +) + +// mustResolveEnvPlaceholder checks if the input string is an environment variable placeholder and resolves it. +func MustResolveEnvPlaceholder(input string) string { + envVarName, hasEnvVar := LookupEnvVarName(input) + if hasEnvVar { + value, set := os.LookupEnv(envVarName) + if !set { + fmt.Fprintf(os.Stderr, "Error resolving '%s'. Environment variable '%s' not set or is empty\n", input, envVarName) + os.Exit(1) + } + return value + } + return input +} + +func LookupEnvVarName(input string) (string, bool) { + re := regexp.MustCompile(`^{{ env\.([a-zA-Z_]+) }}$`) + matches := re.FindStringSubmatch(input) + if len(matches) > 1 { + return matches[1], true + } + return "", false +} From 213de0e178c85830b24159c38dda29aac2077c5d Mon Sep 17 00:00:00 2001 From: Lukasz <120112546+lukaszcl@users.noreply.github.com> Date: Wed, 17 Jul 2024 17:45:56 +0200 Subject: [PATCH 07/26] Add missing package.json for envresolve (#1031) * Add missing package.json for envresolve * Update release-tools.yml --- .github/workflows/release-tools.yaml | 1 + tools/envresolve/package.json | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 tools/envresolve/package.json diff --git a/.github/workflows/release-tools.yaml b/.github/workflows/release-tools.yaml index 71454b62f..7bf1101fa 100644 --- a/.github/workflows/release-tools.yaml +++ b/.github/workflows/release-tools.yaml @@ -10,6 +10,7 @@ jobs: matrix: tool: [ + tools/envresolve, tools/gotestloghelper, tools/testlistgenerator, tools/ecrimagefetcher, diff --git a/tools/envresolve/package.json b/tools/envresolve/package.json new file mode 100644 index 000000000..35cc0e53a --- /dev/null +++ b/tools/envresolve/package.json @@ -0,0 +1,5 @@ +{ + "name": "envresolve", + "description": "Resolve environment variables in a string. Example envresolve '{{ env.CHAINLINK_IMAGE }}'", + "version": "1.0.0" +} From 27be14aa812147e4c38bcb934ce3feb4f6e39042 Mon Sep 17 00:00:00 2001 From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com> Date: Tue, 30 Jul 2024 14:18:24 +0530 Subject: [PATCH 08/26] support --max-persisted-states in foundry/anvil (#1033) --- charts/foundry/Chart.yaml | 2 +- charts/foundry/templates/deployment.yaml | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/charts/foundry/Chart.yaml b/charts/foundry/Chart.yaml index 44d8216d4..a1b2e4885 100644 --- a/charts/foundry/Chart.yaml +++ b/charts/foundry/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: foundry description: A Helm chart for foundry, mostly used to run Anvil node type: application -version: 0.2.1 +version: 0.2.2 appVersion: 'latest' diff --git a/charts/foundry/templates/deployment.yaml b/charts/foundry/templates/deployment.yaml index 428494a31..daf4d0491 100644 --- a/charts/foundry/templates/deployment.yaml +++ b/charts/foundry/templates/deployment.yaml @@ -122,6 +122,10 @@ spec: - "--transaction-block-keeper" - {{ .Values.anvil.blocksToKeepInMemory | quote }} {{- end }} + {{- if .Values.anvil.maxPersistedStates }} + - "--max-persisted-states" + - {{ .Values.anvil.maxPersistedStates | quote }} + {{- end }} imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - name: http From e1b4280b001c1c51807a5112ee61e1baffb24703 Mon Sep 17 00:00:00 2001 From: Adam Hamrick Date: Tue, 30 Jul 2024 16:47:18 -0400 Subject: [PATCH 09/26] Fixes Image Pull Policy (#1035) * Fixes Image Pull Policy * Version bump --- charts/chainlink/Chart.yaml | 2 +- charts/chainlink/templates/chainlink-deployment.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/chainlink/Chart.yaml b/charts/chainlink/Chart.yaml index 3bf49b45c..7df8715fb 100644 --- a/charts/chainlink/Chart.yaml +++ b/charts/chainlink/Chart.yaml @@ -5,7 +5,7 @@ description: A Helm chart for Kubernetes # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.2.12 +version: 0.2.13 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/charts/chainlink/templates/chainlink-deployment.yaml b/charts/chainlink/templates/chainlink-deployment.yaml index 20e4a701d..9576312ac 100644 --- a/charts/chainlink/templates/chainlink-deployment.yaml +++ b/charts/chainlink/templates/chainlink-deployment.yaml @@ -47,7 +47,7 @@ spec: {{- end }} {{- end }} image: {{ $image }}:{{ $tag }} - imagePullPolicy: IfNotPresent + imagePullPolicy: Always command: [ "/bin/bash" ] args: - "-c" From 4ce33d7304aba46d68152503c408f3a62c5f4e9d Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Wed, 31 Jul 2024 11:15:45 +0200 Subject: [PATCH 10/26] [TT-1393] reth support update mirrors (#1023) --- .../update-internal-mirrors/action.yaml | 6 + .../scripts/update_mirrors.sh | 128 ++++++++++++++++-- .../workflows/update-internal-mirrors.yaml | 14 +- 3 files changed, 130 insertions(+), 18 deletions(-) diff --git a/.github/actions/update-internal-mirrors/action.yaml b/.github/actions/update-internal-mirrors/action.yaml index 1a38e4e04..bfeb691e6 100644 --- a/.github/actions/update-internal-mirrors/action.yaml +++ b/.github/actions/update-internal-mirrors/action.yaml @@ -19,6 +19,10 @@ inputs: description: 'Number of tags to return per page' required: false default: '100' + github_token: + description: 'Token to use for GitHub API, in most cases github.token' + required: true + runs: using: 'composite' steps: @@ -38,6 +42,8 @@ runs: AWS_REGION: ${{ inputs.aws_region }} - name: Update images shell: bash + env: + GHCR_TOKEN: ${{ inputs.github_token }} run: | # Update images # Change to the directory where the action is stored diff --git a/.github/actions/update-internal-mirrors/scripts/update_mirrors.sh b/.github/actions/update-internal-mirrors/scripts/update_mirrors.sh index a9eda98b2..dca3b3562 100755 --- a/.github/actions/update-internal-mirrors/scripts/update_mirrors.sh +++ b/.github/actions/update-internal-mirrors/scripts/update_mirrors.sh @@ -6,7 +6,6 @@ SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) cd "$SCRIPT_DIR"/../ || exit 1 -# Check if any arguments are provided if [ $# -eq 0 ]; then echo "Usage: $0 " exit 1 @@ -31,11 +30,9 @@ check_image_in_ecr() { local docker_image="$1" local repository_name image_tag - # Extract the repository name and tag from the docker image string repository_name=$(echo "$docker_image" | cut -d: -f1) image_tag=$(echo "$docker_image" | cut -d: -f2) - # If the image tag is empty, it means the image name did not include a tag, and we'll use "latest" by default if [[ -z "$image_tag" ]]; then image_tag="latest" fi @@ -53,13 +50,8 @@ pull_tag_push() { local docker_image=$1 local ecr_image="$ECR_REGISTRY_URL/${docker_image}" - # Pull the image from Docker Hub docker pull "$docker_image" - - # Tag the image for ECR docker tag "$docker_image" "$ecr_image" - - # Push the image to ECR docker push "$ecr_image" } @@ -88,11 +80,15 @@ push_latest_images_for_expression_from_dockerhub() { if [[ $image_name == gcr.io* ]]; then # Handle GCR images images=$(gcloud container images list-tags gcr.io/prysmaticlabs/prysm/validator --limit="${page_size}" --filter='tags:v*' --format=json | jq -r '.[].tags[]' | grep -E "${image_expression}") + elif [[ $image_name == ghcr.io* ]]; then + # Handle GitHub Container Registry images + images=$(fetch_images_from_gh_container_registry "${image_name}" "${image_expression}" "${page_size}") else images=$(fetch_images_from_dockerhub "${image_name}" "${image_expression}" "${page_size}") fi set -e + if [ -z "$images" ]; then echo "No images were found matching the expression. Either something went wrong or you need to increase the page size to greater than ${page_size}." exit 1 @@ -136,27 +132,133 @@ fetch_images_from_dockerhub() { echo "$images" } +# Function to fetch images from Github Container Registry with pagination support +fetch_images_from_gh_container_registry() { + local image_name="$1" + local image_expression="$2" + local max_image_count="$3" + + local org + local package + + org=$(echo "$image_name" | awk -F'[/:]' '{print $2}') + package=$(echo "$image_name" | awk -F'[/:]' '{print $3}') + + if [ -z "$org" ] || [ -z "$package" ]; then + >&2 echo "Error: Failed to extract organisation and package name from $image_name. Please provide the image name in the format ghcr.io/org/package." + exit 1 + fi + + if [ -z "$GHCR_TOKEN" ]; then + >&2 echo "Error: $GHCR_TOKEN environment variable is not set." + exit 1 + else + >&2 echo "::debug::GHCR_TOKEN is set" + fi + + local url="https://api.github.com/orgs/$org/packages?package_type=container" + >&2 echo "::debug::url: $url" + + local image_count=0 + local images="" + + while [ -n "$url" ]; do + response=$(curl -s -H "Authorization: Bearer $GHCR_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + "$url") + + >&2 echo "::debug::response: $response" + + if ! echo "$response" | jq empty > /dev/null 2>&1; then + >&2 echo "Error: Received invalid JSON response." + exit 1 + fi + + if echo "$response" | jq -e 'if type == "object" then (has("message") or has("status")) else false end' > /dev/null; then + message=$(echo "$response" | jq -r '.message // empty') + status=$(echo "$response" | jq -r '.status // empty') + + if [ -n "$status" ] && [ "$status" -eq "$status" ] 2>/dev/null && [ "$status" -gt 299 ]; then + >&2 echo "Error: Request to get containers failed with status $status and message: $message" + exit 1 + fi + fi + + packages=$(echo "$response" | jq -r --arg package "$package" '.[] | select(.name == $package) | .name') + + if [ -z "$packages" ]; then + >&2 echo "Error: No matching packages found." + exit 1 + fi + + for package in $packages; do + versions_url="https://api.github.com/orgs/$org/packages/container/$package/versions" + while [ -n "$versions_url" ]; do + versions_response=$(curl -s -H "Authorization: token $GHCR_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + "$versions_url") + + if ! echo "$versions_response" | jq empty > /dev/null 2>&1; then + >&2 echo "Error: Received invalid JSON response for versions." + exit 1 + fi + + tags=$(echo "$versions_response" | jq -r --arg regex "$image_expression" ' + .[] | + select(.metadata.container.tags | length > 0) | + .metadata.container.tags[] as $tag | + select($tag | test($regex)) | + $tag + ') + + while read -r tag; do + if [ "$image_count" -lt "$max_image_count" ]; then + images+="$tag"$'\n' + ((image_count++)) + else + break 2 + fi + done <<< "$tags" + + if [ "$image_count" -ge "$max_image_count" ]; then + images=$(echo "$images" | grep -v '^\s*$') + echo "$images" + return + fi + + versions_url=$(curl -sI -H "Authorization: token $GHCR_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + "$versions_url" | awk -F'[<>]' '/rel="next"/{print $2}') + done + done + + url=$(curl -sI -H "Authorization: token $GHCR_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + "$url" | awk -F'[<>]' '/rel="next"/{print $2}') + done + + images=$(echo "$images" | grep -v '^\s*$') + echo "$images" +} + push_images_in_list() { local -a image_list=("$@") local prefix="library/" - # Iterate over the images + for docker_image in "${image_list[@]}"; do echo "---" echo "Checking if $docker_image exists in ECR..." - # Check if the image is a standard library image and needs the library/ prefix removed docker_image="${docker_image#"$prefix"}" - # Check if the image exists in ECR if ! check_image_in_ecr "$docker_image"; then echo "$docker_image does not exist in ECR. Mirroring image..." - # Pull, tag, and push the image to ECR + pull_tag_push "$docker_image" else echo "$docker_image already exists in ECR. Skipping..." fi done - } # Run the code diff --git a/.github/workflows/update-internal-mirrors.yaml b/.github/workflows/update-internal-mirrors.yaml index da170384a..b7b650e75 100644 --- a/.github/workflows/update-internal-mirrors.yaml +++ b/.github/workflows/update-internal-mirrors.yaml @@ -42,6 +42,8 @@ jobs: expression: '^v[0-9]+\.[0-9]+\.[0-9]+$' - name: nethermind/nethermind expression: '^[0-9]+\.[0-9]+\.[0-9]+$' + - name: ghcr.io/paradigmxyz/reth + expression: '^v[0-9]+\.[0-9]+\.[0-9]+$' - name: wiremock/wiremock expression: '^[0-9]+\.[0-9]+\.[0-9]+$' # disabled until gcloud auth is added @@ -51,15 +53,16 @@ jobs: # expression: '^v[0-9]+\.[0-9]+\.[0-9]+$' - name: tofelb/ethereum-genesis-generator expression: '^[0-9]+\.[0-9]+\.[0-9]+(\-slots\-per\-epoch)?' - # This one only has latest tag, probably only want to update it when we know for sure it's a new version we want - # - name: protolambda/eth2-val-tools - # expression: 'latest' + # This one only has latest tag, probably only want to update it when we know for sure it's a new version we want + # - name: protolambda/eth2-val-tools + # expression: 'latest' permissions: id-token: write contents: read + packages: read steps: - name: Update image - uses: smartcontractkit/chainlink-testing-framework/.github/actions/update-internal-mirrors@9190fa16db15bbb7caa5595b347c51acdda9eb3a + uses: smartcontractkit/chainlink-testing-framework/.github/actions/update-internal-mirrors@e7e2434b9616f4e984fa57024ce43f6a9f26688f with: aws_region: ${{ secrets.QA_AWS_REGION }} role_to_assume: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -67,6 +70,7 @@ jobs: image_name: ${{matrix.mirror.name}} expression: ${{matrix.mirror.expression}} page_size: ${{matrix.mirror.page_size}} + github_token: ${{ secrets.RETH_GH_TOKEN }} # needed only for checking GHRC.io repositories update-other-images: runs-on: ubuntu-latest @@ -76,7 +80,7 @@ jobs: contents: read steps: - name: Update other images - uses: smartcontractkit/chainlink-testing-framework/.github/actions/update-internal-mirrors@9190fa16db15bbb7caa5595b347c51acdda9eb3a + uses: smartcontractkit/chainlink-testing-framework/.github/actions/update-internal-mirrors@e7e2434b9616f4e984fa57024ce43f6a9f26688f with: aws_region: ${{ secrets.QA_AWS_REGION }} role_to_assume: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} From 352cf299b529a33208146d9f7f0e0b5534fba6e7 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Wed, 31 Jul 2024 21:44:33 +0200 Subject: [PATCH 11/26] remove k8s replaces (#1036) --- go.mod | 38 ++------------------------------------ 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/go.mod b/go.mod index bc6eb61fc..a3783c808 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( k8s.io/apimachinery v0.28.2 k8s.io/cli-runtime v0.28.2 k8s.io/client-go v0.28.2 - k8s.io/kubectl v0.25.11 + k8s.io/kubectl v0.28.2 ) require ( @@ -300,7 +300,7 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.28.1 // indirect + k8s.io/apiextensions-apiserver v0.28.2 // indirect k8s.io/component-base v0.28.2 // indirect k8s.io/klog/v2 v2.100.1 // indirect k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect @@ -318,39 +318,5 @@ require ( // avoids ambigious imports of indirect dependencies exclude github.com/hashicorp/consul v1.2.1 -// K8s versions are infuriatingly inconsistent, so we pin them here. // replicating the replace directive on cosmos SDK replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 - -replace ( - k8s.io/api => k8s.io/api v0.28.2 - k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.28.2 - k8s.io/apimachinery => k8s.io/apimachinery v0.28.2 - k8s.io/apiserver => k8s.io/apiserver v0.28.2 - k8s.io/cli-runtime => k8s.io/cli-runtime v0.28.2 - k8s.io/client-go => k8s.io/client-go v0.28.2 - k8s.io/cloud-provider => k8s.io/cloud-provider v0.28.2 - k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.28.2 - k8s.io/code-generator => k8s.io/code-generator v0.28.2 - k8s.io/component-base => k8s.io/component-base v0.28.2 - k8s.io/component-helpers => k8s.io/component-helpers v0.28.2 - k8s.io/controller-manager => k8s.io/controller-manager v0.28.2 - k8s.io/cri-api => k8s.io/cri-api v0.28.2 - k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.28.2 - k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.28.2 - k8s.io/endpointslice => k8s.io/endpointslice v0.28.2 - k8s.io/kms => k8s.io/kms v0.28.2 - k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.28.2 - k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.28.2 - k8s.io/kube-proxy => k8s.io/kube-proxy v0.28.2 - k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.28.2 - k8s.io/kubectl => k8s.io/kubectl v0.28.2 - k8s.io/kubelet => k8s.io/kubelet v0.28.2 - k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.28.2 - k8s.io/metrics => k8s.io/metrics v0.28.2 - k8s.io/mount-utils => k8s.io/mount-utils v0.28.2 - k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.28.2 - k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.28.2 - k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.28.2 - k8s.io/sample-controller => k8s.io/sample-controller v0.28.2 -) From acf86c1e347a9a97f927019281b446ab9868f954 Mon Sep 17 00:00:00 2001 From: Sergey Kudasov Date: Mon, 5 Aug 2024 13:16:47 +0200 Subject: [PATCH 12/26] Use DialOptions, custom RPC headers for RPC and Resty clients (#1032) * try root command * use DialOptions and custom RPC headers from env vars * remove root command * fix lint * add resty env headers everywhere * goimports * use headers explicitly, debug http * bump seth * simplify GAP connection, add README --- README.md | 7 +++ blockchain/config.go | 4 ++ blockchain/ethereum.go | 17 +++-- client/explorer.go | 4 +- client/kafka_rest.go | 4 +- client/mockserver.go | 23 ++++--- crib/README.md | 25 ++++++++ crib/config.go | 137 +++++++++++++++++++++++++++++++++++++++++ go.mod | 3 +- go.sum | 6 +- grafana/client.go | 8 ++- 11 files changed, 215 insertions(+), 23 deletions(-) create mode 100644 crib/README.md create mode 100644 crib/config.go diff --git a/README.md b/README.md index 1e51ef3c4..2670d2aab 100644 --- a/README.md +++ b/README.md @@ -416,3 +416,10 @@ We have two ways to add new images to the ecr. The first two requirements are th 1. If it does not have version numbers or is gcr then you can add it [here](./scripts/mirror.json) 2. You can add to the [mirror matrix](./.github/workflows/update-internal-mirrors.yaml) the new image name and an expression to get the latest versions added when the workflow runs. You can check the postgres one used in there for an example but basically the expression should filter out only the latest image or 2 for that particular version when calling the dockerhub endpoint, example curl call `curl -s "https://hub.docker.com/v2/repositories/${image_name}/tags/?page_size=100" | jq -r '.results[].name' | grep -E ${image_expression}` where image_name could be `library/postgres` and image_expression could be `'^[0-9]+\.[0-9]+$'`. Adding your ecr to this matrix should make sure we always have the latest versions for that expression. + +## Debugging HTTP and RPC calls + +```bash +export SETH_LOG_LEVEL=info +export RESTY_DEBUG=true +``` diff --git a/blockchain/config.go b/blockchain/config.go index 5b690e8f2..591f0e402 100644 --- a/blockchain/config.go +++ b/blockchain/config.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "net/http" "strings" "time" @@ -82,6 +83,9 @@ type EVMNetwork struct { // Only used internally, do not set URL string `ignored:"true"` + + // Only used internally, do not set + Headers http.Header `toml:"evm_headers" json:"evm_headers"` } // LoadNetworkFromEnvironment loads an EVM network from default environment variables. Helpful in soak tests diff --git a/blockchain/ethereum.go b/blockchain/ethereum.go index 4867a2645..3565f2400 100644 --- a/blockchain/ethereum.go +++ b/blockchain/ethereum.go @@ -1,3 +1,6 @@ +/* +This should be removed when we migrate all Ethereum client code to Seth +*/ package blockchain // Contains implementations for multi and single node ethereum clients @@ -32,7 +35,10 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" ) -const MaxTimeoutForFinality = 15 * time.Minute +const ( + MaxTimeoutForFinality = 15 * time.Minute + DefaultDialTimeout = 1 * time.Minute +) // EthereumClient wraps the client and the BlockChain network to interact with an EVM based Blockchain type EthereumClient struct { @@ -65,14 +71,13 @@ func newEVMClient(networkSettings EVMNetwork, logger zerolog.Logger) (EVMClient, Bool("Supports EIP-1559", networkSettings.SupportsEIP1559). Bool("Finality Tag", networkSettings.FinalityTag). Msg("Connecting client") - cl, err := ethclient.Dial(networkSettings.URL) - if err != nil { - return nil, err - } - raw, err := rpc.Dial(networkSettings.URL) + ctx, cancel := context.WithTimeout(context.Background(), DefaultDialTimeout) + defer cancel() + raw, err := rpc.DialOptions(ctx, networkSettings.URL) if err != nil { return nil, err } + cl := ethclient.NewClient(raw) ec := &EthereumClient{ NetworkConfig: networkSettings, diff --git a/client/explorer.go b/client/explorer.go index 8db60737a..0ebc9a932 100644 --- a/client/explorer.go +++ b/client/explorer.go @@ -15,11 +15,11 @@ type ExplorerClient struct { } // NewExplorerClient creates a new explorer mock client -func NewExplorerClient(cfg *ExplorerConfig) *ExplorerClient { +func NewExplorerClient(cfg *ExplorerConfig) (*ExplorerClient, error) { return &ExplorerClient{ Config: cfg, APIClient: resty.New().SetBaseURL(cfg.URL), - } + }, nil } // PostAdminNodes is used to exercise the POST /api/v1/admin/nodes endpoint diff --git a/client/kafka_rest.go b/client/kafka_rest.go index e698fef42..9ec4e1eb4 100644 --- a/client/kafka_rest.go +++ b/client/kafka_rest.go @@ -19,11 +19,11 @@ type KafkaRestConfig struct { } // NewKafkaRestClient creates a new KafkaRestClient -func NewKafkaRestClient(cfg *KafkaRestConfig) *KafkaRestClient { +func NewKafkaRestClient(cfg *KafkaRestConfig) (*KafkaRestClient, error) { return &KafkaRestClient{ Config: cfg, APIClient: resty.New().SetBaseURL(cfg.URL), - } + }, nil } // GetTopics Get a list of Kafka topics. diff --git a/client/mockserver.go b/client/mockserver.go index 61e49aa3b..0c2a74d47 100644 --- a/client/mockserver.go +++ b/client/mockserver.go @@ -1,8 +1,10 @@ package client import ( + "crypto/tls" "fmt" "net/http" + "os" "strings" "github.com/go-resty/resty/v2" @@ -22,32 +24,39 @@ type MockserverClient struct { type MockserverConfig struct { LocalURL string ClusterURL string + Headers map[string]string } // ConnectMockServer creates a connection to a deployed mockserver in the environment -func ConnectMockServer(e *environment.Environment) (*MockserverClient, error) { +func ConnectMockServer(e *environment.Environment) *MockserverClient { c := NewMockserverClient(&MockserverConfig{ LocalURL: e.URLs[mockserver.LocalURLsKey][0], ClusterURL: e.URLs[mockserver.InternalURLsKey][0], }) - return c, nil + return c } // ConnectMockServerURL creates a connection to a mockserver at a given url, should only be used for inside K8s tests -func ConnectMockServerURL(url string) (*MockserverClient, error) { +func ConnectMockServerURL(url string) *MockserverClient { c := NewMockserverClient(&MockserverConfig{ LocalURL: url, ClusterURL: url, }) - return c, nil + return c } // NewMockserverClient returns a mockserver client func NewMockserverClient(cfg *MockserverConfig) *MockserverClient { log.Debug().Str("Local URL", cfg.LocalURL).Str("Remote URL", cfg.ClusterURL).Msg("Connected to MockServer") + isDebug := os.Getenv("RESTY_DEBUG") == "true" return &MockserverClient{ - Config: cfg, - APIClient: resty.New().SetBaseURL(cfg.LocalURL), + Config: cfg, + APIClient: resty.New(). + SetBaseURL(cfg.LocalURL). + SetHeaders(cfg.Headers). + SetDebug(isDebug). + //nolint + SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}), } } @@ -114,7 +123,7 @@ func (em *MockserverClient) SetValuePath(path string, v int) error { initializers := []HttpInitializer{initializer} resp, err := em.APIClient.R().SetBody(&initializers).Put("/expectation") if resp.StatusCode() != http.StatusCreated { - err = fmt.Errorf("status code expected %d got %d", http.StatusCreated, resp.StatusCode()) + err = fmt.Errorf("status code expected %d got %d, err: %s", http.StatusCreated, resp.StatusCode(), err) } return err } diff --git a/crib/README.md b/crib/README.md new file mode 100644 index 000000000..34f9a5f7c --- /dev/null +++ b/crib/README.md @@ -0,0 +1,25 @@ +### CRIB Connector + +This is a simple CRIB connector for OCRv1 CRIB +This code is temporary and may be removed in the future if connection logic will be simplified with [ARC](https://github.com/actions/actions-runner-controller) + +## Example + +Go to the [CRIB](https://github.com/smartcontractkit/crib) repository and spin up a cluster. + +```shell +./scripts/cribbit.sh crib-oh-my-crib +devspace deploy --debug --profile local-dev-simulated-core-ocr1 +``` + +## Run an example test + +```shell +export CRIB_NAMESPACE=crib-oh-my-crib +export CRIB_NETWORK=geth # only "geth" is supported for now +export CRIB_NODES=5 # min 5 nodes +#export SETH_LOG_LEVEL=debug # these two can be enabled to debug connection issues +#export RESTY_DEBUG=true +export GAP_URL=https://localhost:8080/primary # only applicable in CI, unset the var to connect locally +go test -v -run TestCRIB +``` diff --git a/crib/config.go b/crib/config.go new file mode 100644 index 000000000..af3485ed5 --- /dev/null +++ b/crib/config.go @@ -0,0 +1,137 @@ +package crib + +import ( + "fmt" + "net/http" + "os" + "strconv" + + "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink-testing-framework/logging" +) + +const ( + /* + These are constants for simulated CRIB that should never change + Ideally, they should be placed into CRIB repository, however, for simplicity we keep all environment connectors in CTF + CRIB: https://github.com/smartcontractkit/crib/tree/main/core + Core Chart: https://github.com/smartcontractkit/infra-charts/tree/main/chainlink-cluster + */ + MockserverCRIBTemplate = "https://%s-mockserver%s" + InternalNodeDNSTemplate = "app-node%d" + IngressNetworkWSURLTemplate = "wss://%s-geth-%d-ws%s" + IngressNetworkHTTPURLTemplate = "https://%s-geth-%d-http%s" + // DefaultSimulatedPrivateKey is a first key used for Geth/Hardhat/Anvil + DefaultSimulatedPrivateKey = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + // DefaultSimulatedNetworkChainID is a default chainID we use for Geth/Hardhat/Anvil + DefaultSimulatedNetworkChainID = 1337 + HostHeader = "X-Original-Host" +) + +// ConnectionVars common K8s connection vars +type ConnectionVars struct { + IngressSuffix string + Namespace string + Network string + Nodes int +} + +// CoreDONConnectionConfig Chainlink DON connection config +type CoreDONConnectionConfig struct { + *ConnectionVars + PrivateKeys []string + NodeURLs []string + NodeInternalDNS []string + NodeHeaders []map[string]string + BlockchainNodeHeaders http.Header + MockserverHeaders map[string]string + ChainID int64 + NetworkWSURL string + NetworkHTTPURL string + MockserverURL string +} + +// CoreDONSimulatedConnection returns all vars required to connect to core DON Simulated CRIB +// connects in CI via GAP if GAP_URL is provided +func CoreDONSimulatedConnection() (*CoreDONConnectionConfig, error) { + vars, err := ReadCRIBVars() + if err != nil { + return nil, err + } + var conn *CoreDONConnectionConfig + clNodeURLs := make([]string, 0) + clNodesInternalDNS := make([]string, 0) + clNodesHeaders := make([]map[string]string, 0) + for i := 1; i <= vars.Nodes; i++ { + clNodesInternalDNS = append(clNodesInternalDNS, fmt.Sprintf(InternalNodeDNSTemplate, i)) + clNodesHeaders = append(clNodesHeaders, map[string]string{ + HostHeader: fmt.Sprintf("%s-node%d%s", vars.Namespace, i, vars.IngressSuffix), + }) + } + conn = &CoreDONConnectionConfig{ + ConnectionVars: vars, + PrivateKeys: []string{DefaultSimulatedPrivateKey}, + NodeURLs: clNodeURLs, + NodeInternalDNS: clNodesInternalDNS, + NodeHeaders: clNodesHeaders, + BlockchainNodeHeaders: http.Header{ + HostHeader: []string{fmt.Sprintf("%s-geth-%d-http%s", vars.Namespace, DefaultSimulatedNetworkChainID, vars.IngressSuffix)}, + }, + MockserverHeaders: map[string]string{ + HostHeader: fmt.Sprintf("%s-mockserver%s", vars.Namespace, vars.IngressSuffix), + }, + ChainID: DefaultSimulatedNetworkChainID, + } + // GAP connection + gapURL := os.Getenv("GAP_URL") + if gapURL == "" { + logging.L.Info().Msg("Connecting to CRIB locally") + for i := 1; i <= vars.Nodes; i++ { + conn.NodeURLs = append(conn.NodeURLs, fmt.Sprintf("https://%s-node%d%s", vars.Namespace, i, vars.IngressSuffix)) + } + conn.NetworkWSURL = fmt.Sprintf(IngressNetworkWSURLTemplate, vars.Namespace, DefaultSimulatedNetworkChainID, vars.IngressSuffix) + conn.NetworkHTTPURL = fmt.Sprintf(IngressNetworkHTTPURLTemplate, vars.Namespace, DefaultSimulatedNetworkChainID, vars.IngressSuffix) + conn.MockserverURL = fmt.Sprintf(MockserverCRIBTemplate, vars.Namespace, vars.IngressSuffix) + } else { + logging.L.Info().Msg("Connecting to CRIB using GAP") + for i := 1; i <= vars.Nodes; i++ { + conn.NodeURLs = append(conn.NodeURLs, gapURL) + } + conn.NetworkWSURL = gapURL + conn.NetworkHTTPURL = gapURL + conn.MockserverURL = gapURL + } + logging.L.Debug().Any("ConnectionInfo", conn).Msg("CRIB connection info") + return conn, nil +} + +// ReadCRIBVars read CRIB environment variables +func ReadCRIBVars() (*ConnectionVars, error) { + ingressSuffix := os.Getenv("K8S_STAGING_INGRESS_SUFFIX") + if ingressSuffix == "" { + return nil, errors.New("K8S_STAGING_INGRESS_SUFFIX must be set to connect to k8s ingresses") + } + cribNamespace := os.Getenv("CRIB_NAMESPACE") + if cribNamespace == "" { + return nil, errors.New("CRIB_NAMESPACE must be set to connect") + } + cribNetwork := os.Getenv("CRIB_NETWORK") + if cribNetwork == "" { + return nil, errors.New("CRIB_NETWORK must be set to connect, only 'geth' is supported for now") + } + cribNodes := os.Getenv("CRIB_NODES") + nodes, err := strconv.Atoi(cribNodes) + if err != nil { + return nil, errors.New("CRIB_NODES must be a number, 5-19 nodes") + } + if nodes < 2 { + return nil, fmt.Errorf("not enough chainlink nodes, need at least 2") + } + return &ConnectionVars{ + IngressSuffix: ingressSuffix, + Namespace: cribNamespace, + Network: cribNetwork, + Nodes: nodes, + }, nil +} diff --git a/go.mod b/go.mod index a3783c808..645c1dbe1 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/prometheus/common v0.45.0 github.com/rs/zerolog v1.30.0 github.com/slack-go/slack v0.12.2 - github.com/smartcontractkit/seth v1.0.11 + github.com/smartcontractkit/seth v1.1.1 github.com/smartcontractkit/wasp v0.4.1 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 @@ -68,6 +68,7 @@ require ( github.com/allegro/bigcache v1.2.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect github.com/aws/aws-sdk-go v1.45.25 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect diff --git a/go.sum b/go.sum index 57a7dde24..bc225bbf1 100644 --- a/go.sum +++ b/go.sum @@ -131,6 +131,8 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= +github.com/awalterschulze/gographviz v2.0.3+incompatible h1:9sVEXJBJLwGX7EQVhLm2elIKCm7P2YHFC8v6096G09E= +github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4= github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= @@ -1017,8 +1019,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/seth v1.0.11 h1:Ct8wSifW2ZXnyHtYRKaawBnpW7Ef0m8zItUcqYPallM= -github.com/smartcontractkit/seth v1.0.11/go.mod h1:fVCE+8LD6AbU7d8BHZ1uS/ceJ+8JO0iVTUcDdQmGPAc= +github.com/smartcontractkit/seth v1.1.1 h1:6hvexjJD7ek8ht/CLlEwQcH21K2E/WEYwbSRdKInZmM= +github.com/smartcontractkit/seth v1.1.1/go.mod h1:cDfKHi/hJLpO9sRpVbrflrHCOV+MJPAMJHloExJnIXk= github.com/smartcontractkit/wasp v0.4.1 h1:qgIx2s+eCwH0OaBKaHEAHUQ1Z47bAgDu+ICS9IOqvGQ= github.com/smartcontractkit/wasp v0.4.1/go.mod h1:3qiofyI3pkbrc48a3CVshbMfgl74SiuPL/tm30d9Wb4= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= diff --git a/grafana/client.go b/grafana/client.go index 4e0effd3f..b5633284b 100644 --- a/grafana/client.go +++ b/grafana/client.go @@ -64,9 +64,11 @@ func (c *Client) GetDatasources() (map[string]string, *resty.Response, error) { } func NewGrafanaClient(url, apiKey string) *Client { - isDebug := os.Getenv("DEBUG_RESTY") == "true" - resty := resty.New().SetDebug(isDebug).SetBaseURL(url).SetHeader("Authorization", "Bearer "+apiKey) - + isDebug := os.Getenv("RESTY_DEBUG") == "true" + resty := resty.New(). + SetDebug(isDebug). + SetBaseURL(url). + SetHeader("Authorization", "Bearer "+apiKey) return &Client{ resty: resty, AlertManager: &AlertManagerClient{resty: resty}, From d1b3fde506ebde6d87ace24cb94f2dd13d2bc51f Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Mon, 5 Aug 2024 13:55:13 +0200 Subject: [PATCH 13/26] [TT-1425] Support pre-Deneb genesis (#1034) --- config/private_ethereum_network.go | 170 +++++++++++------- {docker/test_env => config/types}/messages.go | 2 +- config/types/types.go | 22 +++ docker/ethereum/ethereum.go | 165 +++++++++++++++++ docker/ethereum/images.go | 27 +++ docker/test_env/besu_base.go | 33 ++-- docker/test_env/besu_eth1.go | 7 +- docker/test_env/besu_eth2.go | 43 +++-- docker/test_env/besu_test.go | 46 ++++- .../cmd/internal/start_test_env_commands.go | 5 +- docker/test_env/env_component_test.go | 2 +- docker/test_env/erigon_base.go | 58 +++--- docker/test_env/erigon_eth1.go | 6 +- docker/test_env/erigon_eth2.go | 16 +- docker/test_env/erigon_test.go | 46 ++++- docker/test_env/eth2_common.go | 41 +++-- docker/test_env/eth2_init_helpers.go | 34 ++-- docker/test_env/eth_common.go | 10 +- docker/test_env/ethereum_env.go | 139 ++++++++------ docker/test_env/ethereum_env_test.go | 82 +++++---- docker/test_env/ethereum_env_versions_test.go | 13 +- docker/test_env/genesis_generator.go | 59 ++++-- docker/test_env/genesis_generator_helpers.go | 9 +- docker/test_env/geth_base.go | 63 ++++--- docker/test_env/geth_eth1.go | 7 +- docker/test_env/geth_eth2.go | 21 ++- docker/test_env/geth_test.go | 79 +++++++- docker/test_env/github_utils.go | 3 +- docker/test_env/nethermind_base.go | 29 ++- docker/test_env/nethermind_eth1.go | 9 +- docker/test_env/nethermind_eth2.go | 21 ++- docker/test_env/nethermind_test.go | 48 ++++- docker/test_env/prysm.go | 56 +++--- docker/test_env/reth_base.go | 28 ++- docker/test_env/reth_eth2.go | 17 +- docker/test_env/reth_test.go | 10 +- docker/test_env/utils.go | 113 ------------ go.mod | 4 +- go.sum | 4 +- utils/docker/docker.go | 25 +++ 40 files changed, 1040 insertions(+), 532 deletions(-) rename {docker/test_env => config/types}/messages.go (92%) create mode 100644 config/types/types.go create mode 100644 docker/ethereum/ethereum.go create mode 100644 docker/ethereum/images.go create mode 100644 utils/docker/docker.go diff --git a/config/private_ethereum_network.go b/config/private_ethereum_network.go index da6163b0d..b82d4a65e 100644 --- a/config/private_ethereum_network.go +++ b/config/private_ethereum_network.go @@ -11,6 +11,8 @@ import ( "github.com/rs/zerolog" tc "github.com/testcontainers/testcontainers-go" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/utils/slice" ) @@ -23,18 +25,18 @@ var ( ) type EthereumNetworkConfig struct { - ConsensusType *EthereumVersion `toml:"consensus_type"` - EthereumVersion *EthereumVersion `toml:"ethereum_version"` - ConsensusLayer *ConsensusLayer `toml:"consensus_layer"` - ExecutionLayer *ExecutionLayer `toml:"execution_layer"` - DockerNetworkNames []string `toml:"docker_network_names"` - Containers EthereumNetworkContainers `toml:"containers"` - WaitForFinalization *bool `toml:"wait_for_finalization"` - GeneratedDataHostDir *string `toml:"generated_data_host_dir"` - ValKeysDir *string `toml:"val_keys_dir"` - EthereumChainConfig *EthereumChainConfig `toml:"EthereumChainConfig"` - CustomDockerImages map[ContainerType]string `toml:"CustomDockerImages"` - NodeLogLevel *string `toml:"node_log_level,omitempty"` + ConsensusType *config_types.EthereumVersion `toml:"consensus_type"` + EthereumVersion *config_types.EthereumVersion `toml:"ethereum_version"` + ConsensusLayer *ConsensusLayer `toml:"consensus_layer"` + ExecutionLayer *config_types.ExecutionLayer `toml:"execution_layer"` + DockerNetworkNames []string `toml:"docker_network_names"` + Containers EthereumNetworkContainers `toml:"containers"` + WaitForFinalization *bool `toml:"wait_for_finalization"` + GeneratedDataHostDir *string `toml:"generated_data_host_dir"` + ValKeysDir *string `toml:"val_keys_dir"` + EthereumChainConfig *EthereumChainConfig `toml:"EthereumChainConfig"` + CustomDockerImages map[ContainerType]string `toml:"CustomDockerImages"` + NodeLogLevel *string `toml:"node_log_level,omitempty"` } func (en *EthereumNetworkConfig) Validate() error { @@ -49,10 +51,12 @@ func (en *EthereumNetworkConfig) Validate() error { l.Debug().Msg("Using _deprecated_ ConsensusType as EthereumVersion") tempEthVersion := en.ConsensusType switch *tempEthVersion { - case EthereumVersion_Eth1, EthereumVersion_Eth1_Legacy: - *tempEthVersion = EthereumVersion_Eth1 - case EthereumVersion_Eth2, EthereumVersion_Eth2_Legacy: - *tempEthVersion = EthereumVersion_Eth2 + //nolint:staticcheck //ignore SA1019 + case config_types.EthereumVersion_Eth1, config_types.EthereumVersion_Eth1_Legacy: + *tempEthVersion = config_types.EthereumVersion_Eth1 + //nolint:staticcheck //ignore SA1019 + case config_types.EthereumVersion_Eth2, config_types.EthereumVersion_Eth2_Legacy: + *tempEthVersion = config_types.EthereumVersion_Eth2 default: return fmt.Errorf("unknown ethereum version (consensus type): %s", *en.ConsensusType) } @@ -68,12 +72,14 @@ func (en *EthereumNetworkConfig) Validate() error { return ErrMissingExecutionLayer } - if (en.EthereumVersion != nil && (*en.EthereumVersion == EthereumVersion_Eth2_Legacy || *en.EthereumVersion == EthereumVersion_Eth2)) && (en.ConsensusLayer == nil || *en.ConsensusLayer == "") { + //nolint:staticcheck //ignore SA1019 + if (en.EthereumVersion != nil && (*en.EthereumVersion == config_types.EthereumVersion_Eth2_Legacy || *en.EthereumVersion == config_types.EthereumVersion_Eth2)) && (en.ConsensusLayer == nil || *en.ConsensusLayer == "") { l.Warn().Msg("Consensus layer is not set, but is required for PoS. Defaulting to Prysm") en.ConsensusLayer = &ConsensusLayer_Prysm } - if (en.EthereumVersion != nil && (*en.EthereumVersion == EthereumVersion_Eth1_Legacy || *en.EthereumVersion == EthereumVersion_Eth1)) && (en.ConsensusLayer != nil && *en.ConsensusLayer != "") { + //nolint:staticcheck //ignore SA1019 + if (en.EthereumVersion != nil && (*en.EthereumVersion == config_types.EthereumVersion_Eth1_Legacy || *en.EthereumVersion == config_types.EthereumVersion_Eth1)) && (en.ConsensusLayer != nil && *en.ConsensusLayer != "") { l.Warn().Msg("Consensus layer is set, but is not allowed for PoW. Ignoring") en.ConsensusLayer = nil } @@ -82,7 +88,7 @@ func (en *EthereumNetworkConfig) Validate() error { en.NodeLogLevel = &DefaultNodeLogLevel } - if *en.EthereumVersion == EthereumVersion_Eth1 && *en.ExecutionLayer == ExecutionLayer_Reth { + if *en.EthereumVersion == config_types.EthereumVersion_Eth1 && *en.ExecutionLayer == config_types.ExecutionLayer_Reth { msg := `%s If you are using builder to create the network, please change the EthereumVersion to EthereumVersion_Eth2 by calling this method: @@ -105,7 +111,7 @@ ethereum_version="eth2" return errors.New("ethereum chain config is required") } - return en.EthereumChainConfig.Validate(l, en.EthereumVersion) + return en.EthereumChainConfig.Validate(l, en.EthereumVersion, en.ExecutionLayer, en.CustomDockerImages) } func (en *EthereumNetworkConfig) ApplyOverrides(from *EthereumNetworkConfig) error { @@ -163,27 +169,6 @@ const ( ConsensusType_PoW ConsensusType = "pow" ) -type EthereumVersion string - -const ( - EthereumVersion_Eth2 EthereumVersion = "eth2" - // Deprecated: use EthereumVersion_Eth2 instead - EthereumVersion_Eth2_Legacy EthereumVersion = "pos" - EthereumVersion_Eth1 EthereumVersion = "eth1" - // Deprecated: use EthereumVersion_Eth1 instead - EthereumVersion_Eth1_Legacy EthereumVersion = "pow" -) - -type ExecutionLayer string - -const ( - ExecutionLayer_Geth ExecutionLayer = "geth" - ExecutionLayer_Nethermind ExecutionLayer = "nethermind" - ExecutionLayer_Erigon ExecutionLayer = "erigon" - ExecutionLayer_Besu ExecutionLayer = "besu" - ExecutionLayer_Reth ExecutionLayer = "reth" -) - type ConsensusLayer string var ConsensusLayer_Prysm ConsensusLayer = "prysm" @@ -200,10 +185,6 @@ const ( ContainerType_ValKeysGenerator ContainerType = "val_keys_generator" ) -const ( - UnsopportedForkErr = "only 'Electra' and 'EOF' hard forks are supported" -) - type EthereumChainConfig struct { SecondsPerSlot int `json:"seconds_per_slot" toml:"seconds_per_slot"` SlotsPerEpoch int `json:"slots_per_epoch" toml:"slots_per_epoch"` @@ -218,6 +199,7 @@ type EthereumChainConfig struct { //go:embed tomls/default_ethereum_env.toml var defaultEthereumChainConfig []byte +// Default sets the EthereumChainConfig to the default values func (c *EthereumChainConfig) Default() error { wrapper := struct { EthereumNetwork *EthereumNetworkConfig `toml:"PrivateEthereumNetwork"` @@ -239,7 +221,8 @@ func (c *EthereumChainConfig) Default() error { return nil } -func GetDefaultChainConfig() EthereumChainConfig { +// MustGetDefaultChainConfig returns the default EthereumChainConfig or panics if it can't be loaded +func MustGetDefaultChainConfig() EthereumChainConfig { config := EthereumChainConfig{} if err := config.Default(); err != nil { panic(err) @@ -247,14 +230,16 @@ func GetDefaultChainConfig() EthereumChainConfig { return config } -func (c *EthereumChainConfig) Validate(logger zerolog.Logger, ethereumVersion *EthereumVersion) error { +// Validate validates the EthereumChainConfig +func (c *EthereumChainConfig) Validate(l zerolog.Logger, ethereumVersion *config_types.EthereumVersion, executionLayer *config_types.ExecutionLayer, customDockerImages map[ContainerType]string) error { if c.ChainID < 1 { return fmt.Errorf("chain id must be >= 0") } // don't like it 100% but in cases where we load private ethereum network config from TOML it might be incomplete // until we pass it to ethereum network builder that will fill in defaults - if ethereumVersion == nil || (*ethereumVersion == EthereumVersion_Eth1_Legacy || *ethereumVersion == EthereumVersion_Eth1) { + //nolint:staticcheck //ignore SA1019 + if ethereumVersion == nil || (*ethereumVersion == config_types.EthereumVersion_Eth1_Legacy || *ethereumVersion == config_types.EthereumVersion_Eth1) { return nil } @@ -274,7 +259,7 @@ func (c *EthereumChainConfig) Validate(logger zerolog.Logger, ethereumVersion *E return fmt.Errorf("genesis timestamp must be generated by calling GenerateGenesisTimestamp()") } - if err := c.ValidateHardForks(); err != nil { + if err := c.ValidateHardForks(l, ethereumVersion, executionLayer, customDockerImages); err != nil { return err } @@ -286,23 +271,84 @@ func (c *EthereumChainConfig) Validate(logger zerolog.Logger, ethereumVersion *E return err } if hadDuplicates { - logger.Warn().Msg("Duplicate addresses found in addresses_to_fund. Removed them. You might want to review your configuration.") + l.Warn().Msg("Duplicate addresses found in addresses_to_fund. Removed them. You might want to review your configuration.") } return nil } -func (c *EthereumChainConfig) ValidateHardForks() error { - if len(c.HardForkEpochs) == 0 { +// ValidateHardForks validates hard forks based either on custom or default docker images for eth2 execution layer +func (c *EthereumChainConfig) ValidateHardForks(l zerolog.Logger, ethereumVersion *config_types.EthereumVersion, executionLayer *config_types.ExecutionLayer, customDockerImages map[ContainerType]string) error { + //nolint:staticcheck //ignore SA1019 + if ethereumVersion == nil || (*ethereumVersion == config_types.EthereumVersion_Eth1_Legacy || *ethereumVersion == config_types.EthereumVersion_Eth1) { return nil } - // currently Prysm Beacon Chain doesn't support any fork (Electra is coming in 2025) - c.HardForkEpochs = map[string]int{} + customImage := customDockerImages[ContainerType_ExecutionLayer] + var baseEthereumFork ethereum.Fork + var err error + if customImage == "" { + if executionLayer == nil { + return ErrMissingExecutionLayer + } + var dockerImage string + switch *executionLayer { + case config_types.ExecutionLayer_Geth: + dockerImage = ethereum.DefaultGethEth2Image + case config_types.ExecutionLayer_Nethermind: + dockerImage = ethereum.DefaultNethermindEth2Image + case config_types.ExecutionLayer_Erigon: + dockerImage = ethereum.DefaultErigonEth2Image + case config_types.ExecutionLayer_Besu: + dockerImage = ethereum.DefaultBesuEth2Image + case config_types.ExecutionLayer_Reth: + dockerImage = ethereum.DefaultRethEth2Image + } + baseEthereumFork, err = ethereum.LastSupportedForkForEthereumClient(dockerImage) + } else { + baseEthereumFork, err = ethereum.LastSupportedForkForEthereumClient(customImage) + } + + if err != nil { + return err + } + + validFutureForks, err := baseEthereumFork.ValidFutureForks() + if err != nil { + return err + } + + validForks := make(map[string]int) + + // latest Prysm Beacon Chain doesn't support any fork (Electra is coming in 2025) + // but older versions do support Deneb + for fork, epoch := range c.HardForkEpochs { + isValid := false + for _, validFork := range validFutureForks { + if strings.EqualFold(fork, string(validFork)) { + isValid = true + validForks[fork] = epoch + break + } + } + + if !isValid { + l.Debug().Msgf("Fork %s is not supported. Removed it from configuration", fork) + } + } + + // at the same time for Shanghai-based forks we need to add Deneb to the list if it's not there, so that genesis is valid + if _, ok := c.HardForkEpochs[string(ethereum.EthereumFork_Deneb)]; !ok && baseEthereumFork == ethereum.EthereumFork_Shanghai { + l.Debug().Msg("Adding Deneb to fork setup, because it's required, but was missing from the configuration. It's scheduled for epoch 1000") + validForks[string(ethereum.EthereumFork_Deneb)] = 1000 + } + + c.HardForkEpochs = validForks return nil } +// ApplyOverrides applies overrides from another EthereumChainConfig func (c *EthereumChainConfig) ApplyOverrides(from *EthereumChainConfig) error { if from == nil { return nil @@ -328,8 +374,9 @@ func (c *EthereumChainConfig) ApplyOverrides(from *EthereumChainConfig) error { return nil } +// FillInMissingValuesWithDefault fills in missing/zero values with default values func (c *EthereumChainConfig) FillInMissingValuesWithDefault() { - defaultConfig := GetDefaultChainConfig() + defaultConfig := MustGetDefaultChainConfig() if c.ValidatorCount == 0 { c.ValidatorCount = defaultConfig.ValidatorCount } @@ -356,18 +403,21 @@ func (c *EthereumChainConfig) FillInMissingValuesWithDefault() { } } -func (c *EthereumChainConfig) GetValidatorBasedGenesisDelay() int { +// ValidatorBasedGenesisDelay returns the delay in seconds based on the number of validators +func (c *EthereumChainConfig) ValidatorBasedGenesisDelay() int { return c.ValidatorCount * 5 } func (c *EthereumChainConfig) GenerateGenesisTimestamp() { - c.GenesisTimestamp = int(time.Now().Unix()) + c.GetValidatorBasedGenesisDelay() + c.GenesisTimestamp = int(time.Now().Unix()) + c.ValidatorBasedGenesisDelay() } -func (c *EthereumChainConfig) GetDefaultWaitDuration() time.Duration { - return time.Duration((c.GenesisDelay+c.GetValidatorBasedGenesisDelay())*2) * time.Second +// DefaultWaitDuration returns the default wait duration for the network based on the genesis delay and the number of validators +func (c *EthereumChainConfig) DefaultWaitDuration() time.Duration { + return time.Duration((c.GenesisDelay+c.ValidatorBasedGenesisDelay())*2) * time.Second } -func (c *EthereumChainConfig) GetDefaultFinalizationWaitDuration() time.Duration { +// DefaultFinalizationWaitDuration returns the default wait duration for finalization +func (c *EthereumChainConfig) DefaultFinalizationWaitDuration() time.Duration { return 5 * time.Minute } diff --git a/docker/test_env/messages.go b/config/types/messages.go similarity index 92% rename from docker/test_env/messages.go rename to config/types/messages.go index afb88a74a..ae593d304 100644 --- a/docker/test_env/messages.go +++ b/config/types/messages.go @@ -1,4 +1,4 @@ -package test_env +package types const ( MsgInvalidDockerImageFormat = "invalid docker image format: %s" diff --git a/config/types/types.go b/config/types/types.go new file mode 100644 index 000000000..bdfab9657 --- /dev/null +++ b/config/types/types.go @@ -0,0 +1,22 @@ +package types + +type ExecutionLayer string + +const ( + ExecutionLayer_Geth ExecutionLayer = "geth" + ExecutionLayer_Nethermind ExecutionLayer = "nethermind" + ExecutionLayer_Erigon ExecutionLayer = "erigon" + ExecutionLayer_Besu ExecutionLayer = "besu" + ExecutionLayer_Reth ExecutionLayer = "reth" +) + +type EthereumVersion string + +const ( + EthereumVersion_Eth2 EthereumVersion = "eth2" + // Deprecated: use EthereumVersion_Eth2 instead + EthereumVersion_Eth2_Legacy EthereumVersion = "pos" + EthereumVersion_Eth1 EthereumVersion = "eth1" + // Deprecated: use EthereumVersion_Eth1 instead + EthereumVersion_Eth1_Legacy EthereumVersion = "pow" +) diff --git a/docker/ethereum/ethereum.go b/docker/ethereum/ethereum.go new file mode 100644 index 000000000..a3f6be5f6 --- /dev/null +++ b/docker/ethereum/ethereum.go @@ -0,0 +1,165 @@ +package ethereum + +import ( + "errors" + "fmt" + "strings" + + "github.com/Masterminds/semver/v3" + + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + docker_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/docker" +) + +type Fork string + +const ( + EthereumFork_Shanghai Fork = "Shanghai" + EthereumFork_Deneb Fork = "Deneb" +) + +// ValidFutureForks returns the list of valid future forks for the given Ethereum fork +func (e Fork) ValidFutureForks() ([]Fork, error) { + switch e { + case EthereumFork_Shanghai: + return []Fork{EthereumFork_Deneb}, nil + case EthereumFork_Deneb: + return []Fork{}, nil + default: + return []Fork{}, fmt.Errorf("unknown fork: %s", e) + } +} + +// LastSupportedForkForEthereumClient returns the last supported fork for the given Ethereum client. It supports only eth2 clients. +func LastSupportedForkForEthereumClient(imageWithVersion string) (Fork, error) { + ethereumVersion, err := VersionFromImage(imageWithVersion) + if err != nil { + return "", err + } + + //nolint:staticcheck //ignore SA1019 + if ethereumVersion == config_types.EthereumVersion_Eth1 || ethereumVersion == config_types.EthereumVersion_Eth1_Legacy { + return "", fmt.Errorf("ethereum version '%s' is not supported", ethereumVersion) + } + + executionLayer, err := ExecutionLayerFromDockerImage(imageWithVersion) + if err != nil { + return "", err + } + + version, err := docker_utils.GetSemverFromImage(imageWithVersion) + if err != nil { + return "", err + } + + var constraint *semver.Constraints + + switch executionLayer { + case config_types.ExecutionLayer_Besu: + constraint, err = semver.NewConstraint("<24.1") + case config_types.ExecutionLayer_Geth: + constraint, err = semver.NewConstraint("<1.13.12") + case config_types.ExecutionLayer_Erigon: + constraint, err = semver.NewConstraint("= 246 { + kgzConstraint, err := semver.NewConstraint(">=23.1 <24.0") + if err != nil { + return nil, fmt.Errorf("failed to parse constraint: %s", ">=23.1 && <23.7") + } + + if kgzConstraint.Check(version) { + cmd = append(cmd, "--kzg-trusted-setup", fmt.Sprintf("%s/trusted_setup.txt", g.generatedDataContainerDir)) + } + + bonsaiConstraint, err := semver.NewConstraint(">=24.6") + if err != nil { + return nil, fmt.Errorf("failed to parse constraint: %s", ">=24.6") + } + + if bonsaiConstraint.Check(version) { // it crashes with sync-mode=FULL, and when we use a different sync mode then consensus client fails to propose correct blocks cmd = append(cmd, "--bonsai-limit-trie-logs-enabled=false") } @@ -102,7 +121,7 @@ func (g *Besu) getEth2ContainerRequest() (*tc.ContainerRequest, error) { hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{ Type: mount.TypeBind, Source: g.generatedDataHostDir, - Target: GENERATED_DATA_DIR_INSIDE_CONTAINER, + Target: g.generatedDataContainerDir, ReadOnly: false, }) }, diff --git a/docker/test_env/besu_test.go b/docker/test_env/besu_test.go index 1d4fcf1c8..e2c145fa5 100644 --- a/docker/test_env/besu_test.go +++ b/docker/test_env/besu_test.go @@ -9,6 +9,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/config" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" ) @@ -19,8 +21,8 @@ func TestBesuEth1(t *testing.T) { builder := NewEthereumNetworkBuilder() cfg, err := builder. //nolint:staticcheck //ignore SA1019 - WithEthereumVersion(config.EthereumVersion_Eth1_Legacy). - WithExecutionLayer(config.ExecutionLayer_Besu). + WithEthereumVersion(config_types.EthereumVersion_Eth1_Legacy). + WithExecutionLayer(config_types.ExecutionLayer_Besu). Build() require.NoError(t, err, "Builder validation failed") @@ -38,15 +40,14 @@ func TestBesuEth1(t *testing.T) { require.NoError(t, err, "Couldn't close the client") } -func TestBesuEth2(t *testing.T) { +func TestBesuEth2_Deneb(t *testing.T) { l := logging.GetTestLogger(t) builder := NewEthereumNetworkBuilder() cfg, err := builder. - //nolint:staticcheck //ignore SA1019 - WithEthereumVersion(config.EthereumVersion_Eth2_Legacy). + WithCustomDockerImages(map[config.ContainerType]string{config.ContainerType_ExecutionLayer: "hyperledger/besu:24.1.0"}). WithConsensusLayer(config.ConsensusLayer_Prysm). - WithExecutionLayer(config.ExecutionLayer_Besu). + WithExecutionLayer(config_types.ExecutionLayer_Besu). Build() require.NoError(t, err, "Builder validation failed") @@ -76,5 +77,38 @@ func TestBesuEth2(t *testing.T) { _, err = blockchain.ConnectEVMClient(eip1559Network, l) require.Error(t, err, "Could not connect to Besu") require.Contains(t, err.Error(), "Method not found", "Besu should not work EIP-1559 yet") +} + +func TestBesuEth2_Shanghai(t *testing.T) { + l := logging.GetTestLogger(t) + + chainConfig := config.MustGetDefaultChainConfig() + chainConfig.HardForkEpochs = map[string]int{"Deneb": 500} + builder := NewEthereumNetworkBuilder() + cfg, err := builder. + WithCustomDockerImages(map[config.ContainerType]string{config.ContainerType_ExecutionLayer: "hyperledger/besu:23.10"}). + WithExecutionLayer(config_types.ExecutionLayer_Besu). + WithEthereumChainConfig(chainConfig). + Build() + require.NoError(t, err, "Builder validation failed") + + _, eth2, err := cfg.Start() + require.NoError(t, err, "Couldn't start PoS network") + + nonEip1559Network := blockchain.SimulatedEVMNetwork + nonEip1559Network.Name = "Simulated Besu + Prysm (non-EIP 1559)" + nonEip1559Network.GasEstimationBuffer = 10_000_000_000 + nonEip1559Network.URLs = eth2.PublicWsUrls() + clientOne, err := blockchain.ConnectEVMClient(nonEip1559Network, l) + require.NoError(t, err, "Couldn't connect to the evm client") + + t.Cleanup(func() { + err = clientOne.Close() + require.NoError(t, err, "Couldn't close the client") + }) + + address := common.HexToAddress("0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1") + err = sendAndCompareBalances(testcontext.Get(t), clientOne, address) + require.NoError(t, err, fmt.Sprintf("balance wasn't correctly updated for %s network", nonEip1559Network.Name)) } diff --git a/docker/test_env/cmd/internal/start_test_env_commands.go b/docker/test_env/cmd/internal/start_test_env_commands.go index 9d8d59b7d..affe2bed7 100644 --- a/docker/test_env/cmd/internal/start_test_env_commands.go +++ b/docker/test_env/cmd/internal/start_test_env_commands.go @@ -15,6 +15,7 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/smartcontractkit/chainlink-testing-framework/config" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logging" ) @@ -167,9 +168,9 @@ func startPrivateEthChainE(cmd *cobra.Command, args []string) error { } builder := test_env.NewEthereumNetworkBuilder() - builder = *builder.WithEthereumVersion(config.EthereumVersion(ethereumVersion)). + builder = *builder.WithEthereumVersion(config_types.EthereumVersion(ethereumVersion)). WithConsensusLayer(consensusLayerToUse). - WithExecutionLayer(config.ExecutionLayer(executionLayer)). + WithExecutionLayer(config_types.ExecutionLayer(executionLayer)). WithEthereumChainConfig(config.EthereumChainConfig{ ValidatorCount: 8, SlotsPerEpoch: 2, diff --git a/docker/test_env/env_component_test.go b/docker/test_env/env_component_test.go index d09f5f3a2..241bbd4dc 100644 --- a/docker/test_env/env_component_test.go +++ b/docker/test_env/env_component_test.go @@ -39,7 +39,7 @@ func TestEthEnvComponentPauseChaos(t *testing.T) { network, err := docker.CreateNetwork(l) require.NoError(t, err) - defaultChainCfg := config.GetDefaultChainConfig() + defaultChainCfg := config.MustGetDefaultChainConfig() g := NewGethEth1([]string{network.Name}, &defaultChainCfg). WithTestInstance(t) _, err = g.StartContainer() diff --git a/docker/test_env/erigon_base.go b/docker/test_env/erigon_base.go index 176263eba..c55f0da40 100644 --- a/docker/test_env/erigon_base.go +++ b/docker/test_env/erigon_base.go @@ -6,25 +6,20 @@ import ( "testing" "time" + "github.com/Masterminds/semver/v3" "github.com/rs/zerolog" - tc "github.com/testcontainers/testcontainers-go" tcwait "github.com/testcontainers/testcontainers-go/wait" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/config" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" "github.com/smartcontractkit/chainlink-testing-framework/docker" "github.com/smartcontractkit/chainlink-testing-framework/logging" + docker_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/docker" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" ) -const ( - defaultErigonEth1Image = "thorax/erigon:v2.40.0" - defaultErigonEth2Image = "thorax/erigon:v2.59.3" // v.2.60.0 is the latest, but gas estimations using zero address are broken - erigonBaseImageName = "thorax/erigon" - erigonGitRepo = "ledgerwatch/erigon" -) - type Erigon struct { EnvComponent ExternalHttpUrl string @@ -33,12 +28,12 @@ type Erigon struct { InternalWsUrl string InternalExecutionURL string ExternalExecutionURL string - generatedDataHostDir string chainConfig *config.EthereumChainConfig consensusLayer config.ConsensusLayer - ethereumVersion config.EthereumVersion + ethereumVersion config_types.EthereumVersion l zerolog.Logger t *testing.T + posContainerSettings } func (g *Erigon) WithTestInstance(t *testing.T) ExecutionClient { @@ -50,7 +45,7 @@ func (g *Erigon) WithTestInstance(t *testing.T) ExecutionClient { func (g *Erigon) StartContainer() (blockchain.EVMNetwork, error) { var r *tc.ContainerRequest var err error - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { r, err = g.getEth1ContainerRequest() } else { r, err = g.getEth2ContainerRequest() @@ -79,7 +74,7 @@ func (g *Erigon) StartContainer() (blockchain.EVMNetwork, error) { return blockchain.EVMNetwork{}, err } - if g.GetEthereumVersion() == config.EthereumVersion_Eth2 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth2 { executionPort, err := ct.MappedPort(testcontext.Get(g.t), NatPort(ETH2_EXECUTION_PORT)) if err != nil { return blockchain.EVMNetwork{}, err @@ -95,7 +90,7 @@ func (g *Erigon) StartContainer() (blockchain.EVMNetwork, error) { g.InternalWsUrl = FormatWsUrl(g.ContainerName, DEFAULT_EVM_NODE_HTTP_PORT) networkConfig := blockchain.SimulatedEVMNetwork - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { networkConfig.Name = fmt.Sprintf("Private Eth-1-PoW [erigon %s]", g.ContainerVersion) } else { networkConfig.Name = fmt.Sprintf("Private Eth-2-PoS [erigon %s] + %s", g.ContainerVersion, g.consensusLayer) @@ -111,14 +106,14 @@ func (g *Erigon) StartContainer() (blockchain.EVMNetwork, error) { } func (g *Erigon) GetInternalExecutionURL() string { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { panic("eth1 node doesn't have an execution URL") } return g.InternalExecutionURL } func (g *Erigon) GetExternalExecutionURL() string { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { panic("eth1 node doesn't have an execution URL") } return g.ExternalExecutionURL @@ -148,12 +143,12 @@ func (g *Erigon) GetContainer() *tc.Container { return &g.Container } -func (g *Erigon) GetEthereumVersion() config.EthereumVersion { +func (g *Erigon) GetEthereumVersion() config_types.EthereumVersion { return g.ethereumVersion } func (g *Erigon) WaitUntilChainIsReady(ctx context.Context, waitTime time.Duration) error { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { return nil } waitForFirstBlock := tcwait.NewLogStrategy("Built block").WithPollInterval(1 * time.Second).WithStartupTimeout(waitTime) @@ -161,28 +156,47 @@ func (g *Erigon) WaitUntilChainIsReady(ctx context.Context, waitTime time.Durati } func (g *Erigon) GethConsensusMechanism() ConsensusMechanism { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { return ConsensusMechanism_PoW } return ConsensusMechanism_PoS } func (g *Erigon) getExtraExecutionFlags() (string, error) { - version, err := GetComparableVersionFromDockerImage(g.GetImageWithVersion()) + version, err := docker_utils.GetSemverFromImage(g.GetImageWithVersion()) if err != nil { return "", err } extraExecutionFlags := "" - if version > 247 { + + // Erigon v2.47.0 and above have a new flag for disabling tx fee cap + txFeeCapConstraint, err := semver.NewConstraint(">= 2.47.0") + if err != nil { + return "", err + } + + if txFeeCapConstraint.Check(version) { extraExecutionFlags = " --rpc.txfeecap=0" } - if version > 254 { + // Erigon v2.54.0 and above have a new flag for allowing unprotected txs + allowUnprotectedTxsConstraint, err := semver.NewConstraint(">= 2.54.0") + if err != nil { + return "", err + } + + if allowUnprotectedTxsConstraint.Check(version) { extraExecutionFlags += " --rpc.allow-unprotected-txs" } - if version > 242 { + // Erigon v2.42.0 and above have a new flag for setting the db size limit + dbSizeLimitConstraint, err := semver.NewConstraint(">= 2.42.0") + if err != nil { + return "", err + } + + if dbSizeLimitConstraint.Check(version) { extraExecutionFlags += " --db.size.limit=8GB" } diff --git a/docker/test_env/erigon_eth1.go b/docker/test_env/erigon_eth1.go index 35cede17b..7ef8b40ee 100644 --- a/docker/test_env/erigon_eth1.go +++ b/docker/test_env/erigon_eth1.go @@ -15,6 +15,8 @@ import ( tcwait "github.com/testcontainers/testcontainers-go/wait" "github.com/smartcontractkit/chainlink-testing-framework/config" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/mirror" "github.com/smartcontractkit/chainlink-testing-framework/utils/templates" @@ -22,7 +24,7 @@ import ( // NewErigonEth1 starts a new Erigon Eth1 node running in Docker func NewErigonEth1(networks []string, chainConfig *config.EthereumChainConfig, opts ...EnvComponentOption) (*Erigon, error) { - parts := strings.Split(defaultErigonEth1Image, ":") + parts := strings.Split(ethereum.DefaultErigonEth1Image, ":") g := &Erigon{ EnvComponent: EnvComponent{ ContainerName: fmt.Sprintf("%s-%s", "erigon-eth1", uuid.NewString()[0:8]), @@ -33,7 +35,7 @@ func NewErigonEth1(networks []string, chainConfig *config.EthereumChainConfig, o }, chainConfig: chainConfig, l: logging.GetTestLogger(nil), - ethereumVersion: config.EthereumVersion_Eth1, + ethereumVersion: config_types.EthereumVersion_Eth1, } g.SetDefaultHooks() for _, opt := range opts { diff --git a/docker/test_env/erigon_eth2.go b/docker/test_env/erigon_eth2.go index 1ff5bd1fa..c71d2f5ad 100644 --- a/docker/test_env/erigon_eth2.go +++ b/docker/test_env/erigon_eth2.go @@ -15,13 +15,15 @@ import ( tcwait "github.com/testcontainers/testcontainers-go/wait" "github.com/smartcontractkit/chainlink-testing-framework/config" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/mirror" ) // NewErigonEth2 starts a new Erigon Eth2 node running in Docker -func NewErigonEth2(networks []string, chainConfig *config.EthereumChainConfig, generatedDataHostDir string, consensusLayer config.ConsensusLayer, opts ...EnvComponentOption) (*Erigon, error) { - parts := strings.Split(defaultErigonEth2Image, ":") +func NewErigonEth2(networks []string, chainConfig *config.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir string, consensusLayer config.ConsensusLayer, opts ...EnvComponentOption) (*Erigon, error) { + parts := strings.Split(ethereum.DefaultErigonEth2Image, ":") g := &Erigon{ EnvComponent: EnvComponent{ ContainerName: fmt.Sprintf("%s-%s", "erigon-eth2", uuid.NewString()[0:8]), @@ -31,10 +33,10 @@ func NewErigonEth2(networks []string, chainConfig *config.EthereumChainConfig, g StartupTimeout: 2 * time.Minute, }, chainConfig: chainConfig, - generatedDataHostDir: generatedDataHostDir, + posContainerSettings: posContainerSettings{generatedDataHostDir: generatedDataHostDir, generatedDataContainerDir: generatedDataContainerDir}, consensusLayer: consensusLayer, l: logging.GetTestLogger(nil), - ethereumVersion: config.EthereumVersion_Eth2, + ethereumVersion: config_types.EthereumVersion_Eth2, } g.SetDefaultHooks() for _, opt := range opts { @@ -92,7 +94,7 @@ func (g *Erigon) getEth2ContainerRequest() (*tc.ContainerRequest, error) { hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{ Type: mount.TypeBind, Source: g.generatedDataHostDir, - Target: GENERATED_DATA_DIR_INSIDE_CONTAINER, + Target: g.generatedDataContainerDir, ReadOnly: false, }) }, @@ -145,8 +147,8 @@ func (g *Erigon) buildPosInitScript() (string, error) { }{ HttpPort: DEFAULT_EVM_NODE_HTTP_PORT, ChainID: g.chainConfig.ChainID, - GeneratedDataDir: GENERATED_DATA_DIR_INSIDE_CONTAINER, - JwtFileLocation: JWT_SECRET_FILE_LOCATION_INSIDE_CONTAINER, + GeneratedDataDir: g.generatedDataContainerDir, + JwtFileLocation: getJWTSecretFileLocationInsideContainer(g.generatedDataContainerDir), ExecutionDir: "/home/erigon/execution-data", ExtraExecutionFlags: extraExecutionFlags, SendersToTrace: strings.Join(g.chainConfig.AddressesToFund, ","), diff --git a/docker/test_env/erigon_test.go b/docker/test_env/erigon_test.go index afe2ee41f..8c43b4167 100644 --- a/docker/test_env/erigon_test.go +++ b/docker/test_env/erigon_test.go @@ -4,6 +4,8 @@ import ( "fmt" "testing" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" @@ -19,8 +21,8 @@ func TestErigonEth1(t *testing.T) { builder := NewEthereumNetworkBuilder() cfg, err := builder. //nolint:staticcheck //ignore SA1019 - WithEthereumVersion(config.EthereumVersion_Eth1_Legacy). - WithExecutionLayer(config.ExecutionLayer_Erigon). + WithEthereumVersion(config_types.EthereumVersion_Eth1_Legacy). + WithExecutionLayer(config_types.ExecutionLayer_Erigon). Build() require.NoError(t, err, "Builder validation failed") @@ -38,15 +40,15 @@ func TestErigonEth1(t *testing.T) { require.NoError(t, err, "Couldn't close the client") } -func TestErigonEth2(t *testing.T) { +func TestErigonEth2_Deneb(t *testing.T) { l := logging.GetTestLogger(t) builder := NewEthereumNetworkBuilder() cfg, err := builder. //nolint:staticcheck //ignore SA1019 - WithEthereumVersion(config.EthereumVersion_Eth2_Legacy). + WithCustomDockerImages(map[config.ContainerType]string{config.ContainerType_ExecutionLayer: "thorax/erigon:v2.59.0"}). WithConsensusLayer(config.ConsensusLayer_Prysm). - WithExecutionLayer(config.ExecutionLayer_Erigon). + WithExecutionLayer(config_types.ExecutionLayer_Erigon). Build() require.NoError(t, err, "Builder validation failed") @@ -84,3 +86,37 @@ func TestErigonEth2(t *testing.T) { err = sendAndCompareBalances(ctx, clientTwo, address) require.NoError(t, err, fmt.Sprintf("balance wasn't correctly updated for %s network", eip1559Network.Name)) } + +func TestErigonEth2_Shanghai(t *testing.T) { + l := logging.GetTestLogger(t) + + chainConfig := config.MustGetDefaultChainConfig() + chainConfig.HardForkEpochs = map[string]int{"Deneb": 500} + + builder := NewEthereumNetworkBuilder() + cfg, err := builder. + WithCustomDockerImages(map[config.ContainerType]string{config.ContainerType_ExecutionLayer: "thorax/erigon:v2.58.0"}). + WithExecutionLayer(config_types.ExecutionLayer_Erigon). + WithEthereumChainConfig(chainConfig). + Build() + require.NoError(t, err, "Builder validation failed") + + _, eth2, err := cfg.Start() + require.NoError(t, err, "Couldn't start PoS network") + + nonEip1559Network := blockchain.SimulatedEVMNetwork + nonEip1559Network.Name = "Simulated Erigon + Prysm (non-EIP 1559)" + nonEip1559Network.URLs = eth2.PublicWsUrls() + clientOne, err := blockchain.ConnectEVMClient(nonEip1559Network, l) + require.NoError(t, err, "Couldn't connect to the evm client") + + t.Cleanup(func() { + err = clientOne.Close() + require.NoError(t, err, "Couldn't close the client") + }) + + ctx := testcontext.Get(t) + address := common.HexToAddress("0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1") + err = sendAndCompareBalances(ctx, clientOne, address) + require.NoError(t, err, fmt.Sprintf("balance wasn't correctly updated for %s network", nonEip1559Network.Name)) +} diff --git a/docker/test_env/eth2_common.go b/docker/test_env/eth2_common.go index 140f86712..71f7a3d95 100644 --- a/docker/test_env/eth2_common.go +++ b/docker/test_env/eth2_common.go @@ -13,19 +13,38 @@ import ( ) var ( - ETH2_EXECUTION_PORT = "8551" - WALLET_PASSWORD = "password" - VALIDATOR_WALLET_PASSWORD_FILE_INSIDE_CONTAINER = fmt.Sprintf("%s/wallet_password.txt", GENERATED_DATA_DIR_INSIDE_CONTAINER) - ACCOUNT_PASSWORD_FILE_INSIDE_CONTAINER = fmt.Sprintf("%s/account_password.txt", GENERATED_DATA_DIR_INSIDE_CONTAINER) - ACCOUNT_KEYSTORE_FILE_INSIDE_CONTAINER = fmt.Sprintf("%s/account_key", KEYSTORE_DIR_LOCATION_INSIDE_CONTAINER) - KEYSTORE_DIR_LOCATION_INSIDE_CONTAINER = fmt.Sprintf("%s/keystore", GENERATED_DATA_DIR_INSIDE_CONTAINER) - GENERATED_VALIDATOR_KEYS_DIR_INSIDE_CONTAINER = "/keys" - NODE_0_DIR_INSIDE_CONTAINER = fmt.Sprintf("%s/node-0", GENERATED_VALIDATOR_KEYS_DIR_INSIDE_CONTAINER) - GENERATED_DATA_DIR_INSIDE_CONTAINER = "/data/metadata" - JWT_SECRET_FILE_LOCATION_INSIDE_CONTAINER = fmt.Sprintf("%s/jwtsecret", GENERATED_DATA_DIR_INSIDE_CONTAINER) // #nosec G101 - VALIDATOR_BIP39_MNEMONIC = "giant issue aisle success illegal bike spike question tent bar rely arctic volcano long crawl hungry vocal artwork sniff fantasy very lucky have athlete" + ETH2_EXECUTION_PORT = "8551" + WALLET_PASSWORD = "password" + GENERATED_VALIDATOR_KEYS_DIR_INSIDE_CONTAINER = "/keys" + NODE_0_DIR_INSIDE_CONTAINER = fmt.Sprintf("%s/node-0", GENERATED_VALIDATOR_KEYS_DIR_INSIDE_CONTAINER) + VALIDATOR_BIP39_MNEMONIC = "giant issue aisle success illegal bike spike question tent bar rely arctic volcano long crawl hungry vocal artwork sniff fantasy very lucky have athlete" ) +type posContainerSettings struct { + generatedDataHostDir string + generatedDataContainerDir string +} + +func getValidatorWalletPasswordFileInsideContainer(generatedDataContainerDir string) string { + return fmt.Sprintf("%s/wallet_password.txt", generatedDataContainerDir) +} + +func getAccountPasswordFileInsideContainer(generatedDataContainerDir string) string { + return fmt.Sprintf("%s/account_password.txt", generatedDataContainerDir) +} + +func getAccountKeystoreFileInsideContainer(generatedDataContainerDir string) string { + return fmt.Sprintf("%s/account_key", getKeystoreDirLocationInsideContainer(generatedDataContainerDir)) +} + +func getKeystoreDirLocationInsideContainer(generatedDataContainerDir string) string { + return fmt.Sprintf("%s/keystore", generatedDataContainerDir) +} + +func getJWTSecretFileLocationInsideContainer(generatedDataContainerDir string) string { + return fmt.Sprintf("%s/jwtsecret", generatedDataContainerDir) +} + func waitForChainToFinaliseAnEpoch(lggr zerolog.Logger, evmClient blockchain.EVMClient, timeout time.Duration) error { lggr.Info().Msg("Waiting for chain to finalize an epoch") diff --git a/docker/test_env/eth2_init_helpers.go b/docker/test_env/eth2_init_helpers.go index 9ec9f0f62..87d889b0c 100644 --- a/docker/test_env/eth2_init_helpers.go +++ b/docker/test_env/eth2_init_helpers.go @@ -22,23 +22,23 @@ import ( type AfterGenesisHelper struct { EnvComponent - chainConfig config.EthereumChainConfig - l zerolog.Logger - customConfigDataDir string - addressesToFund []string - t *testing.T + chainConfig config.EthereumChainConfig + addressesToFund []string + l zerolog.Logger + t *testing.T + posContainerSettings } -func NewInitHelper(chainConfig config.EthereumChainConfig, customConfigDataDir string, opts ...EnvComponentOption) *AfterGenesisHelper { +func NewInitHelper(chainConfig config.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir string, opts ...EnvComponentOption) *AfterGenesisHelper { g := &AfterGenesisHelper{ EnvComponent: EnvComponent{ ContainerName: fmt.Sprintf("%s-%s", "after-genesis-helper", uuid.NewString()[0:8]), StartupTimeout: 20 * time.Second, }, - chainConfig: chainConfig, - customConfigDataDir: customConfigDataDir, - l: log.Logger, - addressesToFund: []string{}, + chainConfig: chainConfig, + posContainerSettings: posContainerSettings{generatedDataHostDir: generatedDataHostDir, generatedDataContainerDir: generatedDataContainerDir}, + l: log.Logger, + addressesToFund: []string{}, } g.SetDefaultHooks() for _, opt := range opts { @@ -110,8 +110,8 @@ func (g *AfterGenesisHelper) getContainerRequest(networks []string) (*tc.Contain HostConfigModifier: func(hostConfig *container.HostConfig) { hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{ Type: mount.TypeBind, - Source: g.customConfigDataDir, - Target: GENERATED_DATA_DIR_INSIDE_CONTAINER, + Source: g.generatedDataHostDir, + Target: g.generatedDataContainerDir, ReadOnly: false, }) }, @@ -157,11 +157,11 @@ echo "------------------------------------------------------------------" GenesisTimestamp int }{ WalletPassword: WALLET_PASSWORD, - WalletPasswordFileLocation: VALIDATOR_WALLET_PASSWORD_FILE_INSIDE_CONTAINER, - AccountPasswordFileLocation: ACCOUNT_PASSWORD_FILE_INSIDE_CONTAINER, - JwtFileLocation: JWT_SECRET_FILE_LOCATION_INSIDE_CONTAINER, - AccountKeystoreFileLocation: ACCOUNT_KEYSTORE_FILE_INSIDE_CONTAINER, - KeystoreDirLocation: KEYSTORE_DIR_LOCATION_INSIDE_CONTAINER, + WalletPasswordFileLocation: getValidatorWalletPasswordFileInsideContainer(g.generatedDataContainerDir), + AccountPasswordFileLocation: getAccountPasswordFileInsideContainer(g.generatedDataContainerDir), + JwtFileLocation: getJWTSecretFileLocationInsideContainer(g.generatedDataContainerDir), + AccountKeystoreFileLocation: getAccountKeystoreFileInsideContainer(g.generatedDataContainerDir), + KeystoreDirLocation: getKeystoreDirLocationInsideContainer(g.generatedDataContainerDir), GenesisTimestamp: g.chainConfig.GenesisTimestamp, } diff --git a/docker/test_env/eth_common.go b/docker/test_env/eth_common.go index c71b098a5..e09e9d9c5 100644 --- a/docker/test_env/eth_common.go +++ b/docker/test_env/eth_common.go @@ -7,10 +7,12 @@ import ( "testing" "time" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + tc "github.com/testcontainers/testcontainers-go" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/config" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" ) const ( @@ -39,7 +41,7 @@ type ExecutionClient interface { GetInternalWsUrl() string GetExternalHttpUrl() string GetExternalWsUrl() string - GetEthereumVersion() config.EthereumVersion + GetEthereumVersion() config_types.EthereumVersion GethConsensusMechanism() ConsensusMechanism WaitUntilChainIsReady(ctx context.Context, waitTime time.Duration) error WithTestInstance(t *testing.T) ExecutionClient @@ -51,10 +53,10 @@ type UnsupportedVersion struct { } var UNSUPPORTED_VERSIONS = []UnsupportedVersion{ - {DockerImage: fmt.Sprintf("%s:1.20.0", nethermindBaseImageName), + {DockerImage: fmt.Sprintf("%s:1.20.0", ethereum.NethermindBaseImageName), Reason: "1.20.0 was replaced with 1.20.1, for more info check https://github.com/NethermindEth/nethermind/releases/tag/1.20.0", }, - {DockerImage: fmt.Sprintf("%s:v1.9.0", gethBaseImageName), + {DockerImage: fmt.Sprintf("%s:v1.9.0", ethereum.GethBaseImageName), Reason: "v1.9.0 randomly drops websocket connections, for more info check https://github.com/ethereum/go-ethereum/issues/19001", }, } diff --git a/docker/test_env/ethereum_env.go b/docker/test_env/ethereum_env.go index 13e775455..45acc3096 100644 --- a/docker/test_env/ethereum_env.go +++ b/docker/test_env/ethereum_env.go @@ -13,7 +13,9 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/config" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" "github.com/smartcontractkit/chainlink-testing-framework/docker" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/logstream" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" @@ -35,9 +37,9 @@ type EthereumNetworkBuilder struct { t *testing.T ls *logstream.LogStream dockerNetworks []string - ethereumVersion config.EthereumVersion + ethereumVersion config_types.EthereumVersion consensusLayer *config.ConsensusLayer - executionLayer config.ExecutionLayer + executionLayer config_types.ExecutionLayer ethereumChainConfig *config.EthereumChainConfig existingConfig *config.EthereumNetworkConfig customDockerImages map[config.ContainerType]string @@ -61,16 +63,16 @@ func NewEthereumNetworkBuilder() EthereumNetworkBuilder { func (b *EthereumNetworkBuilder) WithConsensusType(consensusType config.ConsensusType) *EthereumNetworkBuilder { switch consensusType { case config.ConsensusType_PoS: - b.ethereumVersion = config.EthereumVersion_Eth2 + b.ethereumVersion = config_types.EthereumVersion_Eth2 case config.ConsensusType_PoW: - b.ethereumVersion = config.EthereumVersion_Eth1 + b.ethereumVersion = config_types.EthereumVersion_Eth1 default: panic(fmt.Sprintf("unknown consensus type: %s", consensusType)) } return b } -func (b *EthereumNetworkBuilder) WithEthereumVersion(ethereumVersion config.EthereumVersion) *EthereumNetworkBuilder { +func (b *EthereumNetworkBuilder) WithEthereumVersion(ethereumVersion config_types.EthereumVersion) *EthereumNetworkBuilder { b.ethereumVersion = ethereumVersion return b } @@ -80,7 +82,7 @@ func (b *EthereumNetworkBuilder) WithConsensusLayer(consensusLayer config.Consen return b } -func (b *EthereumNetworkBuilder) WithExecutionLayer(executionLayer config.ExecutionLayer) *EthereumNetworkBuilder { +func (b *EthereumNetworkBuilder) WithExecutionLayer(executionLayer config_types.ExecutionLayer) *EthereumNetworkBuilder { b.executionLayer = executionLayer return b } @@ -176,7 +178,7 @@ func (b *EthereumNetworkBuilder) Build() (EthereumNetwork, error) { if !b.importExistingConfig() { if b.ethereumChainConfig == nil { - defaultConfig := config.GetDefaultChainConfig() + defaultConfig := config.MustGetDefaultChainConfig() b.ethereumChainConfig = &defaultConfig } else { b.ethereumChainConfig.FillInMissingValuesWithDefault() @@ -246,7 +248,7 @@ func (b *EthereumNetworkBuilder) validate() error { } //nolint:staticcheck //ignore SA1019 - if (b.ethereumVersion == config.EthereumVersion_Eth2 || b.ethereumVersion == config.EthereumVersion_Eth2_Legacy) && b.consensusLayer == nil { + if (b.ethereumVersion == config_types.EthereumVersion_Eth2 || b.ethereumVersion == config_types.EthereumVersion_Eth2_Legacy) && b.consensusLayer == nil { return ErrMissingConsensusLayer } @@ -265,7 +267,7 @@ func (b *EthereumNetworkBuilder) validate() error { return errors.New("ethereum chain config is required") } - return b.ethereumChainConfig.Validate(logging.GetTestLogger(nil), &b.ethereumVersion) + return b.ethereumChainConfig.Validate(logging.GetTestLogger(nil), &b.ethereumVersion, &b.executionLayer, b.customDockerImages) } func (b *EthereumNetworkBuilder) validateCustomDockerImages() error { @@ -281,7 +283,7 @@ func (b *EthereumNetworkBuilder) validateCustomDockerImages() error { return fmt.Errorf("docker image %s is not supported, due to: %s", image, reason) } - executionLayer, err := GetExecutionLayerFromDockerImage(image) + executionLayer, err := ethereum.ExecutionLayerFromDockerImage(image) if err != nil { return err } @@ -313,18 +315,18 @@ func (b *EthereumNetworkBuilder) autoFill() error { } //nolint:staticcheck //ignore SA1019 - if (b.ethereumVersion == config.EthereumVersion_Eth2_Legacy || b.ethereumVersion == config.EthereumVersion_Eth2) && b.consensusLayer == nil { + if (b.ethereumVersion == config_types.EthereumVersion_Eth2_Legacy || b.ethereumVersion == config_types.EthereumVersion_Eth2) && b.consensusLayer == nil { b.consensusLayer = &config.ConsensusLayer_Prysm } //nolint:staticcheck //ignore SA1019 - if b.ethereumVersion == config.EthereumVersion_Eth1_Legacy { - b.ethereumVersion = config.EthereumVersion_Eth1 + if b.ethereumVersion == config_types.EthereumVersion_Eth1_Legacy { + b.ethereumVersion = config_types.EthereumVersion_Eth1 } //nolint:staticcheck //ignore SA1019 - if b.ethereumVersion == config.EthereumVersion_Eth2_Legacy { - b.ethereumVersion = config.EthereumVersion_Eth2 + if b.ethereumVersion == config_types.EthereumVersion_Eth2_Legacy { + b.ethereumVersion = config_types.EthereumVersion_Eth2 } if b.nodeLogLevel == "" { @@ -338,7 +340,7 @@ func (b *EthereumNetworkBuilder) setExecutionLayerBasedOnCustomDocker() error { if b.executionLayer == "" && len(b.customDockerImages) > 0 { if image, ok := b.customDockerImages[config.ContainerType_ExecutionLayer]; ok { var err error - b.executionLayer, err = GetExecutionLayerFromDockerImage(image) + b.executionLayer, err = ethereum.ExecutionLayerFromDockerImage(image) if err != nil { return err } @@ -382,7 +384,7 @@ func (b *EthereumNetworkBuilder) trySettingEthereumVersionBasedOnCustomImage() e return errors.New("couldn't determine ethereum version as no custom docker image for execution layer was provided") } - ethereumVersion, err := GetEthereumVersionFromImage(b.executionLayer, dockerImageToUse) + ethereumVersion, err := ethereum.VersionFromImage(dockerImageToUse) if err != nil { return err } @@ -402,10 +404,10 @@ type EthereumNetwork struct { func (en *EthereumNetwork) Start() (blockchain.EVMNetwork, RpcProvider, error) { switch *en.EthereumVersion { //nolint:staticcheck //ignore SA1019 - case config.EthereumVersion_Eth1, config.EthereumVersion_Eth1_Legacy: + case config_types.EthereumVersion_Eth1, config_types.EthereumVersion_Eth1_Legacy: return en.startEth1() //nolint:staticcheck //ignore SA1019 - case config.EthereumVersion_Eth2_Legacy, config.EthereumVersion_Eth2: + case config_types.EthereumVersion_Eth2_Legacy, config_types.EthereumVersion_Eth2: return en.startEth2() default: return blockchain.EVMNetwork{}, RpcProvider{}, fmt.Errorf("unknown ethereum version: %s", *en.EthereumVersion) @@ -425,32 +427,56 @@ func (en *EthereumNetwork) startEth2() (blockchain.EVMNetwork, RpcProvider, erro if err != nil { return blockchain.EVMNetwork{}, RpcProvider{}, errors.Wrapf(err, "failed to create docker networks") } - generatedDataHostDir, valKeysDir, err := en.generateGenesisAndFoldersIfNeeded() + + executionLayerImage := en.getImageOverride(config.ContainerType_ExecutionLayer) + if executionLayerImage == "" { + switch *en.ExecutionLayer { + case config_types.ExecutionLayer_Besu: + executionLayerImage = ethereum.DefaultBesuEth2Image + case config_types.ExecutionLayer_Geth: + executionLayerImage = ethereum.DefaultGethEth2Image + case config_types.ExecutionLayer_Nethermind: + executionLayerImage = ethereum.DefaultNethermindEth2Image + case config_types.ExecutionLayer_Erigon: + executionLayerImage = ethereum.DefaultErigonEth2Image + case config_types.ExecutionLayer_Reth: + executionLayerImage = ethereum.DefaultRethEth2Image + default: + return blockchain.EVMNetwork{}, RpcProvider{}, fmt.Errorf(config_types.MsgUnsupportedExecutionLayer, *en.ExecutionLayer) + } + } + + baseEthereumFork, err := ethereum.LastSupportedForkForEthereumClient(executionLayerImage) + if err != nil { + return blockchain.EVMNetwork{}, RpcProvider{}, errors.Wrapf(err, "failed to get last supported fork for Ethereum client") + } + + generatedDataHostDir, generatedDataContainerDir, valKeysDir, err := en.generateGenesisAndFoldersIfNeeded(baseEthereumFork) if err != nil { return blockchain.EVMNetwork{}, RpcProvider{}, errors.Wrapf(err, "failed to prepare genesis") } opts := en.getExecutionLayerEnvComponentOpts() - chainReadyWaitTime := en.EthereumChainConfig.GetDefaultWaitDuration() + chainReadyWaitTime := en.EthereumChainConfig.DefaultWaitDuration() var client ExecutionClient var clientErr error switch *en.ExecutionLayer { - case config.ExecutionLayer_Geth: - client, clientErr = NewGethEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, config.ConsensusLayer_Prysm, opts...) - case config.ExecutionLayer_Nethermind: - client, clientErr = NewNethermindEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, config.ConsensusLayer_Prysm, opts...) + case config_types.ExecutionLayer_Geth: + client, clientErr = NewGethEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir, config.ConsensusLayer_Prysm, opts...) + case config_types.ExecutionLayer_Nethermind: + client, clientErr = NewNethermindEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir, config.ConsensusLayer_Prysm, opts...) chainReadyWaitTime = chainReadyWaitTime * 2 - case config.ExecutionLayer_Erigon: - client, clientErr = NewErigonEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, config.ConsensusLayer_Prysm, opts...) + case config_types.ExecutionLayer_Erigon: + client, clientErr = NewErigonEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir, config.ConsensusLayer_Prysm, opts...) chainReadyWaitTime = chainReadyWaitTime * 2 - case config.ExecutionLayer_Besu: - client, clientErr = NewBesuEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, config.ConsensusLayer_Prysm, opts...) + case config_types.ExecutionLayer_Besu: + client, clientErr = NewBesuEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir, config.ConsensusLayer_Prysm, opts...) chainReadyWaitTime = chainReadyWaitTime * 2 - case config.ExecutionLayer_Reth: - client, clientErr = NewRethEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, config.ConsensusLayer_Prysm, opts...) + case config_types.ExecutionLayer_Reth: + client, clientErr = NewRethEth2(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir, config.ConsensusLayer_Prysm, opts...) default: - return blockchain.EVMNetwork{}, RpcProvider{}, fmt.Errorf(MsgUnsupportedExecutionLayer, *en.ExecutionLayer) + return blockchain.EVMNetwork{}, RpcProvider{}, fmt.Errorf(config_types.MsgUnsupportedExecutionLayer, *en.ExecutionLayer) } if clientErr != nil { @@ -464,7 +490,7 @@ func (en *EthereumNetwork) startEth2() (blockchain.EVMNetwork, RpcProvider, erro return blockchain.EVMNetwork{}, RpcProvider{}, errors.Wrapf(err, "failed to start %s execution client", *en.ExecutionLayer) } - beacon, err := NewPrysmBeaconChain(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, client.GetInternalExecutionURL(), append(en.getImageOverride(config.ContainerType_ValKeysGenerator), en.setExistingContainerName(config.ContainerType_ConsensusLayer))...) + beacon, err := NewPrysmBeaconChain(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir, client.GetInternalExecutionURL(), baseEthereumFork, append(en.getImageOverrideOpts(config.ContainerType_ValKeysGenerator), en.setExistingContainerName(config.ContainerType_ConsensusLayer))...) if err != nil { return blockchain.EVMNetwork{}, RpcProvider{}, errors.Wrapf(err, "failed to create beacon chain instance") } @@ -475,8 +501,8 @@ func (en *EthereumNetwork) startEth2() (blockchain.EVMNetwork, RpcProvider, erro return blockchain.EVMNetwork{}, RpcProvider{}, errors.Wrapf(err, "failed to start beacon chain") } - validator, err := NewPrysmValidator(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, valKeysDir, beacon. - InternalBeaconRpcProvider, append(en.getImageOverride(config.ContainerType_ValKeysGenerator), en.setExistingContainerName(config.ContainerType_ConsensusValidator))...) + validator, err := NewPrysmValidator(dockerNetworks, en.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir, valKeysDir, beacon. + InternalBeaconRpcProvider, baseEthereumFork, append(en.getImageOverrideOpts(config.ContainerType_ValKeysGenerator), en.setExistingContainerName(config.ContainerType_ConsensusValidator))...) if err != nil { return blockchain.EVMNetwork{}, RpcProvider{}, errors.Wrapf(err, "failed to create validator instance") } @@ -502,7 +528,7 @@ func (en *EthereumNetwork) startEth2() (blockchain.EVMNetwork, RpcProvider, erro return blockchain.EVMNetwork{}, RpcProvider{}, errors.Wrapf(err, "failed to create evm client") } - err = waitForChainToFinaliseAnEpoch(logger, evmClient, en.EthereumChainConfig.GetDefaultFinalizationWaitDuration()) + err = waitForChainToFinaliseAnEpoch(logger, evmClient, en.EthereumChainConfig.DefaultFinalizationWaitDuration()) if err != nil { return blockchain.EVMNetwork{}, RpcProvider{}, errors.Wrapf(err, "failed to wait for chain to finalize first epoch") } @@ -557,18 +583,18 @@ func (en *EthereumNetwork) startEth1() (blockchain.EVMNetwork, RpcProvider, erro var client ExecutionClient var clientErr error switch *en.ExecutionLayer { - case config.ExecutionLayer_Geth: + case config_types.ExecutionLayer_Geth: client = NewGethEth1(dockerNetworks, en.EthereumChainConfig, opts...) - case config.ExecutionLayer_Besu: + case config_types.ExecutionLayer_Besu: client, clientErr = NewBesuEth1(dockerNetworks, en.EthereumChainConfig, opts...) - case config.ExecutionLayer_Erigon: + case config_types.ExecutionLayer_Erigon: client, clientErr = NewErigonEth1(dockerNetworks, en.EthereumChainConfig, opts...) - case config.ExecutionLayer_Nethermind: + case config_types.ExecutionLayer_Nethermind: client, clientErr = NewNethermindEth1(dockerNetworks, en.EthereumChainConfig, opts...) - case config.ExecutionLayer_Reth: + case config_types.ExecutionLayer_Reth: clientErr = errors.New(config.Eth1NotSupportedByRethMsg) default: - return blockchain.EVMNetwork{}, RpcProvider{}, fmt.Errorf(MsgUnsupportedExecutionLayer, *en.ExecutionLayer) + return blockchain.EVMNetwork{}, RpcProvider{}, fmt.Errorf(config_types.MsgUnsupportedExecutionLayer, *en.ExecutionLayer) } if clientErr != nil { @@ -615,7 +641,7 @@ func (en *EthereumNetwork) getOrCreateDockerNetworks() ([]string, error) { return []string{network.Name}, nil } -func (en *EthereumNetwork) generateGenesisAndFoldersIfNeeded() (generatedDataHostDir string, valKeysDir string, err error) { +func (en *EthereumNetwork) generateGenesisAndFoldersIfNeeded(baseEthereumFork ethereum.Fork) (generatedDataHostDir, generatedDataContainerDir, valKeysDir string, err error) { // create host directories and run genesis containers only if we are NOT recreating existing containers if !en.isRecreated { generatedDataHostDir, valKeysDir, err = createHostDirectories() @@ -628,7 +654,7 @@ func (en *EthereumNetwork) generateGenesisAndFoldersIfNeeded() (generatedDataHos } var valKeysGenerator *ValKeysGenerator - valKeysGenerator, err = NewValKeysGeneretor(en.EthereumChainConfig, valKeysDir, en.getImageOverride(config.ContainerType_ValKeysGenerator)...) + valKeysGenerator, err = NewValKeysGeneretor(en.EthereumChainConfig, valKeysDir, en.getImageOverrideOpts(config.ContainerType_ValKeysGenerator)...) if err != nil { err = errors.Wrap(err, "failed to start val keys generator") return @@ -641,8 +667,8 @@ func (en *EthereumNetwork) generateGenesisAndFoldersIfNeeded() (generatedDataHos return } - var genesis *EthGenesisGeneretor - genesis, err = NewEthGenesisGenerator(*en.EthereumChainConfig, generatedDataHostDir, en.getImageOverride(config.ContainerType_GenesisGenerator)...) + var genesis *EthGenesisGenerator + genesis, err = NewEthGenesisGenerator(*en.EthereumChainConfig, generatedDataHostDir, baseEthereumFork, en.getImageOverrideOpts(config.ContainerType_GenesisGenerator)...) if err != nil { err = errors.Wrap(err, "failed to start genesis generator") return @@ -655,7 +681,9 @@ func (en *EthereumNetwork) generateGenesisAndFoldersIfNeeded() (generatedDataHos return } - initHelper := NewInitHelper(*en.EthereumChainConfig, generatedDataHostDir).WithTestInstance(en.t) + generatedDataContainerDir = genesis.GetGeneratedDataContainerDir() + + initHelper := NewInitHelper(*en.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir).WithTestInstance(en.t) err = initHelper.StartContainer() if err != nil { err = errors.Wrap(err, "failed to start init helper") @@ -685,7 +713,7 @@ func (en *EthereumNetwork) getFinalEvmNetworkConfig(net blockchain.EVMNetwork) b net.FinalityTag = true net.FinalityDepth = 0 - if *en.ExecutionLayer == config.ExecutionLayer_Besu { + if *en.ExecutionLayer == config_types.ExecutionLayer_Besu { // Besu doesn't support "eth_maxPriorityFeePerGas" https://github.com/hyperledger/besu/issues/5658 // And if gas is too low, then transaction doesn't get to prioritized pool and is not a candidate for inclusion in the next block net.GasEstimationBuffer = 10_000_000_000 @@ -715,14 +743,21 @@ func (en *EthereumNetwork) setExistingContainerName(ct config.ContainerType) Env return func(c *EnvComponent) {} } -func (en *EthereumNetwork) getImageOverride(ct config.ContainerType) []EnvComponentOption { - options := []EnvComponentOption{} - if image, ok := en.CustomDockerImages[ct]; ok { +func (en *EthereumNetwork) getImageOverrideOpts(ct config.ContainerType) []EnvComponentOption { + var options []EnvComponentOption + if image := en.getImageOverride(ct); image != "" { options = append(options, WithContainerImageWithVersion(image)) } return options } +func (en *EthereumNetwork) getImageOverride(ct config.ContainerType) string { + if image, ok := en.CustomDockerImages[ct]; ok { + return image + } + return "" +} + func (en *EthereumNetwork) Save() error { name := fmt.Sprintf("ethereum_network_%s", uuid.NewString()[0:8]) confPath, err := toml_utils.SaveStructAsToml(en, ".private_chains", name) @@ -738,7 +773,7 @@ func (en *EthereumNetwork) Save() error { func (en *EthereumNetwork) getExecutionLayerEnvComponentOpts() []EnvComponentOption { opts := []EnvComponentOption{} - opts = append(opts, en.getImageOverride(config.ContainerType_ExecutionLayer)...) + opts = append(opts, en.getImageOverrideOpts(config.ContainerType_ExecutionLayer)...) opts = append(opts, en.setExistingContainerName(config.ContainerType_ExecutionLayer)) opts = append(opts, WithLogStream(en.ls)) diff --git a/docker/test_env/ethereum_env_test.go b/docker/test_env/ethereum_env_test.go index 9d496f269..f3aebbce8 100644 --- a/docker/test_env/ethereum_env_test.go +++ b/docker/test_env/ethereum_env_test.go @@ -6,6 +6,8 @@ import ( "os" "testing" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/ethereum/go-ethereum/common" "github.com/pelletier/go-toml/v2" @@ -21,9 +23,9 @@ func TestEthEnvCustomConfig(t *testing.T) { builder := NewEthereumNetworkBuilder() cfg, err := builder. - WithEthereumVersion(config.EthereumVersion_Eth2). + WithEthereumVersion(config_types.EthereumVersion_Eth2). WithConsensusLayer(config.ConsensusLayer_Prysm). - WithExecutionLayer(config.ExecutionLayer_Geth). + WithExecutionLayer(config_types.ExecutionLayer_Geth). WithEthereumChainConfig(config.EthereumChainConfig{ SecondsPerSlot: 6, SlotsPerEpoch: 2, @@ -48,9 +50,9 @@ func TestEthEnvExtraFunding(t *testing.T) { builder := NewEthereumNetworkBuilder() cfg, err := builder. //nolint:staticcheck //ignore SA1019 - WithEthereumVersion(config.EthereumVersion_Eth2_Legacy). + WithEthereumVersion(config_types.EthereumVersion_Eth2_Legacy). WithConsensusLayer(config.ConsensusLayer_Prysm). - WithExecutionLayer(config.ExecutionLayer_Geth). + WithExecutionLayer(config_types.ExecutionLayer_Geth). WithEthereumChainConfig(config.EthereumChainConfig{ AddressesToFund: []string{addressToFund}, }). @@ -76,9 +78,9 @@ func TestEthEnvWithPrysmAndGethReuseConfig(t *testing.T) { builder := NewEthereumNetworkBuilder() cfg, err := builder. - WithEthereumVersion(config.EthereumVersion_Eth2). + WithEthereumVersion(config_types.EthereumVersion_Eth2). WithConsensusLayer(config.ConsensusLayer_Prysm). - WithExecutionLayer(config.ExecutionLayer_Geth). + WithExecutionLayer(config_types.ExecutionLayer_Geth). Build() require.NoError(t, err, "Builder validation failed") @@ -151,10 +153,10 @@ func TestEthEnvExecClientFromToml(t *testing.T) { WithExistingConfig(tomlCfg). Build() require.NoError(t, err, "Builder validation failed") - require.Equal(t, config.ExecutionLayer_Besu, *cfg.ExecutionLayer, "Execution layer should be Besu") + require.Equal(t, config_types.ExecutionLayer_Besu, *cfg.ExecutionLayer, "Execution layer should be Besu") require.NotNil(t, cfg.ConsensusLayer, "Consensus layer should not be nil") require.Equal(t, config.ConsensusLayer_Prysm, *cfg.ConsensusLayer, "Consensus layer should be Prysm") - require.Equal(t, config.EthereumVersion_Eth2, *cfg.EthereumVersion, "Ethereum Version should be Eth2") + require.Equal(t, config_types.EthereumVersion_Eth2, *cfg.EthereumVersion, "Ethereum Version should be Eth2") require.NotNil(t, cfg.WaitForFinalization, "Wait for finalization should not be nil") require.False(t, *cfg.WaitForFinalization, "Wait for finalization should be false") require.Equal(t, 2, len(cfg.EthereumChainConfig.AddressesToFund), "Should have 2 addresses to fund") @@ -192,14 +194,9 @@ func TestEthEnvCustomDockerImagesFromToml(t *testing.T) { tomlCfg.EthereumChainConfig.GenerateGenesisTimestamp() err = tomlCfg.Validate() - require.NoError(t, err, "Couldn't validate TOML config") - - builder := NewEthereumNetworkBuilder() - _, err = builder. - WithExistingConfig(tomlCfg). - Build() - require.Error(t, err, "Builder validation failed") - require.Contains(t, fmt.Sprintf(MsgUnsupportedDockerImage, "i-dont-exist"), err.Error(), "Error message is not correct") + require.NotNil(t, err, "Should have failed to validate TOML config") + require.Error(t, err, "Couldn't validate TOML config") + require.Equal(t, fmt.Sprintf("failed to parse docker image and extract version: %s", "i-dont-exist:tag-me"), err.Error(), "Error message is not correct") } func TestEthNoLogLevelDefaultsToInfo(t *testing.T) { @@ -307,23 +304,36 @@ func TestEthEnvCustomDockerNetworks(t *testing.T) { builder := NewEthereumNetworkBuilder() cfg, err := builder. - WithEthereumVersion(config.EthereumVersion_Eth2). + WithEthereumVersion(config_types.EthereumVersion_Eth2). WithConsensusLayer(config.ConsensusLayer_Prysm). - WithExecutionLayer(config.ExecutionLayer_Geth). + WithExecutionLayer(config_types.ExecutionLayer_Geth). WithDockerNetworks(networks). Build() require.NoError(t, err, "Builder validation failed") require.Equal(t, networks, cfg.DockerNetworkNames, "Incorrect docker networks in config") } +func TestEthEnvValidHardForks(t *testing.T) { + t.Parallel() + chainConfig := config.MustGetDefaultChainConfig() + chainConfig.HardForkEpochs = map[string]int{"Deneb": 500} + + builder := NewEthereumNetworkBuilder() + _, err := builder. + WithCustomDockerImages(map[config.ContainerType]string{config.ContainerType_ExecutionLayer: "ethereum/client-go:v1.13.11"}). + WithExecutionLayer(config_types.ExecutionLayer_Geth). + WithEthereumChainConfig(chainConfig). + Build() + require.NoError(t, err, "Builder validation failed") +} + func TestEthEnvInvalidHardForks(t *testing.T) { t.Parallel() builder := NewEthereumNetworkBuilder() _, err := builder. - //nolint:staticcheck //ignore SA1019 - WithConsensusType(config.ConsensusType_PoS). + WithEthereumVersion(config_types.EthereumVersion_Eth2). WithConsensusLayer(config.ConsensusLayer_Prysm). - WithExecutionLayer(config.ExecutionLayer_Geth). + WithExecutionLayer(config_types.ExecutionLayer_Geth). WithEthereumChainConfig(config.EthereumChainConfig{ HardForkEpochs: map[string]int{"Electra": 0}, }). @@ -335,24 +345,24 @@ func TestEthEnvAutoEthereumVersionEth1Minor(t *testing.T) { t.Parallel() builder := NewEthereumNetworkBuilder() cfg, err := builder. - WithExecutionLayer(config.ExecutionLayer_Besu). + WithExecutionLayer(config_types.ExecutionLayer_Besu). WithCustomDockerImages(map[config.ContainerType]string{ config.ContainerType_ExecutionLayer: "hyperledger/besu:20.1"}). Build() require.NoError(t, err, "Builder validation failed") - require.Equal(t, config.EthereumVersion_Eth1, *cfg.EthereumVersion, "Ethereum Version should be Eth1") + require.Equal(t, config_types.EthereumVersion_Eth1, *cfg.EthereumVersion, "Ethereum Version should be Eth1") require.Nil(t, cfg.ConsensusLayer, "Consensus layer should be nil") } func TestEthEnvAutoEthereumVersionEth2Minor(t *testing.T) { builder := NewEthereumNetworkBuilder() cfg, err := builder. - WithExecutionLayer(config.ExecutionLayer_Nethermind). + WithExecutionLayer(config_types.ExecutionLayer_Nethermind). WithCustomDockerImages(map[config.ContainerType]string{ config.ContainerType_ExecutionLayer: "nethermind/nethermind:1.17.2"}). Build() require.NoError(t, err, "Builder validation failed") - require.Equal(t, config.EthereumVersion_Eth2, *cfg.EthereumVersion, "Ethereum Version should be Eth2") + require.Equal(t, config_types.EthereumVersion_Eth2, *cfg.EthereumVersion, "Ethereum Version should be Eth2") require.Equal(t, config.ConsensusLayer_Prysm, *cfg.ConsensusLayer, "Consensus layer should be Prysm") } @@ -360,12 +370,12 @@ func TestEthEnvAutoEthereumVersionReleaseCandidate(t *testing.T) { t.Parallel() builder := NewEthereumNetworkBuilder() cfg, err := builder. - WithExecutionLayer(config.ExecutionLayer_Nethermind). + WithExecutionLayer(config_types.ExecutionLayer_Nethermind). WithCustomDockerImages(map[config.ContainerType]string{ config.ContainerType_ExecutionLayer: "nethermind/nethermind:1.17.0-RC2"}). Build() require.NoError(t, err, "Builder validation failed") - require.Equal(t, config.EthereumVersion_Eth2, *cfg.EthereumVersion, "Ethereum Version should be Eth2") + require.Equal(t, config_types.EthereumVersion_Eth2, *cfg.EthereumVersion, "Ethereum Version should be Eth2") require.Equal(t, config.ConsensusLayer_Prysm, *cfg.ConsensusLayer, "Consensus layer should be Prysm") } @@ -374,13 +384,13 @@ func TestEthEnvAutoEthereumVersionWithLettersInVersion(t *testing.T) { builder := NewEthereumNetworkBuilder() cfg, err := builder. WithConsensusLayer(config.ConsensusLayer_Prysm). - WithExecutionLayer(config.ExecutionLayer_Geth). + WithExecutionLayer(config_types.ExecutionLayer_Geth). WithCustomDockerImages(map[config.ContainerType]string{ config.ContainerType_ExecutionLayer: "ethereum/client-go:v1.13.10"}). Build() require.NoError(t, err, "Builder validation failed") - require.Equal(t, config.EthereumVersion_Eth2, *cfg.EthereumVersion, "Ethereum Version should be Eth2") - require.Equal(t, config.ExecutionLayer_Geth, *cfg.ExecutionLayer, "Execution layer should be Geth") + require.Equal(t, config_types.EthereumVersion_Eth2, *cfg.EthereumVersion, "Ethereum Version should be Eth2") + require.Equal(t, config_types.ExecutionLayer_Geth, *cfg.ExecutionLayer, "Execution layer should be Geth") require.Equal(t, config.ConsensusLayer_Prysm, *cfg.ConsensusLayer, "Consensus layer should be Prysm") } @@ -392,8 +402,8 @@ func TestEthEnvAutoEthereumVersionOnlyMajor(t *testing.T) { config.ContainerType_ExecutionLayer: "hyperledger/besu:v24.1"}). Build() require.NoError(t, err, "Builder validation failed") - require.Equal(t, config.EthereumVersion_Eth2, *cfg.EthereumVersion, "Ethereum Version should be Eth2") - require.Equal(t, config.ExecutionLayer_Besu, *cfg.ExecutionLayer, "Execution layer should be Besu") + require.Equal(t, config_types.EthereumVersion_Eth2, *cfg.EthereumVersion, "Ethereum Version should be Eth2") + require.Equal(t, config_types.ExecutionLayer_Besu, *cfg.ExecutionLayer, "Execution layer should be Besu") require.Equal(t, config.ConsensusLayer_Prysm, *cfg.ConsensusLayer, "Consensus layer should be Prysm") } @@ -405,8 +415,8 @@ func TestEthEnvLatestVersionFromGithub(t *testing.T) { config.ContainerType_ExecutionLayer: fmt.Sprintf("hyperledger/besu:%s", AUTOMATIC_STABLE_LATEST_TAG)}). Build() require.NoError(t, err, "Builder validation failed") - require.Equal(t, config.EthereumVersion_Eth2, *cfg.EthereumVersion, "Ethereum Version should be Eth2") - require.Equal(t, config.ExecutionLayer_Besu, *cfg.ExecutionLayer, "Execution layer should be Besu") + require.Equal(t, config_types.EthereumVersion_Eth2, *cfg.EthereumVersion, "Ethereum Version should be Eth2") + require.Equal(t, config_types.ExecutionLayer_Besu, *cfg.ExecutionLayer, "Execution layer should be Besu") require.Equal(t, config.ConsensusLayer_Prysm, *cfg.ConsensusLayer, "Consensus layer should be Prysm") require.NotContains(t, cfg.CustomDockerImages[config.ContainerType_ExecutionLayer], AUTOMATIC_STABLE_LATEST_TAG, "Automatic tag should be replaced") } @@ -415,10 +425,10 @@ func TestEthEnvMischmachedExecutionClient(t *testing.T) { t.Parallel() builder := NewEthereumNetworkBuilder() _, err := builder. - WithExecutionLayer(config.ExecutionLayer_Nethermind). + WithExecutionLayer(config_types.ExecutionLayer_Nethermind). WithCustomDockerImages(map[config.ContainerType]string{ config.ContainerType_ExecutionLayer: "hyperledger/besu:v1.22.0"}). Build() require.Error(t, err, "Builder validation succeeded") - require.Equal(t, fmt.Sprintf(MsgMismatchedExecutionClient, config.ExecutionLayer_Besu, config.ExecutionLayer_Nethermind), err.Error(), "Error message is not correct") + require.Equal(t, fmt.Sprintf(MsgMismatchedExecutionClient, config_types.ExecutionLayer_Besu, config_types.ExecutionLayer_Nethermind), err.Error(), "Error message is not correct") } diff --git a/docker/test_env/ethereum_env_versions_test.go b/docker/test_env/ethereum_env_versions_test.go index 49ca8433f..241b22f02 100644 --- a/docker/test_env/ethereum_env_versions_test.go +++ b/docker/test_env/ethereum_env_versions_test.go @@ -6,6 +6,9 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" @@ -36,7 +39,7 @@ func TestEthEnvNethermindCompatibility(t *testing.T) { nethermindTcs = append(nethermindTcs, fmt.Sprintf("nethermind/nethermind:1.%d.0", i)) } - nethermindTcs = append(nethermindTcs, defaultNethermindEth2Image) + nethermindTcs = append(nethermindTcs, ethereum.DefaultNethermindEth2Image) latest, err := FetchLatestEthereumClientDockerImageVersionIfNeed(fmt.Sprintf("nethermind/nethermind:%s", AUTOMATIC_STABLE_LATEST_TAG)) require.NoError(t, err, "Couldn't fetch the latest Nethermind version") @@ -47,7 +50,7 @@ func TestEthEnvNethermindCompatibility(t *testing.T) { t.Run(fmt.Sprintf("nethermind-%s", tc), func(t *testing.T) { builder := NewEthereumNetworkBuilder() cfg, err := builder. - WithExecutionLayer(config.ExecutionLayer_Nethermind). + WithExecutionLayer(types.ExecutionLayer_Nethermind). WithCustomDockerImages(map[config.ContainerType]string{ config.ContainerType_ExecutionLayer: tc, }). @@ -84,7 +87,7 @@ func TestEthEnvGethCompatibility(t *testing.T) { gethTcs = append(gethTcs, fmt.Sprintf("ethereum/client-go:v1.%d.0", i)) } - gethTcs = append(gethTcs, defaultGethEth2Image) + gethTcs = append(gethTcs, ethereum.DefaultGethEth2Image) latest, err := FetchLatestEthereumClientDockerImageVersionIfNeed(fmt.Sprintf("ethereum/client-go:%s", AUTOMATIC_STABLE_LATEST_TAG)) require.NoError(t, err, "Couldn't fetch the latest Go Ethereum version") @@ -131,7 +134,7 @@ func TestEthEnvErigonCompatibility(t *testing.T) { erigonTcs = append(erigonTcs, fmt.Sprintf("thorax/erigon:v2.%d.0", i)) } - erigonTcs = append(erigonTcs, defaultErigonEth2Image) + erigonTcs = append(erigonTcs, ethereum.DefaultErigonEth2Image) latest, err := FetchLatestEthereumClientDockerImageVersionIfNeed(fmt.Sprintf("thorax/erigon:%s", AUTOMATIC_STABLE_LATEST_TAG)) require.NoError(t, err, "Couldn't fetch the latest Erigon version") @@ -178,7 +181,7 @@ func TestEthEnvBesuCompatibility(t *testing.T) { besuTcs = append(besuTcs, fmt.Sprintf("hyperledger/besu:%d.1.0", i)) } - besuTcs = append(besuTcs, defaultBesuEth2Image) + besuTcs = append(besuTcs, ethereum.DefaultBesuEth2Image) latest, err := FetchLatestEthereumClientDockerImageVersionIfNeed(fmt.Sprintf("hyperledger/besu:%s", AUTOMATIC_STABLE_LATEST_TAG)) require.NoError(t, err, "Couldn't fetch the latest Erigon version") diff --git a/docker/test_env/genesis_generator.go b/docker/test_env/genesis_generator.go index 77dc00242..03a46c3bb 100644 --- a/docker/test_env/genesis_generator.go +++ b/docker/test_env/genesis_generator.go @@ -17,32 +17,53 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/docker" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/mirror" ) -const defaultGenisisGeneratorImage = "tofelb/ethereum-genesis-generator:3.3.4-slots-per-epoch" +var generatorForkToImageMap = map[ethereum.Fork]string{ + ethereum.EthereumFork_Shanghai: "tofelb/ethereum-genesis-generator:2.0.5", + ethereum.EthereumFork_Deneb: "tofelb/ethereum-genesis-generator:3.3.5-no-future-forks", +} + +var generatorForkToDataDirMap = map[ethereum.Fork]string{ + ethereum.EthereumFork_Shanghai: "/data/custom_config_data", + ethereum.EthereumFork_Deneb: "/data/metadata", +} -type EthGenesisGeneretor struct { +type EthGenesisGenerator struct { EnvComponent - chainConfig config.EthereumChainConfig - l zerolog.Logger - generatedDataHostDir string - t *testing.T + chainConfig config.EthereumChainConfig + l zerolog.Logger + generatedDataHostDir string + generatedDataContainerDir string + t *testing.T } -func NewEthGenesisGenerator(chainConfig config.EthereumChainConfig, generatedDataHostDir string, opts ...EnvComponentOption) (*EthGenesisGeneretor, error) { - parts := strings.Split(defaultGenisisGeneratorImage, ":") - g := &EthGenesisGeneretor{ +func NewEthGenesisGenerator(chainConfig config.EthereumChainConfig, generatedDataHostDir string, lastFork ethereum.Fork, opts ...EnvComponentOption) (*EthGenesisGenerator, error) { + genesisGeneratorImage, ok := generatorForkToImageMap[lastFork] + if !ok { + return nil, fmt.Errorf("unknown fork: %s", lastFork) + } + + generatedDataContainerDir, ok := generatorForkToDataDirMap[lastFork] + if !ok { + return nil, fmt.Errorf("unknown fork: %s", lastFork) + } + + parts := strings.Split(genesisGeneratorImage, ":") + g := &EthGenesisGenerator{ EnvComponent: EnvComponent{ ContainerName: fmt.Sprintf("%s-%s", "eth-genesis-generator", uuid.NewString()[0:8]), ContainerImage: parts[0], ContainerVersion: parts[1], StartupTimeout: 30 * time.Second, }, - chainConfig: chainConfig, - generatedDataHostDir: generatedDataHostDir, - l: log.Logger, + chainConfig: chainConfig, + generatedDataHostDir: generatedDataHostDir, + generatedDataContainerDir: generatedDataContainerDir, + l: log.Logger, } g.SetDefaultHooks() for _, opt := range opts { @@ -53,13 +74,13 @@ func NewEthGenesisGenerator(chainConfig config.EthereumChainConfig, generatedDat return g, nil } -func (g *EthGenesisGeneretor) WithTestInstance(t *testing.T) *EthGenesisGeneretor { +func (g *EthGenesisGenerator) WithTestInstance(t *testing.T) *EthGenesisGenerator { g.l = logging.GetTestLogger(t) g.t = t return g } -func (g *EthGenesisGeneretor) StartContainer() error { +func (g *EthGenesisGenerator) StartContainer() error { r, err := g.getContainerRequest(g.Networks) if err != nil { return err @@ -82,7 +103,7 @@ func (g *EthGenesisGeneretor) StartContainer() error { return nil } -func (g *EthGenesisGeneretor) getContainerRequest(networks []string) (*tc.ContainerRequest, error) { +func (g *EthGenesisGenerator) getContainerRequest(networks []string) (*tc.ContainerRequest, error) { valuesEnv, err := os.CreateTemp("", "values.env") if err != nil { return nil, err @@ -131,7 +152,7 @@ func (g *EthGenesisGeneretor) getContainerRequest(networks []string) (*tc.Contai Networks: networks, WaitingFor: tcwait.ForAll( tcwait.ForLog("+ terminalTotalDifficulty=0"), - tcwait.ForLog("+ sed -i 's/TERMINAL_TOTAL_DIFFICULTY:.*/TERMINAL_TOTAL_DIFFICULTY: 0/' /data/metadata/config.yaml"). + tcwait.ForLog(fmt.Sprintf("+ sed -i 's/TERMINAL_TOTAL_DIFFICULTY:.*/TERMINAL_TOTAL_DIFFICULTY: 0/' %s/config.yaml", g.generatedDataContainerDir)). WithPollInterval(1*time.Second), ).WithStartupTimeoutDefault(g.StartupTimeout), Cmd: []string{"all"}, @@ -161,7 +182,7 @@ func (g *EthGenesisGeneretor) getContainerRequest(networks []string) (*tc.Contai hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{ Type: mount.TypeBind, Source: g.generatedDataHostDir, - Target: GENERATED_DATA_DIR_INSIDE_CONTAINER, + Target: g.generatedDataContainerDir, ReadOnly: false, }) }, @@ -173,3 +194,7 @@ func (g *EthGenesisGeneretor) getContainerRequest(networks []string) (*tc.Contai }, }, nil } + +func (g *EthGenesisGenerator) GetGeneratedDataContainerDir() string { + return g.generatedDataContainerDir +} diff --git a/docker/test_env/genesis_generator_helpers.go b/docker/test_env/genesis_generator_helpers.go index 98af0e757..fe6f64eb0 100644 --- a/docker/test_env/genesis_generator_helpers.go +++ b/docker/test_env/genesis_generator_helpers.go @@ -54,11 +54,11 @@ export BELLATRIX_FORK_VERSION="0x30000038" export CAPELLA_FORK_VERSION="0x40000038" export CAPELLA_FORK_EPOCH="0" export DENEB_FORK_VERSION="0x50000038" -export DENEB_FORK_EPOCH="0" +export DENEB_FORK_EPOCH="{{.HardForkEpochs.Deneb}}" export ELECTRA_FORK_VERSION="0x60000038" -export ELECTRA_FORK_EPOCH="{{.HardForkEpochs.Electra}}" +#export ELECTRA_FORK_EPOCH="{{.HardForkEpochs.Electra}}" export EIP7594_FORK_VERSION="0x70000000" -export EIP7594_FORK_EPOCH="{{.HardForkEpochs.EOF}}" +#export EIP7594_FORK_EPOCH="{{.HardForkEpochs.EOF}}" export WITHDRAWAL_TYPE="0x00" export WITHDRAWAL_ADDRESS=0xf97e180c050e5Ab072211Ad2C213Eb5AEE4DF134 export BEACON_STATIC_ENR="enr:-Iq4QJk4WqRkjsX5c2CXtOra6HnxN-BMXnWhmhEQO9Bn9iABTJGdjUOurM7Btj1ouKaFkvTRoju5vz2GPmVON2dffQKGAX53x8JigmlkgnY0gmlwhLKAlv6Jc2VjcDI1NmsxoQK6S-Cii_KmfFdUJL2TANL3ksaKUnNXvTCv1tLwXs0QgIN1ZHCCIyk" @@ -118,6 +118,7 @@ el_premine_addrs: ${PREMINE_ADDRS} genesis_timestamp: ${GENESIS_TIMESTAMP} genesis_delay: ${GENESIS_DELAY} genesis_gaslimit: ${GENESIS_GASLIMIT} +deneb_fork_epoch: ${DENEB_FORK_EPOCH} additional_preloaded_contracts: ${ADDITIONAL_PRELOADED_CONTRACTS} slot_duration_in_seconds: ${SLOT_DURATION_IN_SECONDS} electra_fork_epoch: ${ELECTRA_FORK_EPOCH} @@ -163,7 +164,7 @@ CAPELLA_FORK_EPOCH: 0 # DENEB DENEB_FORK_VERSION: $DENEB_FORK_VERSION -DENEB_FORK_EPOCH: 0 +DENEB_FORK_EPOCH: $DENEB_FORK_EPOCH # Electra ELECTRA_FORK_VERSION: $ELECTRA_FORK_VERSION diff --git a/docker/test_env/geth_base.go b/docker/test_env/geth_base.go index e0d40e04e..1ab454b8d 100644 --- a/docker/test_env/geth_base.go +++ b/docker/test_env/geth_base.go @@ -6,8 +6,10 @@ import ( "testing" "time" - "github.com/rs/zerolog" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/Masterminds/semver/v3" + "github.com/rs/zerolog" tc "github.com/testcontainers/testcontainers-go" tcwait "github.com/testcontainers/testcontainers-go/wait" @@ -15,16 +17,10 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/docker" "github.com/smartcontractkit/chainlink-testing-framework/logging" + docker_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/docker" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" ) -const ( - defaultGethEth1Image = "ethereum/client-go:v1.13.8" - defaultGethEth2Image = "ethereum/client-go:v1.14.3" - gethBaseImageName = "ethereum/client-go" - gethGitRepo = "ethereum/go-ethereum" -) - type Geth struct { EnvComponent ExternalHttpUrl string @@ -33,12 +29,12 @@ type Geth struct { InternalWsUrl string InternalExecutionURL string ExternalExecutionURL string - generatedDataHostDir string chainConfig *config.EthereumChainConfig consensusLayer config.ConsensusLayer - ethereumVersion config.EthereumVersion + ethereumVersion config_types.EthereumVersion l zerolog.Logger t *testing.T + posContainerSettings } func (g *Geth) WithTestInstance(t *testing.T) ExecutionClient { @@ -50,7 +46,7 @@ func (g *Geth) WithTestInstance(t *testing.T) ExecutionClient { func (g *Geth) StartContainer() (blockchain.EVMNetwork, error) { var r *tc.ContainerRequest var err error - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { r, err = g.getEth1ContainerRequest() } else { r, err = g.getEth2ContainerRequest() @@ -82,7 +78,7 @@ func (g *Geth) StartContainer() (blockchain.EVMNetwork, error) { if err != nil { return blockchain.EVMNetwork{}, err } - if g.GetEthereumVersion() == config.EthereumVersion_Eth2 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth2 { executionPort, err := ct.MappedPort(testcontext.Get(g.t), NatPort(ETH2_EXECUTION_PORT)) if err != nil { return blockchain.EVMNetwork{}, err @@ -98,7 +94,7 @@ func (g *Geth) StartContainer() (blockchain.EVMNetwork, error) { g.InternalWsUrl = FormatWsUrl(g.ContainerName, DEFAULT_EVM_NODE_WS_PORT) networkConfig := blockchain.SimulatedEVMNetwork - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { networkConfig.Name = fmt.Sprintf("Private Eth-1-PoA [geth %s]", g.ContainerVersion) } else { networkConfig.Name = fmt.Sprintf("Private Eth-2-PoS [geth %s] + %s", g.ContainerVersion, g.consensusLayer) @@ -107,12 +103,17 @@ func (g *Geth) StartContainer() (blockchain.EVMNetwork, error) { networkConfig.HTTPURLs = []string{g.ExternalHttpUrl} networkConfig.SimulationType = "Geth" - comparableVersion, err := GetComparableVersionFromDockerImage(g.GetImageWithVersion()) + version, err := docker_utils.GetSemverFromImage(g.GetImageWithVersion()) if err != nil { return blockchain.EVMNetwork{}, err } - if comparableVersion >= 110 && comparableVersion < 111 { + constraint, err := semver.NewConstraint(">=1.10 <1.11") + if err != nil { + return blockchain.EVMNetwork{}, fmt.Errorf("failed to parse constraint: %s", ">=1.10 <1.11") + } + + if constraint.Check(version) { // Geth v1.10.x will not set it itself if it's set 0, like later versions do networkConfig.DefaultGasLimit = 9_000_000 } @@ -124,14 +125,14 @@ func (g *Geth) StartContainer() (blockchain.EVMNetwork, error) { } func (g *Geth) GetInternalExecutionURL() string { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { panic("eth1 node doesn't have an execution URL") } return g.InternalExecutionURL } func (g *Geth) GetExternalExecutionURL() string { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { panic("eth1 node doesn't have an execution URL") } return g.ExternalExecutionURL @@ -161,19 +162,19 @@ func (g *Geth) GetContainer() *tc.Container { return &g.Container } -func (g *Geth) GetEthereumVersion() config.EthereumVersion { +func (g *Geth) GetEthereumVersion() config_types.EthereumVersion { return g.ethereumVersion } func (g *Geth) GethConsensusMechanism() ConsensusMechanism { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { return ConsensusMechanism_PoA } return ConsensusMechanism_PoS } func (g *Geth) WaitUntilChainIsReady(ctx context.Context, waitTime time.Duration) error { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { return nil } waitForFirstBlock := tcwait.NewLogStrategy("Chain head was updated").WithPollInterval(1 * time.Second).WithStartupTimeout(waitTime) @@ -181,7 +182,7 @@ func (g *Geth) WaitUntilChainIsReady(ctx context.Context, waitTime time.Duration } func (g *Geth) getEntryPointAndKeystoreLocation(minerAddress string) ([]string, error) { - version, err := GetComparableVersionFromDockerImage(g.GetImageWithVersion()) + version, err := docker_utils.GetSemverFromImage(g.GetImageWithVersion()) if err != nil { return nil, err } @@ -204,7 +205,12 @@ func (g *Geth) getEntryPointAndKeystoreLocation(minerAddress string) ([]string, "--unlock", minerAddress, } - if version < 110 { + constraint, err := semver.NewConstraint("<1.10") + if err != nil { + return nil, fmt.Errorf("failed to parse constraint: %s", "<1.10") + } + + if constraint.Check(version) { entrypoint = append(entrypoint, "--rpc", "--rpcapi", enabledApis, @@ -218,9 +224,7 @@ func (g *Geth) getEntryPointAndKeystoreLocation(minerAddress string) ([]string, "--wsapi", enabledApis, fmt.Sprintf("--wsport=%s", DEFAULT_EVM_NODE_WS_PORT), ) - } - - if version >= 110 { + } else { entrypoint = append(entrypoint, "--http", "--http.vhosts", "*", @@ -242,12 +246,17 @@ func (g *Geth) getEntryPointAndKeystoreLocation(minerAddress string) ([]string, } func (g *Geth) getWebsocketEnabledMessage() (string, error) { - version, err := GetComparableVersionFromDockerImage(g.GetImageWithVersion()) + version, err := docker_utils.GetSemverFromImage(g.GetImageWithVersion()) if err != nil { return "", err } - if version < 110 { + constraint, err := semver.NewConstraint("<1.10") + if err != nil { + return "", fmt.Errorf("failed to parse constraint: %s", "<1.10") + } + + if constraint.Check(version) { return "WebSocket endpoint opened", nil } diff --git a/docker/test_env/geth_eth1.go b/docker/test_env/geth_eth1.go index d2763e49f..5581b3982 100644 --- a/docker/test_env/geth_eth1.go +++ b/docker/test_env/geth_eth1.go @@ -7,6 +7,8 @@ import ( "strings" "time" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/mount" "github.com/google/uuid" @@ -14,6 +16,7 @@ import ( tcwait "github.com/testcontainers/testcontainers-go/wait" "github.com/smartcontractkit/chainlink-testing-framework/config" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/mirror" "github.com/smartcontractkit/chainlink-testing-framework/utils/templates" @@ -21,7 +24,7 @@ import ( // NewGethEth1 starts a new Geth Eth1 node running in Docker func NewGethEth1(networks []string, chainConfig *config.EthereumChainConfig, opts ...EnvComponentOption) *Geth { - parts := strings.Split(defaultGethEth1Image, ":") + parts := strings.Split(ethereum.DefaultGethEth1Image, ":") g := &Geth{ EnvComponent: EnvComponent{ ContainerName: fmt.Sprintf("%s-%s", "geth-eth1", uuid.NewString()[0:8]), @@ -32,7 +35,7 @@ func NewGethEth1(networks []string, chainConfig *config.EthereumChainConfig, opt }, chainConfig: chainConfig, l: logging.GetTestLogger(nil), - ethereumVersion: config.EthereumVersion_Eth1, + ethereumVersion: config_types.EthereumVersion_Eth1, } g.SetDefaultHooks() for _, opt := range opts { diff --git a/docker/test_env/geth_eth2.go b/docker/test_env/geth_eth2.go index 8a0590a23..dc8138639 100644 --- a/docker/test_env/geth_eth2.go +++ b/docker/test_env/geth_eth2.go @@ -8,6 +8,8 @@ import ( "strings" "time" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/mount" "github.com/google/uuid" @@ -15,13 +17,14 @@ import ( tcwait "github.com/testcontainers/testcontainers-go/wait" "github.com/smartcontractkit/chainlink-testing-framework/config" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/mirror" ) // NewGethEth2 starts a new Geth Eth2 node running in Docker -func NewGethEth2(networks []string, chainConfig *config.EthereumChainConfig, generatedDataHostDir string, consensusLayer config.ConsensusLayer, opts ...EnvComponentOption) (*Geth, error) { - parts := strings.Split(defaultGethEth2Image, ":") +func NewGethEth2(networks []string, chainConfig *config.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir string, consensusLayer config.ConsensusLayer, opts ...EnvComponentOption) (*Geth, error) { + parts := strings.Split(ethereum.DefaultGethEth2Image, ":") g := &Geth{ EnvComponent: EnvComponent{ ContainerName: fmt.Sprintf("%s-%s", "geth-eth2", uuid.NewString()[0:8]), @@ -31,10 +34,10 @@ func NewGethEth2(networks []string, chainConfig *config.EthereumChainConfig, gen StartupTimeout: 2 * time.Minute, }, chainConfig: chainConfig, - generatedDataHostDir: generatedDataHostDir, + posContainerSettings: posContainerSettings{generatedDataHostDir: generatedDataHostDir, generatedDataContainerDir: generatedDataContainerDir}, consensusLayer: consensusLayer, l: logging.GetTestLogger(nil), - ethereumVersion: config.EthereumVersion_Eth2, + ethereumVersion: config_types.EthereumVersion_Eth2, } g.SetDefaultHooks() for _, opt := range opts { @@ -91,7 +94,7 @@ func (g *Geth) getEth2ContainerRequest() (*tc.ContainerRequest, error) { hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{ Type: mount.TypeBind, Source: g.generatedDataHostDir, - Target: GENERATED_DATA_DIR_INSIDE_CONTAINER, + Target: g.generatedDataContainerDir, ReadOnly: false, }) }, @@ -152,10 +155,10 @@ func (g *Geth) buildEth2dInitScript() (string, error) { HttpPort: DEFAULT_EVM_NODE_HTTP_PORT, WsPort: DEFAULT_EVM_NODE_WS_PORT, ChainID: g.chainConfig.ChainID, - GeneratedDataDir: GENERATED_DATA_DIR_INSIDE_CONTAINER, - JwtFileLocation: JWT_SECRET_FILE_LOCATION_INSIDE_CONTAINER, - PasswordFileLocation: ACCOUNT_PASSWORD_FILE_INSIDE_CONTAINER, - KeystoreDirLocation: KEYSTORE_DIR_LOCATION_INSIDE_CONTAINER, + GeneratedDataDir: g.generatedDataContainerDir, + JwtFileLocation: getJWTSecretFileLocationInsideContainer(g.generatedDataContainerDir), + PasswordFileLocation: getAccountPasswordFileInsideContainer(g.generatedDataContainerDir), + KeystoreDirLocation: getKeystoreDirLocationInsideContainer(g.generatedDataContainerDir), ExecutionDir: "/execution-data", Verbosity: verbosity, } diff --git a/docker/test_env/geth_test.go b/docker/test_env/geth_test.go index 00dfadc66..5a71ea871 100644 --- a/docker/test_env/geth_test.go +++ b/docker/test_env/geth_test.go @@ -4,6 +4,8 @@ import ( "fmt" "testing" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" @@ -18,7 +20,7 @@ func TestGethLegacy(t *testing.T) { l := logging.GetTestLogger(t) network, err := docker.CreateNetwork(l) require.NoError(t, err) - defaultChainCfg := config.GetDefaultChainConfig() + defaultChainCfg := config.MustGetDefaultChainConfig() g := NewGethEth1([]string{network.Name}, &defaultChainCfg). WithTestInstance(t) _, err = g.StartContainer() @@ -37,11 +39,11 @@ func TestGethEth1(t *testing.T) { builder := NewEthereumNetworkBuilder() cfg, err := builder. //nolint:staticcheck //ignore SA1019 - WithEthereumVersion(config.EthereumVersion_Eth1_Legacy). + WithEthereumVersion(config_types.EthereumVersion_Eth1_Legacy). WithEthereumChainConfig(config.EthereumChainConfig{ ChainID: 2337, }). - WithExecutionLayer(config.ExecutionLayer_Geth). + WithExecutionLayer(config_types.ExecutionLayer_Geth). Build() require.NoError(t, err, "Builder validation failed") @@ -54,15 +56,14 @@ func TestGethEth1(t *testing.T) { require.NoError(t, err, "Couldn't close the client") } -func TestGethEth2(t *testing.T) { +func TestGethEth2_Deneb(t *testing.T) { l := logging.GetTestLogger(t) builder := NewEthereumNetworkBuilder() cfg, err := builder. - //nolint:staticcheck //ignore SA1019 - WithEthereumVersion(config.EthereumVersion_Eth2_Legacy). + WithCustomDockerImages(map[config.ContainerType]string{config.ContainerType_ExecutionLayer: "ethereum/client-go:v1.13.12"}). WithConsensusLayer(config.ConsensusLayer_Prysm). - WithExecutionLayer(config.ExecutionLayer_Geth). + WithExecutionLayer(config_types.ExecutionLayer_Geth). Build() require.NoError(t, err, "Builder validation failed") @@ -100,3 +101,67 @@ func TestGethEth2(t *testing.T) { err = sendAndCompareBalances(ctx, clientTwo, address) require.NoError(t, err, fmt.Sprintf("balance wasn't correctly updated for %s network", eip1559Network.Name)) } + +func TestGethEth2_Shanghai_No_Fork_Setup(t *testing.T) { + l := logging.GetTestLogger(t) + + builder := NewEthereumNetworkBuilder() + cfg, err := builder. + WithCustomDockerImages(map[config.ContainerType]string{config.ContainerType_ExecutionLayer: "ethereum/client-go:v1.13.11"}). + WithExecutionLayer(config_types.ExecutionLayer_Geth). + Build() + require.NoError(t, err, "Builder validation failed") + + _, eth2, err := cfg.Start() + require.NoError(t, err, "Couldn't start PoS network") + + nonEip1559Network := blockchain.SimulatedEVMNetwork + nonEip1559Network.Name = "Simulated Geth + Prysm (non-EIP 1559)" + nonEip1559Network.URLs = eth2.PublicWsUrls() + clientOne, err := blockchain.ConnectEVMClient(nonEip1559Network, l) + require.NoError(t, err, "Couldn't connect to the evm client") + + t.Cleanup(func() { + err = clientOne.Close() + require.NoError(t, err, "Couldn't close the client") + }) + + ctx := testcontext.Get(t) + address := common.HexToAddress("0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1") + err = sendAndCompareBalances(ctx, clientOne, address) + require.NoError(t, err, fmt.Sprintf("balance wasn't correctly updated for %s network", nonEip1559Network.Name)) +} + +func TestGethEth2_Shanghai(t *testing.T) { + l := logging.GetTestLogger(t) + + chainConfig := config.MustGetDefaultChainConfig() + chainConfig.HardForkEpochs = map[string]int{"Deneb": 500} + + builder := NewEthereumNetworkBuilder() + cfg, err := builder. + WithCustomDockerImages(map[config.ContainerType]string{config.ContainerType_ExecutionLayer: "ethereum/client-go:v1.13.11"}). + WithExecutionLayer(config_types.ExecutionLayer_Geth). + WithEthereumChainConfig(chainConfig). + Build() + require.NoError(t, err, "Builder validation failed") + + _, eth2, err := cfg.Start() + require.NoError(t, err, "Couldn't start PoS network") + + nonEip1559Network := blockchain.SimulatedEVMNetwork + nonEip1559Network.Name = "Simulated Geth + Prysm (non-EIP 1559)" + nonEip1559Network.URLs = eth2.PublicWsUrls() + clientOne, err := blockchain.ConnectEVMClient(nonEip1559Network, l) + require.NoError(t, err, "Couldn't connect to the evm client") + + t.Cleanup(func() { + err = clientOne.Close() + require.NoError(t, err, "Couldn't close the client") + }) + + ctx := testcontext.Get(t) + address := common.HexToAddress("0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1") + err = sendAndCompareBalances(ctx, clientOne, address) + require.NoError(t, err, fmt.Sprintf("balance wasn't correctly updated for %s network", nonEip1559Network.Name)) +} diff --git a/docker/test_env/github_utils.go b/docker/test_env/github_utils.go index be4267af9..941c94dab 100644 --- a/docker/test_env/github_utils.go +++ b/docker/test_env/github_utils.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/smartcontractkit/chainlink-testing-framework/client" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" ) const AUTOMATIC_LATEST_TAG = "latest_available" @@ -18,7 +19,7 @@ func FetchLatestEthereumClientDockerImageVersionIfNeed(dockerImageWithVersion st return "", fmt.Errorf("expected correctly formatted docker image, but got '%s'", dockerImageWithVersion) } - ghRepo, err := GetGithubRepositoryFromEthereumClientDockerImage(dockerImageWithVersion) + ghRepo, err := ethereum.GithubRepositoryFromEthereumClientDockerImage(dockerImageWithVersion) if err != nil { return "", err } diff --git a/docker/test_env/nethermind_base.go b/docker/test_env/nethermind_base.go index 33e6949ca..1e7937d8f 100644 --- a/docker/test_env/nethermind_base.go +++ b/docker/test_env/nethermind_base.go @@ -6,6 +6,8 @@ import ( "testing" "time" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/rs/zerolog" tc "github.com/testcontainers/testcontainers-go" @@ -17,13 +19,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/logging" ) -const ( - defaultNethermindEth1Image = "nethermind/nethermind:1.16.0" - defaultNethermindEth2Image = "nethermind/nethermind:1.26.0" - nethermindBaseImageName = "nethermind/nethermind" - nethermindGitRepo = "NethermindEth/nethermind" -) - type Nethermind struct { EnvComponent ExternalHttpUrl string @@ -32,12 +27,12 @@ type Nethermind struct { InternalWsUrl string InternalExecutionURL string ExternalExecutionURL string - generatedDataHostDir string chainConfig *config.EthereumChainConfig consensusLayer config.ConsensusLayer - ethereumVersion config.EthereumVersion + ethereumVersion config_types.EthereumVersion l zerolog.Logger t *testing.T + posContainerSettings } func (g *Nethermind) WithTestInstance(t *testing.T) ExecutionClient { @@ -49,7 +44,7 @@ func (g *Nethermind) WithTestInstance(t *testing.T) ExecutionClient { func (g *Nethermind) StartContainer() (blockchain.EVMNetwork, error) { var r *tc.ContainerRequest var err error - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { r, err = g.getEth1ContainerRequest() } else { @@ -83,7 +78,7 @@ func (g *Nethermind) StartContainer() (blockchain.EVMNetwork, error) { return blockchain.EVMNetwork{}, err } - if g.GetEthereumVersion() == config.EthereumVersion_Eth2 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth2 { executionPort, err := ct.MappedPort(context.Background(), NatPort(ETH2_EXECUTION_PORT)) if err != nil { return blockchain.EVMNetwork{}, err @@ -99,7 +94,7 @@ func (g *Nethermind) StartContainer() (blockchain.EVMNetwork, error) { g.InternalWsUrl = FormatWsUrl(g.ContainerName, DEFAULT_EVM_NODE_WS_PORT) networkConfig := blockchain.SimulatedEVMNetwork - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { networkConfig.Name = fmt.Sprintf("Private Eth-1-PoA [nethermind %s", g.ContainerVersion) networkConfig.GasEstimationBuffer = 100_000_000_000 } else { @@ -116,14 +111,14 @@ func (g *Nethermind) StartContainer() (blockchain.EVMNetwork, error) { } func (g *Nethermind) GetInternalExecutionURL() string { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { panic("eth1 node doesn't have an execution URL") } return g.InternalExecutionURL } func (g *Nethermind) GetExternalExecutionURL() string { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { panic("eth1 node doesn't have an execution URL") } return g.ExternalExecutionURL @@ -153,12 +148,12 @@ func (g *Nethermind) GetContainer() *tc.Container { return &g.Container } -func (g *Nethermind) GetEthereumVersion() config.EthereumVersion { +func (g *Nethermind) GetEthereumVersion() config_types.EthereumVersion { return g.ethereumVersion } func (g *Nethermind) WaitUntilChainIsReady(ctx context.Context, waitTime time.Duration) error { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { return nil } waitForFirstBlock := tcwait.NewLogStrategy("Improved post-merge block").WithPollInterval(1 * time.Second).WithStartupTimeout(waitTime) @@ -166,7 +161,7 @@ func (g *Nethermind) WaitUntilChainIsReady(ctx context.Context, waitTime time.Du } func (g *Nethermind) GethConsensusMechanism() ConsensusMechanism { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { return ConsensusMechanism_PoA } return ConsensusMechanism_PoS diff --git a/docker/test_env/nethermind_eth1.go b/docker/test_env/nethermind_eth1.go index d64639a6a..4abefd4dc 100644 --- a/docker/test_env/nethermind_eth1.go +++ b/docker/test_env/nethermind_eth1.go @@ -7,6 +7,8 @@ import ( "strings" "time" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/mount" "github.com/google/uuid" @@ -14,14 +16,15 @@ import ( tcwait "github.com/testcontainers/testcontainers-go/wait" "github.com/smartcontractkit/chainlink-testing-framework/config" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/mirror" "github.com/smartcontractkit/chainlink-testing-framework/utils/templates" ) -// NewNethermindEth1 starts a new Nethermin Eth1 node running in Docker +// NewNethermindEth1 starts a new Nethermind Eth1 node running in Docker func NewNethermindEth1(networks []string, chainConfig *config.EthereumChainConfig, opts ...EnvComponentOption) (*Nethermind, error) { - parts := strings.Split(defaultNethermindEth1Image, ":") + parts := strings.Split(ethereum.DefaultNethermindEth1Image, ":") g := &Nethermind{ EnvComponent: EnvComponent{ ContainerName: fmt.Sprintf("%s-%s", "nethermind-eth1", uuid.NewString()[0:8]), @@ -32,7 +35,7 @@ func NewNethermindEth1(networks []string, chainConfig *config.EthereumChainConfi }, chainConfig: chainConfig, l: logging.GetTestLogger(nil), - ethereumVersion: config.EthereumVersion_Eth1, + ethereumVersion: config_types.EthereumVersion_Eth1, } g.SetDefaultHooks() for _, opt := range opts { diff --git a/docker/test_env/nethermind_eth2.go b/docker/test_env/nethermind_eth2.go index b860a2883..9cb12b9ea 100644 --- a/docker/test_env/nethermind_eth2.go +++ b/docker/test_env/nethermind_eth2.go @@ -6,6 +6,8 @@ import ( "strings" "time" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/mount" "github.com/google/uuid" @@ -13,13 +15,14 @@ import ( tcwait "github.com/testcontainers/testcontainers-go/wait" "github.com/smartcontractkit/chainlink-testing-framework/config" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/mirror" ) // NewNethermindEth2 starts a new Nethermin Eth2 node running in Docker -func NewNethermindEth2(networks []string, chainConfig *config.EthereumChainConfig, generatedDataHostDir string, consensusLayer config.ConsensusLayer, opts ...EnvComponentOption) (*Nethermind, error) { - parts := strings.Split(defaultNethermindEth2Image, ":") +func NewNethermindEth2(networks []string, chainConfig *config.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir string, consensusLayer config.ConsensusLayer, opts ...EnvComponentOption) (*Nethermind, error) { + parts := strings.Split(ethereum.DefaultNethermindEth2Image, ":") g := &Nethermind{ EnvComponent: EnvComponent{ ContainerName: fmt.Sprintf("%s-%s", "nethermind-eth2", uuid.NewString()[0:8]), @@ -28,11 +31,11 @@ func NewNethermindEth2(networks []string, chainConfig *config.EthereumChainConfi ContainerVersion: parts[1], StartupTimeout: 2 * time.Minute, }, - generatedDataHostDir: generatedDataHostDir, + posContainerSettings: posContainerSettings{generatedDataHostDir: generatedDataHostDir, generatedDataContainerDir: generatedDataContainerDir}, chainConfig: chainConfig, consensusLayer: consensusLayer, l: logging.GetTestLogger(nil), - ethereumVersion: config.EthereumVersion_Eth2, + ethereumVersion: config_types.EthereumVersion_Eth2, } g.SetDefaultHooks() for _, opt := range opts { @@ -64,7 +67,7 @@ func (g *Nethermind) getEth2ContainerRequest() (*tc.ContainerRequest, error) { command := []string{ "--datadir=/nethermind", "--config=/none.cfg", - fmt.Sprintf("--Init.ChainSpecPath=%s/chainspec.json", GENERATED_DATA_DIR_INSIDE_CONTAINER), + fmt.Sprintf("--Init.ChainSpecPath=%s/chainspec.json", g.generatedDataContainerDir), "--Init.DiscoveryEnabled=false", "--Init.WebSocketsEnabled=true", fmt.Sprintf("--JsonRpc.WebSocketsPort=%s", DEFAULT_EVM_NODE_WS_PORT), @@ -75,11 +78,11 @@ func (g *Nethermind) getEth2ContainerRequest() (*tc.ContainerRequest, error) { fmt.Sprintf("--JsonRpc.Port=%s", DEFAULT_EVM_NODE_HTTP_PORT), "--JsonRpc.EngineHost=0.0.0.0", "--JsonRpc.EnginePort=" + ETH2_EXECUTION_PORT, - fmt.Sprintf("--JsonRpc.JwtSecretFile=%s", JWT_SECRET_FILE_LOCATION_INSIDE_CONTAINER), - fmt.Sprintf("--KeyStore.KeyStoreDirectory=%s", KEYSTORE_DIR_LOCATION_INSIDE_CONTAINER), + fmt.Sprintf("--JsonRpc.JwtSecretFile=%s", getJWTSecretFileLocationInsideContainer(g.generatedDataContainerDir)), + fmt.Sprintf("--KeyStore.KeyStoreDirectory=%s", getKeystoreDirLocationInsideContainer(g.generatedDataContainerDir)), "--KeyStore.BlockAuthorAccount=0x123463a4b065722e99115d6c222f267d9cabb524", "--KeyStore.UnlockAccounts=0x123463a4b065722e99115d6c222f267d9cabb524", - fmt.Sprintf("--KeyStore.PasswordFiles=%s", ACCOUNT_PASSWORD_FILE_INSIDE_CONTAINER), + fmt.Sprintf("--KeyStore.PasswordFiles=%s", getAccountPasswordFileInsideContainer(g.generatedDataContainerDir)), "--Network.MaxActivePeers=0", "--Network.OnlyStaticPeers=true", "--HealthChecks.Enabled=true", // default slug /health @@ -115,7 +118,7 @@ func (g *Nethermind) getEth2ContainerRequest() (*tc.ContainerRequest, error) { hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{ Type: mount.TypeBind, Source: g.generatedDataHostDir, - Target: GENERATED_DATA_DIR_INSIDE_CONTAINER, + Target: g.generatedDataContainerDir, ReadOnly: false, }) }, diff --git a/docker/test_env/nethermind_test.go b/docker/test_env/nethermind_test.go index a5a61f4bf..184cb72e9 100644 --- a/docker/test_env/nethermind_test.go +++ b/docker/test_env/nethermind_test.go @@ -4,6 +4,8 @@ import ( "fmt" "testing" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" @@ -19,8 +21,8 @@ func TestNethermindEth1(t *testing.T) { builder := NewEthereumNetworkBuilder() cfg, err := builder. //nolint:staticcheck //ignore SA1019 - WithEthereumVersion(config.EthereumVersion_Eth1_Legacy). - WithExecutionLayer(config.ExecutionLayer_Nethermind). + WithEthereumVersion(config_types.EthereumVersion_Eth1_Legacy). + WithExecutionLayer(config_types.ExecutionLayer_Nethermind). Build() require.NoError(t, err, "Builder validation failed") @@ -38,15 +40,14 @@ func TestNethermindEth1(t *testing.T) { require.NoError(t, err, "Couldn't close the client") } -func TestNethermindEth2(t *testing.T) { +func TestNethermindEth2_Dencun(t *testing.T) { l := logging.GetTestLogger(t) builder := NewEthereumNetworkBuilder() cfg, err := builder. - //nolint:staticcheck //ignore SA1019 - WithEthereumVersion(config.EthereumVersion_Eth2_Legacy). + WithCustomDockerImages(map[config.ContainerType]string{config.ContainerType_ExecutionLayer: "nethermind/nethermind:1.26.0"}). WithConsensusLayer(config.ConsensusLayer_Prysm). - WithExecutionLayer(config.ExecutionLayer_Nethermind). + WithExecutionLayer(config_types.ExecutionLayer_Nethermind). Build() require.NoError(t, err, "Builder validation failed") @@ -84,3 +85,38 @@ func TestNethermindEth2(t *testing.T) { err = sendAndCompareBalances(ctx, clientTwo, address) require.NoError(t, err, fmt.Sprintf("balance wasn't correctly updated for %s network", eip1559Network.Name)) } + +func TestNethermindEth2_Shenghai(t *testing.T) { + l := logging.GetTestLogger(t) + + chainConfig := config.MustGetDefaultChainConfig() + chainConfig.HardForkEpochs = map[string]int{"Deneb": 500} + + builder := NewEthereumNetworkBuilder() + cfg, err := builder. + WithCustomDockerImages(map[config.ContainerType]string{config.ContainerType_ExecutionLayer: "nethermind/nethermind:1.25.4"}). + WithConsensusLayer(config.ConsensusLayer_Prysm). + WithExecutionLayer(config_types.ExecutionLayer_Nethermind). + WithEthereumChainConfig(chainConfig). + Build() + require.NoError(t, err, "Builder validation failed") + + _, eth2, err := cfg.Start() + require.NoError(t, err, "Couldn't start PoS network") + + nonEip1559Network := blockchain.SimulatedEVMNetwork + nonEip1559Network.Name = "Simulated Nethermind + Prysm (non-EIP 1559)" + nonEip1559Network.URLs = eth2.PublicWsUrls() + clientOne, err := blockchain.ConnectEVMClient(nonEip1559Network, l) + require.NoError(t, err, "Couldn't connect to the evm client") + + t.Cleanup(func() { + err = clientOne.Close() + require.NoError(t, err, "Couldn't close the client") + }) + + ctx := testcontext.Get(t) + address := common.HexToAddress("0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1") + err = sendAndCompareBalances(ctx, clientOne, address) + require.NoError(t, err, fmt.Sprintf("balance wasn't correctly updated for %s network", nonEip1559Network.Name)) +} diff --git a/docker/test_env/prysm.go b/docker/test_env/prysm.go index 4d6f38e77..acacb1083 100644 --- a/docker/test_env/prysm.go +++ b/docker/test_env/prysm.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/docker" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/mirror" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" @@ -23,26 +24,37 @@ import ( const ( PRYSM_QUERY_RPC_PORT = "3500" PRYSM_NODE_RPC_PORT = "4000" - - defaultPrysmBeaconChainImage = "gcr.io/prysmaticlabs/prysm/beacon-chain:v5.0.4" - defaultPyrsmValidatorImage = "gcr.io/prysmaticlabs/prysm/validator:v5.0.4" ) +var beaconForkToImageMap = map[ethereum.Fork]string{ + ethereum.EthereumFork_Shanghai: "gcr.io/prysmaticlabs/prysm/beacon-chain:v4.1.1", + ethereum.EthereumFork_Deneb: "gcr.io/prysmaticlabs/prysm/beacon-chain:v5.0.4", +} + +var validatorForkToImageMap = map[ethereum.Fork]string{ + ethereum.EthereumFork_Shanghai: "gcr.io/prysmaticlabs/prysm/validator:v4.1.1", + ethereum.EthereumFork_Deneb: "gcr.io/prysmaticlabs/prysm/validator:v5.0.4", +} + type PrysmBeaconChain struct { EnvComponent InternalBeaconRpcProvider string InternalQueryRpcUrl string ExternalBeaconRpcProvider string ExternalQueryRpcUrl string - generatedDataHostDir string gethInternalExecutionURL string chainConfig *config.EthereumChainConfig l zerolog.Logger t *testing.T + posContainerSettings } -func NewPrysmBeaconChain(networks []string, chainConfig *config.EthereumChainConfig, customConfigDataDir, gethExecutionURL string, opts ...EnvComponentOption) (*PrysmBeaconChain, error) { - parts := strings.Split(defaultPrysmBeaconChainImage, ":") +func NewPrysmBeaconChain(networks []string, chainConfig *config.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir, gethExecutionURL string, baseEthereumFork ethereum.Fork, opts ...EnvComponentOption) (*PrysmBeaconChain, error) { + prysmBeaconChainImage, ok := beaconForkToImageMap[baseEthereumFork] + if !ok { + return nil, fmt.Errorf("unknown fork: %s", baseEthereumFork) + } + parts := strings.Split(prysmBeaconChainImage, ":") g := &PrysmBeaconChain{ EnvComponent: EnvComponent{ ContainerName: fmt.Sprintf("%s-%s", "prysm-beacon-chain", uuid.NewString()[0:8]), @@ -52,7 +64,7 @@ func NewPrysmBeaconChain(networks []string, chainConfig *config.EthereumChainCon StartupTimeout: 2 * time.Minute, }, chainConfig: chainConfig, - generatedDataHostDir: customConfigDataDir, + posContainerSettings: posContainerSettings{generatedDataHostDir: generatedDataHostDir, generatedDataContainerDir: generatedDataContainerDir}, gethInternalExecutionURL: gethExecutionURL, l: logging.GetTestLogger(nil), } @@ -115,7 +127,7 @@ func (g *PrysmBeaconChain) StartContainer() error { } func (g *PrysmBeaconChain) getContainerRequest(networks []string) (*tc.ContainerRequest, error) { - timeout := g.chainConfig.GetDefaultWaitDuration() + timeout := g.chainConfig.DefaultWaitDuration() if g.StartupTimeout < timeout { timeout = g.StartupTimeout } @@ -133,15 +145,15 @@ func (g *PrysmBeaconChain) getContainerRequest(networks []string) (*tc.Container Cmd: []string{ "--accept-terms-of-use", "--datadir=/consensus-data", - fmt.Sprintf("--chain-config-file=%s/config.yaml", GENERATED_DATA_DIR_INSIDE_CONTAINER), - fmt.Sprintf("--genesis-state=%s/genesis.ssz", GENERATED_DATA_DIR_INSIDE_CONTAINER), + fmt.Sprintf("--chain-config-file=%s/config.yaml", g.generatedDataContainerDir), + fmt.Sprintf("--genesis-state=%s/genesis.ssz", g.generatedDataContainerDir), fmt.Sprintf("--execution-endpoint=%s", g.gethInternalExecutionURL), "--rpc-host=0.0.0.0", "--grpc-gateway-host=0.0.0.0", "--grpc-gateway-corsdomain=*", "--suggested-fee-recipient=0x8943545177806ED17B9F23F0a21ee5948eCaa776", "--subscribe-all-subnets=true", - fmt.Sprintf("--jwt-secret=%s", JWT_SECRET_FILE_LOCATION_INSIDE_CONTAINER), + fmt.Sprintf("--jwt-secret=%s", getJWTSecretFileLocationInsideContainer(g.generatedDataContainerDir)), // mine, modify when running multi-node "--minimum-peers-per-subnet=0", "--min-sync-peers=0", @@ -152,7 +164,7 @@ func (g *PrysmBeaconChain) getContainerRequest(networks []string) (*tc.Container hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{ Type: mount.TypeBind, Source: g.generatedDataHostDir, - Target: GENERATED_DATA_DIR_INSIDE_CONTAINER, + Target: g.generatedDataContainerDir, ReadOnly: false, }) }, @@ -170,13 +182,17 @@ type PrysmValidator struct { chainConfig *config.EthereumChainConfig internalBeaconRpcProvider string valKeysDir string - generatedDataHostDir string l zerolog.Logger t *testing.T + posContainerSettings } -func NewPrysmValidator(networks []string, chainConfig *config.EthereumChainConfig, generatedDataHostDir, valKeysDir, internalBeaconRpcProvider string, opts ...EnvComponentOption) (*PrysmValidator, error) { - parts := strings.Split(defaultPyrsmValidatorImage, ":") +func NewPrysmValidator(networks []string, chainConfig *config.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir, valKeysDir, internalBeaconRpcProvider string, baseEthereumFork ethereum.Fork, opts ...EnvComponentOption) (*PrysmValidator, error) { + pyrsmValidatorImage, ok := validatorForkToImageMap[baseEthereumFork] + if !ok { + return nil, fmt.Errorf("unknown fork: %s", baseEthereumFork) + } + parts := strings.Split(pyrsmValidatorImage, ":") g := &PrysmValidator{ EnvComponent: EnvComponent{ ContainerName: fmt.Sprintf("%s-%s", "prysm-validator", uuid.NewString()[0:8]), @@ -185,7 +201,7 @@ func NewPrysmValidator(networks []string, chainConfig *config.EthereumChainConfi ContainerVersion: parts[1], }, chainConfig: chainConfig, - generatedDataHostDir: generatedDataHostDir, + posContainerSettings: posContainerSettings{generatedDataHostDir: generatedDataHostDir, generatedDataContainerDir: generatedDataContainerDir}, valKeysDir: valKeysDir, internalBeaconRpcProvider: internalBeaconRpcProvider, l: logging.GetTestLogger(nil), @@ -238,17 +254,17 @@ func (g *PrysmValidator) getContainerRequest(networks []string) (*tc.ContainerRe ImagePlatform: "linux/x86_64", WaitingFor: tcwait.ForAll( tcwait.ForLog("Beacon chain started"). - WithStartupTimeout(g.chainConfig.GetDefaultWaitDuration()). + WithStartupTimeout(g.chainConfig.DefaultWaitDuration()). WithPollInterval(2 * time.Second), ), Cmd: []string{ "--accept-terms-of-use", - fmt.Sprintf("--chain-config-file=%s/config.yaml", GENERATED_DATA_DIR_INSIDE_CONTAINER), + fmt.Sprintf("--chain-config-file=%s/config.yaml", g.generatedDataContainerDir), fmt.Sprintf("--beacon-rpc-provider=%s", g.internalBeaconRpcProvider), "--datadir=/consensus-data", "--suggested-fee-recipient=0x8943545177806ED17B9F23F0a21ee5948eCaa776", fmt.Sprintf("--wallet-dir=%s/prysm", NODE_0_DIR_INSIDE_CONTAINER), - fmt.Sprintf("--wallet-password-file=%s", VALIDATOR_WALLET_PASSWORD_FILE_INSIDE_CONTAINER), + fmt.Sprintf("--wallet-password-file=%s", getValidatorWalletPasswordFileInsideContainer(g.generatedDataContainerDir)), }, HostConfigModifier: func(hostConfig *container.HostConfig) { hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{ @@ -259,7 +275,7 @@ func (g *PrysmValidator) getContainerRequest(networks []string) (*tc.ContainerRe }, mount.Mount{ Type: mount.TypeBind, Source: g.generatedDataHostDir, - Target: GENERATED_DATA_DIR_INSIDE_CONTAINER, + Target: g.generatedDataContainerDir, ReadOnly: false, }) }, diff --git a/docker/test_env/reth_base.go b/docker/test_env/reth_base.go index 4570316a5..15ab87feb 100644 --- a/docker/test_env/reth_base.go +++ b/docker/test_env/reth_base.go @@ -7,6 +7,8 @@ import ( "testing" "time" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/rs/zerolog" tc "github.com/testcontainers/testcontainers-go" @@ -19,12 +21,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" ) -const ( - defaultRethEth2Image = "ghcr.io/paradigmxyz/reth:v1.0.0" - rethBaseImageName = "ghcr.io/paradigmxyz/reth" - rethGitRepo = "paradigmxyz/reth" -) - type Reth struct { EnvComponent ExternalHttpUrl string @@ -33,12 +29,12 @@ type Reth struct { InternalWsUrl string InternalExecutionURL string ExternalExecutionURL string - generatedDataHostDir string chainConfig *config.EthereumChainConfig consensusLayer config.ConsensusLayer - ethereumVersion config.EthereumVersion + ethereumVersion config_types.EthereumVersion l zerolog.Logger t *testing.T + posContainerSettings } func (g *Reth) WithTestInstance(t *testing.T) ExecutionClient { @@ -48,7 +44,7 @@ func (g *Reth) WithTestInstance(t *testing.T) ExecutionClient { } func (g *Reth) StartContainer() (blockchain.EVMNetwork, error) { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { return blockchain.EVMNetwork{}, errors.New(config.Eth1NotSupportedByRethMsg) } @@ -83,7 +79,7 @@ func (g *Reth) StartContainer() (blockchain.EVMNetwork, error) { return blockchain.EVMNetwork{}, err } - if g.GetEthereumVersion() == config.EthereumVersion_Eth2 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth2 { executionPort, err := ct.MappedPort(testcontext.Get(g.t), NatPort(ETH2_EXECUTION_PORT)) if err != nil { return blockchain.EVMNetwork{}, err @@ -99,7 +95,7 @@ func (g *Reth) StartContainer() (blockchain.EVMNetwork, error) { g.InternalWsUrl = FormatWsUrl(g.ContainerName, DEFAULT_EVM_NODE_WS_PORT) networkConfig := blockchain.SimulatedEVMNetwork - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { networkConfig.Name = fmt.Sprintf("Private Eth-1-PoW [reth %s]", g.ContainerVersion) } else { networkConfig.Name = fmt.Sprintf("Private Eth-2-PoS [reth %s] + %s", g.ContainerVersion, g.consensusLayer) @@ -115,14 +111,14 @@ func (g *Reth) StartContainer() (blockchain.EVMNetwork, error) { } func (g *Reth) GetInternalExecutionURL() string { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { panic("eth1 node doesn't have an execution URL") } return g.InternalExecutionURL } func (g *Reth) GetExternalExecutionURL() string { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { panic("eth1 node doesn't have an execution URL") } return g.ExternalExecutionURL @@ -152,12 +148,12 @@ func (g *Reth) GetContainer() *tc.Container { return &g.Container } -func (g *Reth) GetEthereumVersion() config.EthereumVersion { +func (g *Reth) GetEthereumVersion() config_types.EthereumVersion { return g.ethereumVersion } func (g *Reth) WaitUntilChainIsReady(ctx context.Context, waitTime time.Duration) error { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { return nil } waitForFirstBlock := tcwait.NewLogStrategy("Block added to canonical chain").WithPollInterval(1 * time.Second).WithStartupTimeout(waitTime) @@ -165,7 +161,7 @@ func (g *Reth) WaitUntilChainIsReady(ctx context.Context, waitTime time.Duration } func (g *Reth) GethConsensusMechanism() ConsensusMechanism { - if g.GetEthereumVersion() == config.EthereumVersion_Eth1 { + if g.GetEthereumVersion() == config_types.EthereumVersion_Eth1 { return ConsensusMechanism_PoW } return ConsensusMechanism_PoS diff --git a/docker/test_env/reth_eth2.go b/docker/test_env/reth_eth2.go index 8e9f29a66..7ed048802 100644 --- a/docker/test_env/reth_eth2.go +++ b/docker/test_env/reth_eth2.go @@ -8,6 +8,8 @@ import ( "strings" "time" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/mount" "github.com/google/uuid" @@ -15,13 +17,14 @@ import ( tcwait "github.com/testcontainers/testcontainers-go/wait" "github.com/smartcontractkit/chainlink-testing-framework/config" + "github.com/smartcontractkit/chainlink-testing-framework/docker/ethereum" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/mirror" ) // NewRethEth2 starts a new Reth Eth2 node running in Docker -func NewRethEth2(networks []string, chainConfig *config.EthereumChainConfig, generatedDataHostDir string, consensusLayer config.ConsensusLayer, opts ...EnvComponentOption) (*Reth, error) { - parts := strings.Split(defaultRethEth2Image, ":") +func NewRethEth2(networks []string, chainConfig *config.EthereumChainConfig, generatedDataHostDir, generatedDataContainerDir string, consensusLayer config.ConsensusLayer, opts ...EnvComponentOption) (*Reth, error) { + parts := strings.Split(ethereum.DefaultRethEth2Image, ":") g := &Reth{ EnvComponent: EnvComponent{ ContainerName: fmt.Sprintf("%s-%s", "reth-eth2", uuid.NewString()[0:8]), @@ -32,10 +35,10 @@ func NewRethEth2(networks []string, chainConfig *config.EthereumChainConfig, gen StartupTimeout: 120 * time.Second, }, chainConfig: chainConfig, - generatedDataHostDir: generatedDataHostDir, + posContainerSettings: posContainerSettings{generatedDataHostDir: generatedDataHostDir, generatedDataContainerDir: generatedDataContainerDir}, consensusLayer: consensusLayer, l: logging.GetTestLogger(nil), - ethereumVersion: config.EthereumVersion_Eth2, + ethereumVersion: config_types.EthereumVersion_Eth2, } g.SetDefaultHooks() for _, opt := range opts { @@ -94,7 +97,7 @@ func (g *Reth) getEth2ContainerRequest() (*tc.ContainerRequest, error) { hostConfig.Mounts = append(hostConfig.Mounts, mount.Mount{ Type: mount.TypeBind, Source: g.generatedDataHostDir, - Target: GENERATED_DATA_DIR_INSIDE_CONTAINER, + Target: g.generatedDataContainerDir, ReadOnly: false, }) }, @@ -152,8 +155,8 @@ func (g *Reth) buildPosInitScript() (string, error) { HttpPort: DEFAULT_EVM_NODE_HTTP_PORT, WsPort: DEFAULT_EVM_NODE_WS_PORT, ChainID: g.chainConfig.ChainID, - GeneratedDataDir: GENERATED_DATA_DIR_INSIDE_CONTAINER, - JwtFileLocation: JWT_SECRET_FILE_LOCATION_INSIDE_CONTAINER, + GeneratedDataDir: g.generatedDataContainerDir, + JwtFileLocation: getJWTSecretFileLocationInsideContainer(g.generatedDataContainerDir), ExecutionDir: "/root/.local", LogLevel: g.LogLevel, } diff --git a/docker/test_env/reth_test.go b/docker/test_env/reth_test.go index fbccd0ccc..e96ebcbaf 100644 --- a/docker/test_env/reth_test.go +++ b/docker/test_env/reth_test.go @@ -4,6 +4,8 @@ import ( "fmt" "testing" + config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" @@ -16,8 +18,8 @@ import ( func TestRethEth1(t *testing.T) { builder := NewEthereumNetworkBuilder() _, err := builder. - WithEthereumVersion(config.EthereumVersion_Eth1). - WithExecutionLayer(config.ExecutionLayer_Reth). + WithEthereumVersion(config_types.EthereumVersion_Eth1). + WithExecutionLayer(config_types.ExecutionLayer_Reth). Build() require.Error(t, err, "Builder validation failed") require.Contains(t, err.Error(), config.Eth1NotSupportedByRethMsg) @@ -28,8 +30,8 @@ func TestRethEth2(t *testing.T) { builder := NewEthereumNetworkBuilder() cfg, err := builder. - WithEthereumVersion(config.EthereumVersion_Eth2). - WithExecutionLayer(config.ExecutionLayer_Reth). + WithEthereumVersion(config_types.EthereumVersion_Eth2). + WithExecutionLayer(config_types.ExecutionLayer_Reth). Build() require.NoError(t, err, "Builder validation failed") diff --git a/docker/test_env/utils.go b/docker/test_env/utils.go index 713aad76f..c646c9ba4 100644 --- a/docker/test_env/utils.go +++ b/docker/test_env/utils.go @@ -3,14 +3,10 @@ package test_env import ( "context" "fmt" - "regexp" - "strconv" "strings" "github.com/docker/go-connections/nat" tc "github.com/testcontainers/testcontainers-go" - - "github.com/smartcontractkit/chainlink-testing-framework/config" ) func NatPortFormat(port string) string { @@ -53,115 +49,6 @@ func FormatWsUrl(host string, port string) string { return fmt.Sprintf("ws://%s:%s", host, port) } -// GetEthereumVersionFromImage returns the consensus type based on the Docker image version -func GetEthereumVersionFromImage(executionLayer config.ExecutionLayer, imageWithVersion string) (config.EthereumVersion, error) { - version, err := GetComparableVersionFromDockerImage(imageWithVersion) - if err != nil { - return "", fmt.Errorf("failed to parse docker image and extract version: %s", imageWithVersion) - } - switch executionLayer { - case config.ExecutionLayer_Geth: - if version < 113 { - return config.EthereumVersion_Eth1, nil - } else { - return config.EthereumVersion_Eth2, nil - } - case config.ExecutionLayer_Besu: - if version < 231 { - return config.EthereumVersion_Eth1, nil - } else { - return config.EthereumVersion_Eth2, nil - } - case config.ExecutionLayer_Erigon: - if version < 241 { - return config.EthereumVersion_Eth1, nil - } else { - return config.EthereumVersion_Eth2, nil - } - case config.ExecutionLayer_Nethermind: - if version < 117 { - return config.EthereumVersion_Eth1, nil - } else { - return config.EthereumVersion_Eth2, nil - } - case config.ExecutionLayer_Reth: - return config.EthereumVersion_Eth2, nil - } - - return "", fmt.Errorf(MsgUnsupportedExecutionLayer, executionLayer) -} - -// GetComparableVersionFromDockerImage returns version in xy format removing all non-numeric characters -// and patch version if present. So x.y.z becomes xy. -func GetComparableVersionFromDockerImage(imageWithVersion string) (int, error) { - parts := strings.Split(imageWithVersion, ":") - if len(parts) != 2 { - return -1, fmt.Errorf(MsgInvalidDockerImageFormat, imageWithVersion) - } - - re := regexp.MustCompile("[a-zA-Z]") - cleanedVersion := re.ReplaceAllString(parts[1], "") - if idx := strings.Index(cleanedVersion, "-"); idx != -1 { - cleanedVersion = string(cleanedVersion[:idx]) - } - // remove patch version if present - if count := strings.Count(cleanedVersion, "."); count > 1 { - cleanedVersion = string(cleanedVersion[:strings.LastIndex(cleanedVersion, ".")]) - } - version, err := strconv.Atoi(strings.Replace(cleanedVersion, ".", "", -1)) - if err != nil { - return -1, fmt.Errorf("failed to parse docker version to an integer: %s", cleanedVersion) - } - - return version, nil -} - -// GetGithubRepositoryFromEthereumClientDockerImage returns the GitHub repository name based on the Docker image -func GetGithubRepositoryFromEthereumClientDockerImage(imageWithVersion string) (string, error) { - parts := strings.Split(imageWithVersion, ":") - if len(parts) != 2 { - return "", fmt.Errorf(MsgInvalidDockerImageFormat, imageWithVersion) - } - - switch { - case strings.Contains(parts[0], gethBaseImageName): - return gethGitRepo, nil - case strings.Contains(parts[0], besuBaseImageName): - return besuGitRepo, nil - case strings.Contains(parts[0], nethermindBaseImageName): - return nethermindGitRepo, nil - case strings.Contains(parts[0], erigonBaseImageName): - return erigonGitRepo, nil - case strings.Contains(parts[0], rethBaseImageName): - return rethGitRepo, nil - default: - return "", fmt.Errorf(MsgUnsupportedDockerImage, parts[0]) - } -} - -// GetExecutionLayerFromDockerImage returns the execution layer based on the Docker image -func GetExecutionLayerFromDockerImage(imageWithVersion string) (config.ExecutionLayer, error) { - parts := strings.Split(imageWithVersion, ":") - if len(parts) != 2 { - return "", fmt.Errorf(MsgInvalidDockerImageFormat, imageWithVersion) - } - - switch { - case strings.Contains(parts[0], gethBaseImageName): - return config.ExecutionLayer_Geth, nil - case strings.Contains(parts[0], besuBaseImageName): - return config.ExecutionLayer_Besu, nil - case strings.Contains(parts[0], nethermindBaseImageName): - return config.ExecutionLayer_Nethermind, nil - case strings.Contains(parts[0], erigonBaseImageName): - return config.ExecutionLayer_Erigon, nil - case strings.Contains(parts[0], rethBaseImageName): - return config.ExecutionLayer_Reth, nil - default: - return "", fmt.Errorf(MsgUnsupportedDockerImage, parts[0]) - } -} - // UniqueStringSlice returns a deduplicated slice of strings func UniqueStringSlice(slice []string) []string { stringSet := make(map[string]struct{}) diff --git a/go.mod b/go.mod index 645c1dbe1..39693844c 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.22.5 require ( dario.cat/mergo v1.0.0 + github.com/Masterminds/semver/v3 v3.2.1 github.com/avast/retry-go v3.0.0+incompatible github.com/aws/constructs-go/constructs/v10 v10.1.255 github.com/aws/jsii-runtime-go v1.75.0 @@ -59,7 +60,6 @@ require ( github.com/K-Phoen/sdk v0.12.2 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect @@ -286,7 +286,7 @@ require ( golang.org/x/arch v0.4.0 // indirect golang.org/x/crypto v0.17.0 // indirect golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect - golang.org/x/mod v0.14.0 // indirect + golang.org/x/mod v0.19.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/term v0.15.0 // indirect golang.org/x/time v0.3.0 // indirect diff --git a/go.sum b/go.sum index bc225bbf1..6f326b2fe 100644 --- a/go.sum +++ b/go.sum @@ -1241,8 +1241,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/utils/docker/docker.go b/utils/docker/docker.go new file mode 100644 index 000000000..971f54744 --- /dev/null +++ b/utils/docker/docker.go @@ -0,0 +1,25 @@ +package docker + +import ( + "fmt" + "strings" + + "github.com/Masterminds/semver/v3" +) + +const MsgInvalidDockerImageFormat = "invalid docker image format: %s" + +// GetSemverFromImage returns a semver version from a docker image string +func GetSemverFromImage(imageWithVersion string) (*semver.Version, error) { + parts := strings.Split(imageWithVersion, ":") + if len(parts) != 2 { + return nil, fmt.Errorf(MsgInvalidDockerImageFormat, imageWithVersion) + } + + parsedVersion, err := semver.NewVersion(parts[1]) + if err != nil { + return nil, fmt.Errorf("failed to parse docker version to a semver: %s", parts[1]) + } + + return parsedVersion, nil +} From 058375630a9a33d6f7dd8ddf8881b0c87ec3be46 Mon Sep 17 00:00:00 2001 From: Lukasz <120112546+lukaszcl@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:56:56 +0200 Subject: [PATCH 14/26] Add ReadEnvVarSlice_String to read config values (#1039) --- config/env.go | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/config/env.go b/config/env.go index 70ba314d9..9802e8989 100644 --- a/config/env.go +++ b/config/env.go @@ -54,8 +54,33 @@ func MustReadEnvVar_Boolean(name string) *bool { return ptr.Ptr(value.(bool)) } +// ReadEnvVarSlice_String reads all environment variables matching the specified pattern and returns a slice of strings. +func ReadEnvVarSlice_String(pattern string) []string { + re := regexp.MustCompile(pattern) + var values []string + + for _, env := range os.Environ() { + pair := strings.SplitN(env, "=", 2) + if len(pair) != 2 { + continue + } + key, value := pair[0], pair[1] + if re.MatchString(key) && value != "" { + values = append(values, value) + } + } + return values +} + +// ReadEnvVarGroupedMap combines environment variables into a map where keys map to slices of strings. +// It accepts `singleEnvPattern` for single variables and `groupEnvPattern` for grouped variables. +// Returns a map combining values from both patterns, with single values wrapped in slices. func ReadEnvVarGroupedMap(singleEnvPattern, groupEnvPattern string) map[string][]string { - return mergeMaps(readEnvVarSingleMap(singleEnvPattern), readEnvVarGroupedMap(groupEnvPattern)) + var singleMap map[string]string + if singleEnvPattern != "" { + singleMap = readEnvVarSingleMap(singleEnvPattern) + } + return mergeMaps(singleMap, readEnvVarGroupedMap(groupEnvPattern)) } // readEnvVarValue reads an environment variable and returns the value parsed according to the specified type. From d3b174f4ff73cb073a69fb77e82615e6a0531fa6 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Tue, 6 Aug 2024 15:28:07 +0200 Subject: [PATCH 15/26] [TT-1262] add method to execute pg_dump inside Postgres container (#1038) --- docker/test_env/postgres.go | 41 ++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/docker/test_env/postgres.go b/docker/test_env/postgres.go index 55792fde5..dc2fb2b87 100644 --- a/docker/test_env/postgres.go +++ b/docker/test_env/postgres.go @@ -1,6 +1,7 @@ package test_env import ( + "context" "fmt" "io" "net/url" @@ -11,9 +12,11 @@ import ( "github.com/docker/go-connections/nat" "github.com/google/uuid" + "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/rs/zerolog/log" tc "github.com/testcontainers/testcontainers-go" + tcexec "github.com/testcontainers/testcontainers-go/exec" tcwait "github.com/testcontainers/testcontainers-go/wait" "github.com/smartcontractkit/chainlink-testing-framework/docker" @@ -176,7 +179,9 @@ func (pg *PostgresDb) startOrRestartContainer(withReuse bool) error { return nil } -func (pg *PostgresDb) ExecPgDump(stdout io.Writer) error { +// ExecPgDumpFromLocal executes pg_dump from local machine by connecting to external Postgres port. For it to work pg_dump +// needs to be installed on local machine. +func (pg *PostgresDb) ExecPgDumpFromLocal(stdout io.Writer) error { cmd := exec.Command("pg_dump", "-U", pg.User, "-h", "127.0.0.1", "-p", pg.ExternalPort, pg.DbName) //nolint:gosec cmd.Env = []string{ fmt.Sprintf("PGPASSWORD=%s", pg.Password), @@ -186,6 +191,40 @@ func (pg *PostgresDb) ExecPgDump(stdout io.Writer) error { return cmd.Run() } +// ExecPgDumpFromContainer executed pg_dump from inside the container. It dumps it to temporary file inside the container +// and then writes to the writer. +func (pg *PostgresDb) ExecPgDumpFromContainer(writer io.Writer) error { + tmpFile := "/tmp/db_dump.sql" + command := []string{"pg_dump", "-U", pg.User, "-f", tmpFile, pg.DbName} + env := []string{ + fmt.Sprintf("PGPASSWORD=%s", pg.Password), + } + + ctx, cancelFn := context.WithTimeout(context.Background(), 10*time.Minute) + + _, _, err := pg.Container.Exec(ctx, command, tcexec.WithEnv(env)) + if err != nil { + cancelFn() + return errors.Wrap(err, "Failed to execute pg_dump") + } + + reader, err := pg.Container.CopyFileFromContainer(ctx, tmpFile) + if err != nil { + cancelFn() + return errors.Wrapf(err, "Failed to open for reading %s temporary file with db dump", tmpFile) + } + + _, err = io.Copy(writer, reader) + if err != nil { + cancelFn() + return errors.Wrapf(err, "Failed to send data from %s temporary file with db dump", tmpFile) + } + + cancelFn() + + return nil +} + func (pg *PostgresDb) getContainerRequest() *tc.ContainerRequest { return &tc.ContainerRequest{ Name: pg.ContainerName, From 0495475440e543c21da1dfdf4ecec706184cedc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ot=C3=A1vio=20Migliavacca=20Madalosso?= Date: Wed, 7 Aug 2024 10:28:06 -0300 Subject: [PATCH 16/26] Documentation ghsecrets improvement (#1049) --- tools/ghsecrets/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ghsecrets/README.md b/tools/ghsecrets/README.md index b8b1e0e0b..cb7c1b533 100644 --- a/tools/ghsecrets/README.md +++ b/tools/ghsecrets/README.md @@ -38,7 +38,7 @@ This error typically means that the directory where Go installs its binaries is This command will print the path where Go binaries are installed, typically something like /home/username/go/bin -- Add the following line at the end of the file: +- Add the following line at the end of your shell config file (`.bashrc`, `.zshrc`), usually located at `~/`: ```sh export PATH="$PATH:" From abcc417d7336a80a32ba395848626cefcb724b49 Mon Sep 17 00:00:00 2001 From: Lukasz <120112546+lukaszcl@users.noreply.github.com> Date: Fri, 9 Aug 2024 13:33:25 +0200 Subject: [PATCH 17/26] Add citool to manage e2e tests on Github CI (#1051) --- .github/workflows/release-tools.yaml | 1 + tools/citool/Makefile | 5 + tools/citool/README.md | 15 + tools/citool/cmd/check_tests_cmd.go | 166 ++++ tools/citool/cmd/check_tests_cmd_test.go | 47 ++ tools/citool/cmd/create_test_config_cmd.go | 179 +++++ tools/citool/cmd/csv_export_cmd.go | 96 +++ tools/citool/cmd/filter_cmd.go | 165 ++++ tools/citool/cmd/filter_cmd_test.go | 64 ++ tools/citool/cmd/root_cmd.go | 32 + tools/citool/cmd/test_config_cmd.go | 123 +++ tools/citool/cmd/test_config_cmd_test.go | 75 ++ tools/citool/cmd/types.go | 26 + tools/citool/go.mod | 198 +++++ tools/citool/go.sum | 874 +++++++++++++++++++++ tools/citool/main.go | 9 + tools/citool/package.json | 5 + 17 files changed, 2080 insertions(+) create mode 100644 tools/citool/Makefile create mode 100644 tools/citool/README.md create mode 100644 tools/citool/cmd/check_tests_cmd.go create mode 100644 tools/citool/cmd/check_tests_cmd_test.go create mode 100644 tools/citool/cmd/create_test_config_cmd.go create mode 100644 tools/citool/cmd/csv_export_cmd.go create mode 100644 tools/citool/cmd/filter_cmd.go create mode 100644 tools/citool/cmd/filter_cmd_test.go create mode 100644 tools/citool/cmd/root_cmd.go create mode 100644 tools/citool/cmd/test_config_cmd.go create mode 100644 tools/citool/cmd/test_config_cmd_test.go create mode 100644 tools/citool/cmd/types.go create mode 100644 tools/citool/go.mod create mode 100644 tools/citool/go.sum create mode 100644 tools/citool/main.go create mode 100644 tools/citool/package.json diff --git a/.github/workflows/release-tools.yaml b/.github/workflows/release-tools.yaml index 7bf1101fa..9a2580048 100644 --- a/.github/workflows/release-tools.yaml +++ b/.github/workflows/release-tools.yaml @@ -10,6 +10,7 @@ jobs: matrix: tool: [ + tools/citool, tools/envresolve, tools/gotestloghelper, tools/testlistgenerator, diff --git a/tools/citool/Makefile b/tools/citool/Makefile new file mode 100644 index 000000000..a01538a70 --- /dev/null +++ b/tools/citool/Makefile @@ -0,0 +1,5 @@ +lint: + golangci-lint --color=always run ./... --fix -v + +test_unit: + go test -timeout 5m -json -cover -covermode=count -coverprofile=unit-test-coverage.out ./... 2>&1 | tee /tmp/gotest.log diff --git a/tools/citool/README.md b/tools/citool/README.md new file mode 100644 index 000000000..dfbf49d4a --- /dev/null +++ b/tools/citool/README.md @@ -0,0 +1,15 @@ +# A tool to manage E2E tests on Github CI + +Available Commands: +check-tests Check if all tests in a directory are included in the test configurations YAML file +completion Generate the autocompletion script for the specified shell +csvexport Export tests to CSV format +filter Filter test configurations based on specified criteria +help Help about any command +test-config Manage test config + +## Usage + +```bash +go run main.go +``` diff --git a/tools/citool/cmd/check_tests_cmd.go b/tools/citool/cmd/check_tests_cmd.go new file mode 100644 index 000000000..3ef3712a5 --- /dev/null +++ b/tools/citool/cmd/check_tests_cmd.go @@ -0,0 +1,166 @@ +package cmd + +import ( + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/spf13/cobra" + "gopkg.in/yaml.v3" +) + +type JobConfig struct { + Jobs map[string]struct { + Strategy struct { + Matrix struct { + Test []struct { + Path string `yaml:"path"` + TestOpts string `yaml:"testOpts"` + } `yaml:"test"` + } `yaml:"matrix"` + } `yaml:"strategy"` + } `yaml:"jobs"` +} + +var checkTestsCmd = &cobra.Command{ + Use: "check-tests [directory] [yaml file]", + Short: "Check if all tests in a directory are included in the test configurations YAML file", + Args: cobra.ExactArgs(2), + Run: func(_ *cobra.Command, args []string) { + directory := args[0] + yamlFile := args[1] + excludedDirs := []string{"../../citool"} + tests, err := extractTests(directory, excludedDirs) + if err != nil { + fmt.Println("Error extracting tests:", err) + os.Exit(1) + } + + checkTestsInPipeline(yamlFile, tests) + }, +} + +// extractTests scans the given directory and subdirectories (except the excluded ones) +// for Go test files, extracts test function names, and returns a slice of Test. +func extractTests(dir string, excludeDirs []string) ([]Test, error) { + var tests []Test + + // Resolve to absolute path + absDir, err := filepath.Abs(dir) + if err != nil { + return nil, err + } + + // filepath.WalkDir provides more control and is more efficient for skipping directories + err = filepath.WalkDir(absDir, func(path string, d os.DirEntry, err error) error { + if err != nil { + return err + } + + // Check if the current path is one of the excluded directories + for _, exclude := range excludeDirs { + absExclude, _ := filepath.Abs(exclude) + if strings.HasPrefix(path, absExclude) { + if d.IsDir() { + return filepath.SkipDir // Skip this directory + } + return nil // Skip this file + } + } + + if !d.IsDir() && strings.HasSuffix(d.Name(), "_test.go") { + content, err := os.ReadFile(path) + if err != nil { + return err + } + re := regexp.MustCompile(`func (Test\w+)`) + matches := re.FindAllSubmatch(content, -1) + for _, match := range matches { + funcName := string(match[1]) + if funcName == "TestMain" { // Skip "TestMain" + continue + } + tests = append(tests, Test{ + Name: funcName, + Path: mustExtractSubpath(path, "integration-tests"), + }) + } + } + return nil + }) + + return tests, err +} + +// ExtractSubpath extracts a specific subpath from a given full path. +// If the subpath is not found, it returns an error. +func mustExtractSubpath(fullPath, subPath string) string { + index := strings.Index(fullPath, subPath) + if index == -1 { + panic("subpath not found in the provided full path") + } + return fullPath[index:] +} + +func checkTestsInPipeline(yamlFile string, tests []Test) { + data, err := os.ReadFile(yamlFile) + if err != nil { + fmt.Printf("Error reading YAML file: %s\n", err) + return + } + + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + fmt.Printf("Error parsing YAML: %s\n", err) + return + } + + missingTests := []string{} // Track missing tests + + for _, test := range tests { + found := false + for _, item := range config.Tests { + if item.Path == test.Path { + if strings.Contains(item.TestCmd, "-test.run") { + if matchTestNameInCmd(item.TestCmd, test.Name) { + found = true + break + } + } else { + found = true + break + } + } + } + if !found { + missingTests = append(missingTests, fmt.Sprintf("ERROR: Test '%s' in file '%s' does not have CI configuration in '%s'", test.Name, test.Path, yamlFile)) + } + } + + if len(missingTests) > 0 { + for _, missing := range missingTests { + fmt.Println(missing) + } + os.Exit(1) // Exit with a failure status + } +} + +// matchTestNameInCmd checks if the given test name matches the -test.run pattern in the command string. +func matchTestNameInCmd(cmd string, testName string) bool { + testRunRegex := regexp.MustCompile(`-test\.run ([^\s]+)`) + matches := testRunRegex.FindStringSubmatch(cmd) + if len(matches) > 1 { + // Extract the regex pattern used in the -test.run command + pattern := matches[1] + + // Escape regex metacharacters in the testName before matching + escapedTestName := regexp.QuoteMeta(testName) + + // Check if the escaped test name matches the extracted pattern + return regexp.MustCompile(pattern).MatchString(escapedTestName) + } + return false +} diff --git a/tools/citool/cmd/check_tests_cmd_test.go b/tools/citool/cmd/check_tests_cmd_test.go new file mode 100644 index 000000000..4b7f50e7f --- /dev/null +++ b/tools/citool/cmd/check_tests_cmd_test.go @@ -0,0 +1,47 @@ +package cmd + +import ( + "testing" +) + +func TestMatchTestNameInCmd(t *testing.T) { + tests := []struct { + cmd string + testName string + expected bool + }{ + {"go test -test.run ^TestExample$", "TestExample", true}, + {"go test -test.run ^TestExample$", "TestAnother", false}, + {"go test -test.run ^TestExample$ -v", "TestExample", true}, + {"go test -test.run ^TestExamplePart$", "TestExample", false}, + {"go test -test.run ^TestWithNumbers123$", "TestWithNumbers123", true}, + {"go test -test.run ^Test_With_Underscores$", "Test_With_Underscores", true}, + {"go test -test.run ^Test-With-Dash$", "Test-With-Dash", true}, + {"go test -test.run ^TestWithSpace Space$", "TestWithSpace Space", true}, + {"go test -test.run ^TestWithNewline\nNewline$", "TestWithNewline\nNewline", true}, + {"go test -test.run ^TestOne$|^TestTwo$", "TestOne", true}, + {"go test -test.run ^TestOne$|^TestTwo$", "TestTwo", true}, + {"go test -test.run ^TestOne$|^TestTwo$", "TestThree", false}, + {"go test -test.run TestOne|TestTwo", "TestTwo", true}, + {"go test -test.run TestOne|TestTwo", "TestOne", true}, + {"go test -test.run TestOne|TestTwo|TestThree", "TestFour", false}, + {"go test -test.run ^TestOne$|TestTwo$", "TestTwo", true}, + {"go test -test.run ^TestOne$|TestTwo|TestThree$", "TestThree", true}, + {"go test -test.run TestOne|TestTwo|TestThree", "TestOne", true}, + {"go test -test.run TestOne|TestTwo|TestThree", "TestThree", true}, + {"go test -test.run ^TestA$|^TestB$|^TestC$", "TestA", true}, + {"go test -test.run ^TestA$|^TestB$|^TestC$", "TestB", true}, + {"go test -test.run ^TestA$|^TestB$|^TestC$", "TestD", false}, + {"go test -test.run TestA|^TestB$|TestC", "TestB", true}, + {"go test -test.run ^TestA|^TestB|TestC$", "TestA", true}, + {"go test -test.run ^TestA|^TestB|TestC$", "TestC", true}, + {"go test -test.run ^TestA|^TestB|TestC$", "TestD", false}, + } + + for _, tt := range tests { + result := matchTestNameInCmd(tt.cmd, tt.testName) + if result != tt.expected { + t.Errorf("matchTestNameInCmd(%s, %s) = %t; expected %t", tt.cmd, tt.testName, result, tt.expected) + } + } +} diff --git a/tools/citool/cmd/create_test_config_cmd.go b/tools/citool/cmd/create_test_config_cmd.go new file mode 100644 index 000000000..c0cd91b05 --- /dev/null +++ b/tools/citool/cmd/create_test_config_cmd.go @@ -0,0 +1,179 @@ +package cmd + +import ( + "fmt" + "os" + + "github.com/pelletier/go-toml/v2" + "github.com/spf13/cobra" + + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" + ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" +) + +var createTestConfigCmd = &cobra.Command{ + Use: "create", + Short: "Create a test config from the provided flags", + Run: func(cmd *cobra.Command, _ []string) { + var tc ctf_config.TestConfig + + var version, postgresVersion *string + if cmd.Flags().Changed(ChainlinkVersionFlag) { + version = &oc.ChainlinkVersion + } + if cmd.Flags().Changed(ChainlinkPostgresVersionFlag) { + version = &oc.ChainlinkPostgresVersion + } + if version != nil || postgresVersion != nil { + tc.ChainlinkImage = &ctf_config.ChainlinkImageConfig{ + Version: version, + PostgresVersion: postgresVersion, + } + } + + var upgradeVersion *string + if cmd.Flags().Changed(ChainlinkUpgradeVersionFlag) { + upgradeVersion = &oc.ChainlinkUpgradeVersion + } + if upgradeVersion != nil { + tc.ChainlinkUpgradeImage = &ctf_config.ChainlinkImageConfig{ + Version: upgradeVersion, + } + } + + var selectedNetworks *[]string + if cmd.Flags().Changed(SelectedNetworksFlag) { + selectedNetworks = &oc.SelectedNetworks + } + if selectedNetworks != nil { + tc.Network = &ctf_config.NetworkConfig{ + SelectedNetworks: oc.SelectedNetworks, + } + } + + var peryscopeEnabled *bool + var pyroscopeServerURL, pyroscopeEnvironment, pyroscopeKey *string + if cmd.Flags().Changed(PyroscopeEnabledFlag) { + peryscopeEnabled = &oc.PyroscopeEnabled + } + if cmd.Flags().Changed(PyroscopeServerURLFlag) { + pyroscopeServerURL = &oc.PyroscopeServerURL + } + if cmd.Flags().Changed(PyroscopeKeyFlag) { + pyroscopeKey = &oc.PyroscopeKey + } + if cmd.Flags().Changed(PyroscopeEnvironmentFlag) { + pyroscopeEnvironment = &oc.PyroscopeEnvironment + } + if peryscopeEnabled != nil { + tc.Pyroscope = &ctf_config.PyroscopeConfig{ + Enabled: peryscopeEnabled, + ServerUrl: pyroscopeServerURL, + Environment: pyroscopeEnvironment, + Key: pyroscopeKey, + } + } + + var testLogCollect *bool + if cmd.Flags().Changed(LoggingTestLogCollectFlag) { + testLogCollect = &oc.LoggingTestLogCollect + } + var loggingRunID *string + if cmd.Flags().Changed(LoggingRunIDFlag) { + loggingRunID = &oc.LoggingRunID + } + var loggingLogTargets []string + if cmd.Flags().Changed(LoggingLogTargetsFlag) { + loggingLogTargets = oc.LoggingLogTargets + } + var loggingLokiTenantID *string + if cmd.Flags().Changed(LoggingLokiTenantIDFlag) { + loggingLokiTenantID = &oc.LoggingLokiTenantID + } + var loggingLokiBasicAuth *string + if cmd.Flags().Changed(LoggingLokiBasicAuthFlag) { + loggingLokiBasicAuth = &oc.LoggingLokiBasicAuth + } + var loggingLokiEndpoint *string + if cmd.Flags().Changed(LoggingLokiEndpointFlag) { + loggingLokiEndpoint = &oc.LoggingLokiEndpoint + } + var loggingGrafanaBaseURL *string + if cmd.Flags().Changed(LoggingGrafanaBaseURLFlag) { + loggingGrafanaBaseURL = &oc.LoggingGrafanaBaseURL + } + var loggingGrafanaDashboardURL *string + if cmd.Flags().Changed(LoggingGrafanaDashboardURLFlag) { + loggingGrafanaDashboardURL = &oc.LoggingGrafanaDashboardURL + } + var loggingGrafanaBearerToken *string + if cmd.Flags().Changed(LoggingGrafanaBearerTokenFlag) { + loggingGrafanaBearerToken = &oc.LoggingGrafanaBearerToken + } + + if testLogCollect != nil || loggingRunID != nil || loggingLogTargets != nil || loggingLokiEndpoint != nil || loggingLokiTenantID != nil || loggingLokiBasicAuth != nil || loggingGrafanaBaseURL != nil || loggingGrafanaDashboardURL != nil || loggingGrafanaBearerToken != nil { + tc.Logging = &ctf_config.LoggingConfig{} + tc.Logging.TestLogCollect = testLogCollect + tc.Logging.RunId = loggingRunID + if loggingLogTargets != nil { + tc.Logging.LogStream = &ctf_config.LogStreamConfig{ + LogTargets: loggingLogTargets, + } + } + if loggingLokiTenantID != nil || loggingLokiBasicAuth != nil || loggingLokiEndpoint != nil { + tc.Logging.Loki = &ctf_config.LokiConfig{ + TenantId: loggingLokiTenantID, + BasicAuth: loggingLokiBasicAuth, + Endpoint: loggingLokiEndpoint, + } + } + if loggingGrafanaBaseURL != nil || loggingGrafanaDashboardURL != nil || loggingGrafanaBearerToken != nil { + tc.Logging.Grafana = &ctf_config.GrafanaConfig{ + BaseUrl: loggingGrafanaBaseURL, + DashboardUrl: loggingGrafanaDashboardURL, + BearerToken: loggingGrafanaBearerToken, + } + } + } + + var privateEthereumNetworkExecutionLayer *string + if cmd.Flags().Changed(PrivateEthereumNetworkExecutionLayerFlag) { + privateEthereumNetworkExecutionLayer = &oc.PrivateEthereumNetworkExecutionLayer + } + var privateEthereumNetworkEthereumVersion *string + if cmd.Flags().Changed(PrivateEthereumNetworkEthereumVersionFlag) { + privateEthereumNetworkEthereumVersion = &oc.PrivateEthereumNetworkEthereumVersion + } + var privateEthereumNetworkCustomDockerImage *string + if cmd.Flags().Changed(PrivateEthereumNetworkCustomDockerImageFlag) { + privateEthereumNetworkCustomDockerImage = &oc.PrivateEthereumNetworkCustomDockerImages + } + if privateEthereumNetworkExecutionLayer != nil || privateEthereumNetworkEthereumVersion != nil || privateEthereumNetworkCustomDockerImage != nil { + var el ctf_config_types.ExecutionLayer + if privateEthereumNetworkExecutionLayer != nil { + el = ctf_config_types.ExecutionLayer(*privateEthereumNetworkExecutionLayer) + } + var ev ctf_config_types.EthereumVersion + if privateEthereumNetworkEthereumVersion != nil { + ev = ctf_config_types.EthereumVersion(*privateEthereumNetworkEthereumVersion) + } + var customImages map[ctf_config.ContainerType]string + if privateEthereumNetworkCustomDockerImage != nil { + customImages = map[ctf_config.ContainerType]string{"execution_layer": *privateEthereumNetworkCustomDockerImage} + } + tc.PrivateEthereumNetwork = &ctf_config.EthereumNetworkConfig{ + ExecutionLayer: &el, + EthereumVersion: &ev, + CustomDockerImages: customImages, + } + } + + configToml, err := toml.Marshal(tc) + if err != nil { + fmt.Fprintf(os.Stderr, "Error marshalling TestConfig to TOML: %v\n", err) + os.Exit(1) + } + + fmt.Fprintln(cmd.OutOrStdout(), string(configToml)) + }, +} diff --git a/tools/citool/cmd/csv_export_cmd.go b/tools/citool/cmd/csv_export_cmd.go new file mode 100644 index 000000000..8fe13440c --- /dev/null +++ b/tools/citool/cmd/csv_export_cmd.go @@ -0,0 +1,96 @@ +package cmd + +import ( + "encoding/csv" + "fmt" + "os" + "strings" + + "github.com/spf13/cobra" + "gopkg.in/yaml.v3" +) + +var csvExportCmd = &cobra.Command{ + Use: "csvexport", + Short: "Export tests to CSV format", + Run: func(cmd *cobra.Command, _ []string) { + configFile, _ := cmd.Flags().GetString("file") + if err := exportConfigToCSV(configFile); err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } + }, +} + +func init() { + csvExportCmd.Flags().StringP("file", "f", "", "Path to YML file") + err := csvExportCmd.MarkFlagRequired("file") + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } +} + +func exportConfigToCSV(configFile string) error { + // Read the YAML file + bytes, err := os.ReadFile(configFile) + if err != nil { + return err + } + + // Unmarshal the YAML into the Config struct + var config Config + if err := yaml.Unmarshal(bytes, &config); err != nil { + return err + } + + // Create a CSV file + file, err := os.Create("output.csv") + if err != nil { + return err + } + defer file.Close() + + writer := csv.NewWriter(file) + defer writer.Flush() + + // Write CSV headers + headers := []string{"ID", "Test Path", "Test Env Type", "Runs On", "Test Cmd", "Test Config Override Required", "Test Secrets Required", "Remote Runner Memory", "Pyroscope Env", "Workflows", "Test Inputs"} + if err := writer.Write(headers); err != nil { + return err + } + + // Iterate over Tests and write data to CSV + for _, test := range config.Tests { + workflows := strings.Join(test.Workflows, ", ") // Combine workflows into a single CSV field + // Serialize TestInputs + testInputs := serializeMap(test.TestInputs) + + record := []string{ + test.ID, + test.Path, + test.TestEnvType, + test.RunsOn, + test.TestCmd, + fmt.Sprintf("%t", test.TestConfigOverrideRequired), + fmt.Sprintf("%t", test.TestSecretsRequired), + test.RemoteRunnerMemory, + test.PyroscopeEnv, + workflows, + testInputs, + } + if err := writer.Write(record); err != nil { + return err + } + } + + return nil +} + +func serializeMap(inputs map[string]string) string { + pairs := make([]string, 0, len(inputs)) + for key, value := range inputs { + pairs = append(pairs, fmt.Sprintf("%s=%s", key, value)) + } + return strings.Join(pairs, ", ") +} diff --git a/tools/citool/cmd/filter_cmd.go b/tools/citool/cmd/filter_cmd.go new file mode 100644 index 000000000..c1d5f2235 --- /dev/null +++ b/tools/citool/cmd/filter_cmd.go @@ -0,0 +1,165 @@ +package cmd + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "log" + "os" + "regexp" + "strings" + + "github.com/spf13/cobra" + "gopkg.in/yaml.v2" + + "github.com/smartcontractkit/chainlink-testing-framework/utils" +) + +// Filter tests based on workflow, test type, and test IDs. +func filterTests(allTests []CITestConf, workflow, testType, ids string, envresolve bool) []CITestConf { + workflowFilter := workflow + typeFilter := testType + idFilter := strings.Split(ids, ",") + + var filteredTests []CITestConf + + for _, test := range allTests { + workflowMatch := workflow == "" || contains(test.Workflows, workflowFilter) + typeMatch := testType == "" || test.TestEnvType == typeFilter + idMatch := ids == "*" || ids == "" || contains(idFilter, test.ID) + + if workflowMatch && typeMatch && idMatch { + test.IDSanitized = sanitizeTestID(test.ID) + filteredTests = append(filteredTests, test) + } + if envresolve { + for k, v := range test.TestInputs { + test.TestInputs[k] = utils.MustResolveEnvPlaceholder(v) + } + } + } + + return filteredTests +} + +func filterAndMergeTests(allTests []CITestConf, workflow, testType, base64Tests string, envresolve bool) ([]CITestConf, error) { + decodedBytes, err := base64.StdEncoding.DecodeString(base64Tests) + if err != nil { + return nil, err + } + var decodedTests []CITestConf + err = yaml.Unmarshal(decodedBytes, &decodedTests) + if err != nil { + return nil, err + } + + idFilter := make(map[string]CITestConf) + for _, dt := range decodedTests { + idFilter[dt.ID] = dt + } + + var filteredTests []CITestConf + for _, test := range allTests { + workflowMatch := workflow == "" || contains(test.Workflows, workflow) + typeMatch := testType == "" || test.TestEnvType == testType + + if decodedTest, exists := idFilter[test.ID]; exists && workflowMatch && typeMatch { + // Override test inputs from the base64 encoded tests + for k, v := range decodedTest.TestInputs { + if test.TestInputs == nil { + test.TestInputs = make(map[string]string) + } + test.TestInputs[k] = v + } + test.IDSanitized = sanitizeTestID(test.ID) + filteredTests = append(filteredTests, test) + } + if envresolve { + for k, v := range test.TestInputs { + test.TestInputs[k] = utils.MustResolveEnvPlaceholder(v) + } + } + } + + return filteredTests, nil +} + +func sanitizeTestID(id string) string { + // Define a regular expression that matches any character not a letter, digit, hyphen + re := regexp.MustCompile(`[^a-zA-Z0-9-_]+`) + // Replace all occurrences of disallowed characters with "_" + return re.ReplaceAllString(id, "_") +} + +// Utility function to check if a slice contains a string. +func contains(slice []string, element string) bool { + for _, s := range slice { + if s == element { + return true + } + } + return false +} + +// filterCmd represents the filter command +var filterCmd = &cobra.Command{ + Use: "filter", + Short: "Filter test configurations based on specified criteria", + Long: `Filters tests from a YAML configuration based on name, workflow, test type, and test IDs. +Example usage: +./e2e_tests_tool filter --file .github/e2e-tests.yml --workflow "Run Nightly E2E Tests" --test-env-type "docker" --test-ids "test1,test2"`, + Run: func(cmd *cobra.Command, _ []string) { + yamlFile, _ := cmd.Flags().GetString("file") + workflow, _ := cmd.Flags().GetString("workflow") + testType, _ := cmd.Flags().GetString("test-env-type") + testIDs, _ := cmd.Flags().GetString("test-ids") + testMap, _ := cmd.Flags().GetString("test-list") + envresolve, _ := cmd.Flags().GetBool("envresolve") + + data, err := os.ReadFile(yamlFile) + if err != nil { + fmt.Fprintf(os.Stderr, "Error reading YAML file: %v\n", err) + os.Exit(1) + } + + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + fmt.Fprintf(os.Stderr, "Error parsing YAML file %s data: %v\n", yamlFile, err) + os.Exit(1) + } + + var filteredTests []CITestConf + if testMap == "" { + filteredTests = filterTests(config.Tests, workflow, testType, testIDs, envresolve) + } else { + filteredTests, err = filterAndMergeTests(config.Tests, workflow, testType, testMap, envresolve) + if err != nil { + log.Fatalf("Error filtering and merging tests: %v", err) + } + } + matrix := map[string][]CITestConf{"tests": filteredTests} + matrixJSON, err := json.Marshal(matrix) + if err != nil { + fmt.Fprintf(os.Stderr, "Error marshaling matrix to JSON: %v\n", err) + os.Exit(1) + } + + fmt.Printf("%s", matrixJSON) + }, +} + +func init() { + filterCmd.Flags().StringP("file", "f", "", "Path to the YAML file") + filterCmd.Flags().String("test-list", "", "Base64 encoded list of tests (YML objects) to filter by. Can include test_inputs for each test.") + filterCmd.Flags().StringP("test-ids", "i", "*", "Comma-separated list of test IDs to filter by") + filterCmd.Flags().StringP("test-env-type", "y", "", "Type of test to filter by") + filterCmd.Flags().StringP("workflow", "t", "", "Workflow filter") + filterCmd.Flags().Bool("envresolve", false, "Resolve environment variables in test inputs") + + err := filterCmd.MarkFlagRequired("file") + if err != nil { + fmt.Fprintf(os.Stderr, "Error marking flag as required: %v\n", err) + os.Exit(1) + } +} diff --git a/tools/citool/cmd/filter_cmd_test.go b/tools/citool/cmd/filter_cmd_test.go new file mode 100644 index 000000000..ff6e9c981 --- /dev/null +++ b/tools/citool/cmd/filter_cmd_test.go @@ -0,0 +1,64 @@ +package cmd + +import ( + "testing" +) + +func TestFilterTestsByID(t *testing.T) { + tests := []CITestConf{ + {ID: "run_all_in_ocr_tests_go", TestEnvType: "docker"}, + {ID: "run_all_in_ocr2_tests_go", TestEnvType: "docker"}, + {ID: "run_all_in_ocr3_tests_go", TestEnvType: "k8s_remote_runner"}, + } + + cases := []struct { + description string + inputIDs string + expectedLen int + }{ + {"Filter by single ID", "run_all_in_ocr_tests_go", 1}, + {"Filter by multiple IDs", "run_all_in_ocr_tests_go,run_all_in_ocr2_tests_go", 2}, + {"Wildcard to include all", "*", 3}, + {"Empty ID string to include all", "", 3}, + } + + for _, c := range cases { + t.Run(c.description, func(t *testing.T) { + filtered := filterTests(tests, "", "", c.inputIDs, false) + if len(filtered) != c.expectedLen { + t.Errorf("FilterTests(%s) returned %d tests, expected %d", c.description, len(filtered), c.expectedLen) + } + }) + } +} + +func TestFilterTestsIntegration(t *testing.T) { + tests := []CITestConf{ + {ID: "run_all_in_ocr_tests_go", TestEnvType: "docker", Workflows: []string{"Run Nightly E2E Tests"}}, + {ID: "run_all_in_ocr2_tests_go", TestEnvType: "docker", Workflows: []string{"Run PR E2E Tests"}}, + {ID: "run_all_in_ocr3_tests_go", TestEnvType: "k8s_remote_runner", Workflows: []string{"Run PR E2E Tests"}}, + } + + cases := []struct { + description string + inputNames string + inputWorkflow string + inputTestType string + inputIDs string + expectedLen int + }{ + {"Filter by test type and ID", "", "", "docker", "run_all_in_ocr2_tests_go", 1}, + {"Filter by trigger and test type", "", "Run PR E2E Tests", "docker", "*", 1}, + {"No filters applied", "", "", "", "*", 3}, + {"Filter mismatching all criteria", "", "Run Nightly E2E Tests", "", "", 1}, + } + + for _, c := range cases { + t.Run(c.description, func(t *testing.T) { + filtered := filterTests(tests, c.inputWorkflow, c.inputTestType, c.inputIDs, false) + if len(filtered) != c.expectedLen { + t.Errorf("FilterTests(%s) returned %d tests, expected %d", c.description, len(filtered), c.expectedLen) + } + }) + } +} diff --git a/tools/citool/cmd/root_cmd.go b/tools/citool/cmd/root_cmd.go new file mode 100644 index 000000000..fdb4efd57 --- /dev/null +++ b/tools/citool/cmd/root_cmd.go @@ -0,0 +1,32 @@ +package cmd + +import ( + "os" + + "github.com/spf13/cobra" +) + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "citool", + Short: "A tool to manage E2E tests on Github CI", +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + err := rootCmd.Execute() + if err != nil { + os.Exit(1) + } +} + +func init() { + rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + + rootCmd.AddCommand(checkTestsCmd) + rootCmd.AddCommand(filterCmd) + rootCmd.AddCommand(csvExportCmd) + rootCmd.AddCommand(testConfigCmd) + testConfigCmd.AddCommand(createTestConfigCmd) +} diff --git a/tools/citool/cmd/test_config_cmd.go b/tools/citool/cmd/test_config_cmd.go new file mode 100644 index 000000000..0c0e27235 --- /dev/null +++ b/tools/citool/cmd/test_config_cmd.go @@ -0,0 +1,123 @@ +package cmd + +import ( + "strings" + + "github.com/spf13/cobra" + + "github.com/smartcontractkit/chainlink-testing-framework/utils" +) + +var testConfigCmd = &cobra.Command{ + Use: "test-config", + Short: "Manage test config", +} + +// OverrideConfig holds the configuration data for overrides +type OverrideConfig struct { + ChainlinkImage string + ChainlinkVersion string + ChainlinkUpgradeImage string + ChainlinkUpgradeVersion string + ChainlinkPostgresVersion string + SelectedNetworks []string + PyroscopeEnabled bool + PyroscopeServerURL string + PyroscopeEnvironment string + PyroscopeKey string + LoggingTestLogCollect bool + LoggingRunID string + LoggingLogTargets []string + LoggingLokiTenantID string + LoggingLokiEndpoint string + LoggingLokiBasicAuth string + LoggingGrafanaBaseURL string + LoggingGrafanaDashboardURL string + LoggingGrafanaBearerToken string + PrivateEthereumNetworkExecutionLayer string + PrivateEthereumNetworkEthereumVersion string + PrivateEthereumNetworkCustomDockerImages string +} + +const ( + ChainlinkVersionFlag = "chainlink-version" + ChainlinkUpgradeVersionFlag = "chainlink-upgrade-version" + ChainlinkPostgresVersionFlag = "chainlink-postgres-version" + SelectedNetworksFlag = "selected-networks" + FromBase64ConfigFlag = "from-base64-config" + LoggingLokiBasicAuthFlag = "logging-loki-basic-auth" + LoggingLokiEndpointFlag = "logging-loki-endpoint" + LoggingRunIDFlag = "logging-run-id" + LoggingLokiTenantIDFlag = "logging-loki-tenant-id" + LoggingGrafanaBaseURLFlag = "logging-grafana-base-url" + LoggingGrafanaDashboardURLFlag = "logging-grafana-dashboard-url" + LoggingGrafanaBearerTokenFlag = "logging-grafana-bearer-token" + LoggingLogTargetsFlag = "logging-log-targets" + LoggingTestLogCollectFlag = "logging-test-log-collect" + PyroscopeEnabledFlag = "pyroscope-enabled" + PyroscopeServerURLFlag = "pyroscope-server-url" + PyroscopeKeyFlag = "pyroscope-key" + PyroscopeEnvironmentFlag = "pyroscope-environment" + PrivateEthereumNetworkExecutionLayerFlag = "private-ethereum-network-execution-layer" + PrivateEthereumNetworkEthereumVersionFlag = "private-ethereum-network-ethereum-version" + PrivateEthereumNetworkCustomDockerImageFlag = "private-ethereum-network-custom-docker-image" +) + +var oc OverrideConfig + +func init() { + cmds := []*cobra.Command{createTestConfigCmd} + for _, c := range cmds { + c.Flags().StringArrayVar(&oc.SelectedNetworks, SelectedNetworksFlag, nil, "Selected networks") + c.Flags().StringVar(&oc.ChainlinkVersion, ChainlinkVersionFlag, "", "Chainlink version") + c.Flags().StringVar(&oc.ChainlinkUpgradeVersion, ChainlinkUpgradeVersionFlag, "", "Chainlink upgrade version") + c.Flags().StringVar(&oc.ChainlinkPostgresVersion, ChainlinkPostgresVersionFlag, "", "Chainlink Postgres version") + c.Flags().BoolVar(&oc.PyroscopeEnabled, PyroscopeEnabledFlag, false, "Pyroscope enabled") + c.Flags().StringVar(&oc.PyroscopeServerURL, PyroscopeServerURLFlag, "", "Pyroscope server URL") + c.Flags().StringVar(&oc.PyroscopeKey, PyroscopeKeyFlag, "", "Pyroscope key") + c.Flags().StringVar(&oc.PyroscopeEnvironment, PyroscopeEnvironmentFlag, "", "Pyroscope environment") + c.Flags().BoolVar(&oc.LoggingTestLogCollect, LoggingTestLogCollectFlag, false, "Test log collect") + c.Flags().StringVar(&oc.LoggingRunID, LoggingRunIDFlag, "", "Run ID") + c.Flags().StringArrayVar(&oc.LoggingLogTargets, LoggingLogTargetsFlag, nil, "Logging.LogStream.LogTargets") + c.Flags().StringVar(&oc.LoggingLokiEndpoint, LoggingLokiEndpointFlag, "", "") + c.Flags().StringVar(&oc.LoggingLokiTenantID, LoggingLokiTenantIDFlag, "", "") + c.Flags().StringVar(&oc.LoggingLokiBasicAuth, LoggingLokiBasicAuthFlag, "", "") + c.Flags().StringVar(&oc.LoggingGrafanaBaseURL, LoggingGrafanaBaseURLFlag, "", "") + c.Flags().StringVar(&oc.LoggingGrafanaDashboardURL, LoggingGrafanaDashboardURLFlag, "", "") + c.Flags().StringVar(&oc.LoggingGrafanaBearerToken, LoggingGrafanaBearerTokenFlag, "", "") + c.Flags().StringVar(&oc.PrivateEthereumNetworkExecutionLayer, PrivateEthereumNetworkExecutionLayerFlag, "", "") + c.Flags().StringVar(&oc.PrivateEthereumNetworkEthereumVersion, PrivateEthereumNetworkEthereumVersionFlag, "", "") + c.Flags().StringVar(&oc.PrivateEthereumNetworkCustomDockerImages, PrivateEthereumNetworkCustomDockerImageFlag, "", "") + + c.PreRun = func(_ *cobra.Command, _ []string) { + // Resolve selected networks environment variable if set + if len(oc.SelectedNetworks) > 0 { + _, hasEnvVar := utils.LookupEnvVarName(oc.SelectedNetworks[0]) + if hasEnvVar { + selectedNetworks := utils.MustResolveEnvPlaceholder(oc.SelectedNetworks[0]) + oc.SelectedNetworks = strings.Split(selectedNetworks, ",") + } + } + + // Resolve all other environment variables + oc.ChainlinkImage = utils.MustResolveEnvPlaceholder(oc.ChainlinkImage) + oc.ChainlinkVersion = utils.MustResolveEnvPlaceholder(oc.ChainlinkVersion) + oc.ChainlinkUpgradeImage = utils.MustResolveEnvPlaceholder(oc.ChainlinkUpgradeImage) + oc.ChainlinkUpgradeVersion = utils.MustResolveEnvPlaceholder(oc.ChainlinkUpgradeVersion) + oc.ChainlinkPostgresVersion = utils.MustResolveEnvPlaceholder(oc.ChainlinkPostgresVersion) + oc.PyroscopeServerURL = utils.MustResolveEnvPlaceholder(oc.PyroscopeServerURL) + oc.PyroscopeKey = utils.MustResolveEnvPlaceholder(oc.PyroscopeKey) + oc.PyroscopeEnvironment = utils.MustResolveEnvPlaceholder(oc.PyroscopeEnvironment) + oc.LoggingRunID = utils.MustResolveEnvPlaceholder(oc.LoggingRunID) + oc.LoggingLokiTenantID = utils.MustResolveEnvPlaceholder(oc.LoggingLokiTenantID) + oc.LoggingLokiEndpoint = utils.MustResolveEnvPlaceholder(oc.LoggingLokiEndpoint) + oc.LoggingLokiBasicAuth = utils.MustResolveEnvPlaceholder(oc.LoggingLokiBasicAuth) + oc.LoggingGrafanaBaseURL = utils.MustResolveEnvPlaceholder(oc.LoggingGrafanaBaseURL) + oc.LoggingGrafanaDashboardURL = utils.MustResolveEnvPlaceholder(oc.LoggingGrafanaDashboardURL) + oc.LoggingGrafanaBearerToken = utils.MustResolveEnvPlaceholder(oc.LoggingGrafanaBearerToken) + oc.PrivateEthereumNetworkExecutionLayer = utils.MustResolveEnvPlaceholder(oc.PrivateEthereumNetworkExecutionLayer) + oc.PrivateEthereumNetworkEthereumVersion = utils.MustResolveEnvPlaceholder(oc.PrivateEthereumNetworkEthereumVersion) + oc.PrivateEthereumNetworkCustomDockerImages = utils.MustResolveEnvPlaceholder(oc.PrivateEthereumNetworkCustomDockerImages) + } + } +} diff --git a/tools/citool/cmd/test_config_cmd_test.go b/tools/citool/cmd/test_config_cmd_test.go new file mode 100644 index 000000000..79185e608 --- /dev/null +++ b/tools/citool/cmd/test_config_cmd_test.go @@ -0,0 +1,75 @@ +package cmd + +import ( + "bytes" + "testing" + + "github.com/pelletier/go-toml/v2" + "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" + + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" + ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" +) + +func TestCreateTestConfigCmd(t *testing.T) { + tests := []struct { + name string + args []string + want interface{} + check func(t *testing.T, tc *ctf_config.TestConfig) + wantErr bool + }{ + { + name: "LoggingLogTargets", + args: []string{"create", "--logging-log-targets=target1", "--logging-log-targets=target2"}, + check: func(t *testing.T, tc *ctf_config.TestConfig) { + assert.NotNil(t, tc.Logging) + assert.NotNil(t, tc.Logging.LogStream) + assert.Equal(t, []string{"target1", "target2"}, tc.Logging.LogStream.LogTargets) + }, + }, + { + name: "PrivateEthereumNetworkExecutionLayerFlag", + args: []string{"create", "--private-ethereum-network-execution-layer=geth", "--private-ethereum-network-ethereum-version=1.10.0"}, + check: func(t *testing.T, tc *ctf_config.TestConfig) { + assert.NotNil(t, tc.PrivateEthereumNetwork) + assert.NotNil(t, tc.PrivateEthereumNetwork.ExecutionLayer) + assert.Equal(t, ctf_config_types.ExecutionLayer("geth"), *tc.PrivateEthereumNetwork.ExecutionLayer) + assert.Equal(t, ctf_config_types.EthereumVersion("1.10.0"), *tc.PrivateEthereumNetwork.EthereumVersion) + }, + }, + { + name: "PrivateEthereumNetworkCustomDockerImageFlag", + args: []string{"create", "--private-ethereum-network-execution-layer=geth", "--private-ethereum-network-ethereum-version=1.10.0", "--private-ethereum-network-custom-docker-image=custom-image:v1.0"}, + check: func(t *testing.T, tc *ctf_config.TestConfig) { + assert.NotNil(t, tc.PrivateEthereumNetwork) + assert.NotNil(t, tc.PrivateEthereumNetwork.ExecutionLayer) + assert.Equal(t, map[ctf_config.ContainerType]string{"execution_layer": "custom-image:v1.0"}, tc.PrivateEthereumNetwork.CustomDockerImages) + }, + }, + } + + rootCmd := &cobra.Command{} + rootCmd.AddCommand(createTestConfigCmd) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + rootCmd.SetArgs(tt.args) + var out bytes.Buffer + rootCmd.SetOutput(&out) + err := rootCmd.Execute() + if (err != nil) != tt.wantErr { + t.Fatalf("Execute() error = %v, wantErr %v", err, tt.wantErr) + } + var tc ctf_config.TestConfig + err = toml.Unmarshal(out.Bytes(), &tc) + if err != nil { + t.Fatalf("Failed to unmarshal output: %v", err) + } + if tt.check != nil { + tt.check(t, &tc) + } + }) + } +} diff --git a/tools/citool/cmd/types.go b/tools/citool/cmd/types.go new file mode 100644 index 000000000..3c347e940 --- /dev/null +++ b/tools/citool/cmd/types.go @@ -0,0 +1,26 @@ +package cmd + +type Test struct { + Name string + Path string +} + +// CITestConf defines the configuration for running a test in a CI environment, specifying details like test ID, path, type, runner settings, command, and associated workflows. +type CITestConf struct { + ID string `yaml:"id" json:"id"` + IDSanitized string `json:"id_sanitized"` + Path string `yaml:"path" json:"path"` + TestEnvType string `yaml:"test_env_type" json:"test_env_type"` + RunsOn string `yaml:"runs_on" json:"runs_on"` + TestCmd string `yaml:"test_cmd" json:"test_cmd"` + TestConfigOverrideRequired bool `yaml:"test_config_override_required" json:"testConfigOverrideRequired"` + TestSecretsRequired bool `yaml:"test_secrets_required" json:"testSecretsRequired"` + TestInputs map[string]string `yaml:"test_inputs" json:"test_inputs"` + RemoteRunnerMemory string `yaml:"remote_runner_memory" json:"remoteRunnerMemory"` + PyroscopeEnv string `yaml:"pyroscope_env" json:"pyroscopeEnv"` + Workflows []string `yaml:"workflows" json:"workflows"` +} + +type Config struct { + Tests []CITestConf `yaml:"runner-test-matrix"` +} diff --git a/tools/citool/go.mod b/tools/citool/go.mod new file mode 100644 index 000000000..99c3d3e72 --- /dev/null +++ b/tools/citool/go.mod @@ -0,0 +1,198 @@ +module github.com/smartcontractkit/chainlink-testing-framework/tools/citool + +go 1.22.5 + +replace ( + github.com/go-kit/log => github.com/go-kit/log v0.2.1 + + // replicating the replace directive on cosmos SDK + github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 + +) + +require ( + github.com/pelletier/go-toml/v2 v2.2.2 + github.com/smartcontractkit/chainlink-testing-framework v1.34.2 + github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240809091712-98b90543972d + github.com/spf13/cobra v1.8.1 + github.com/stretchr/testify v1.9.0 + gopkg.in/yaml.v2 v2.4.0 + gopkg.in/yaml.v3 v3.0.1 +) + +require ( + dario.cat/mergo v1.0.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/DataDog/zstd v1.5.2 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect + github.com/Masterminds/semver/v3 v3.2.1 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/hcsshim v0.11.4 // indirect + github.com/VictoriaMetrics/fastcache v1.12.1 // indirect + github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect + github.com/avast/retry-go v3.0.0+incompatible // indirect + github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect + github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect + github.com/aws/jsii-runtime-go v1.75.0 // indirect + github.com/benbjohnson/clock v1.3.5 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chai2010/gettext-go v1.0.2 // indirect + github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f // indirect + github.com/cockroachdb/errors v1.9.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect + github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/containerd/containerd v1.7.12 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect + github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/distribution/reference v0.5.0 // indirect + github.com/docker/docker v25.0.2+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/emicklei/go-restful/v3 v3.12.1 // indirect + github.com/ethereum/c-kzg-4844 v0.4.0 // indirect + github.com/ethereum/go-ethereum v1.13.8 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.9.0 // indirect + github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect + github.com/fatih/camelcase v1.0.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fvbommel/sortorder v1.1.0 // indirect + github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect + github.com/getsentry/sentry-go v0.19.0 // indirect + github.com/go-errors/errors v1.4.2 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-resty/resty/v2 v2.11.0 // indirect + github.com/gofrs/flock v0.8.1 // indirect + github.com/gogo/protobuf v1.3.3 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect + github.com/google/btree v1.1.2 // indirect + github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/holiman/uint256 v1.2.4 // indirect + github.com/imdario/mergo v0.3.16 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/joho/godotenv v1.5.1 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kelseyhightower/envconfig v1.4.0 // indirect + github.com/klauspost/compress v1.17.3 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/spdystream v0.4.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0-rc5 // indirect + github.com/peterbourgon/diskv v2.0.1+incompatible // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rivo/uniseg v0.4.4 // indirect + github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/rs/zerolog v1.31.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/shirou/gopsutil/v3 v3.24.3 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/smartcontractkit/seth v1.1.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/supranational/blst v0.3.11 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect + github.com/testcontainers/testcontainers-go v0.28.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/xlab/treeprint v1.2.0 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/ratelimit v0.3.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect + golang.org/x/mod v0.19.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/term v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.23.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + k8s.io/api v0.28.2 // indirect + k8s.io/apiextensions-apiserver v0.28.2 // indirect + k8s.io/apimachinery v0.28.2 // indirect + k8s.io/cli-runtime v0.28.2 // indirect + k8s.io/client-go v0.28.2 // indirect + k8s.io/component-base v0.28.2 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f // indirect + k8s.io/kubectl v0.28.2 // indirect + k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect + rsc.io/tmplfunc v0.0.3 // indirect + sigs.k8s.io/controller-runtime v0.16.2 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect + sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect +) diff --git a/tools/citool/go.sum b/tools/citool/go.sum new file mode 100644 index 000000000..76e3a8a7b --- /dev/null +++ b/tools/citool/go.sum @@ -0,0 +1,874 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= +github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 h1:t3eaIm0rUkzbrIewtiFmMK5RXHej2XnoXNhxVsAYUfg= +github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= +github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= +github.com/awalterschulze/gographviz v2.0.3+incompatible h1:9sVEXJBJLwGX7EQVhLm2elIKCm7P2YHFC8v6096G09E= +github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs= +github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3sWOxO2Dfja0iA1W7ZcI7g= +github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= +github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= +github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYSN6/mGyHI6O3I= +github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= +github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= +github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= +github.com/bxcodec/faker v2.0.1+incompatible/go.mod h1:BNzfpVdTwnFJ6GtfYTcQu6l6rHShT+veBxNCnjCx5XM= +github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 h1:rvc39Ol6z3MvaBzXkxFC6Nfsnixq/dRypushKDd7Nc0= +github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5/go.mod h1:R/pdNYDYFQk+tuuOo7QES1kkv6OLmp5ze2XBZQIVffM= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= +github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= +github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= +github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f h1:onZ3oc6l1Gz8pVpQ0c1U1Cb11kIMoDb3xtEy/iZbYZM= +github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f/go.mod h1:x11iCbZV6hzzSQWMq610B6Wl5Lg1dhwqcVfeiWQQnQQ= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= +github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= +github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= +github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= +github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= +github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v25.0.2+incompatible h1:/OaKeauroa10K4Nqavw4zlhcDq/WBcPMc5DbjOGgozY= +github.com/docker/docker v25.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= +github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= +github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= +github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= +github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= +github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= +github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= +github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= +github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= +github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= +github.com/getsentry/sentry-go v0.19.0 h1:BcCH3CN5tXt5aML+gwmbFwVptLLQA+eT866fCO9wVOM= +github.com/getsentry/sentry-go v0.19.0/go.mod h1:y3+lGEFEFexZtpbG1GUE2WD/f9zGyKYwpEqryTOC/nE= +github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= +github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= +github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= +github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= +github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= +github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= +github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= +github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= +github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= +github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= +github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= +github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= +github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= +github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= +github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= +github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= +github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= +github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= +github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= +github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= +github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= +github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= +github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/smartcontractkit/chainlink-testing-framework v1.34.2 h1:YL3ft7KJB7SAopdmJeyeR4/kv0j4jOdagNihXq8OZ38= +github.com/smartcontractkit/chainlink-testing-framework v1.34.2/go.mod h1:hRZEDh2+afO8MSZb9qYNscmWb+3mHZf01J5ACZuIdTQ= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240809091712-98b90543972d h1:6FxG5HxqBChkibqk8w3sOtrdQjgoquz44gBA6+IcBDA= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240809091712-98b90543972d/go.mod h1:dvQ1dAmlXaz9i1vzq9jpuLH33krZNC9E+ziHgqwIxws= +github.com/smartcontractkit/seth v1.1.1 h1:6hvexjJD7ek8ht/CLlEwQcH21K2E/WEYwbSRdKInZmM= +github.com/smartcontractkit/seth v1.1.1/go.mod h1:cDfKHi/hJLpO9sRpVbrflrHCOV+MJPAMJHloExJnIXk= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/testcontainers/testcontainers-go v0.28.0 h1:1HLm9qm+J5VikzFDYhOd+Zw12NtOl+8drH2E8nTY1r8= +github.com/testcontainers/testcontainers-go v0.28.0/go.mod h1:COlDpUXbwW3owtpMkEB1zo9gwb1CoKVKlyrVPejF4AU= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.22.12 h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= +github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= +go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/ratelimit v0.3.0 h1:IdZd9wqvFXnvLvSEBo0KPcGfkoBGNkpTHlrE3Rcjkjw= +go.uber.org/ratelimit v0.3.0/go.mod h1:So5LG7CV1zWpY1sHe+DXTJqQvOx+FFPFaAs2SnoyBaI= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= +gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= +k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= +k8s.io/apiextensions-apiserver v0.28.2 h1:J6/QRWIKV2/HwBhHRVITMLYoypCoPY1ftigDM0Kn+QU= +k8s.io/apiextensions-apiserver v0.28.2/go.mod h1:5tnkxLGa9nefefYzWuAlWZ7RZYuN/765Au8cWLA6SRg= +k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= +k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= +k8s.io/cli-runtime v0.28.2 h1:64meB2fDj10/ThIMEJLO29a1oujSm0GQmKzh1RtA/uk= +k8s.io/cli-runtime v0.28.2/go.mod h1:bTpGOvpdsPtDKoyfG4EG041WIyFZLV9qq4rPlkyYfDA= +k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= +k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= +k8s.io/component-base v0.28.2 h1:Yc1yU+6AQSlpJZyvehm/NkJBII72rzlEsd6MkBQ+G0E= +k8s.io/component-base v0.28.2/go.mod h1:4IuQPQviQCg3du4si8GpMrhAIegxpsgPngPRR/zWpzc= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f h1:2sXuKesAYbRHxL3aE2PN6zX/gcJr22cjrsej+W784Tc= +k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc= +k8s.io/kubectl v0.28.2 h1:fOWOtU6S0smdNjG1PB9WFbqEIMlkzU5ahyHkc7ESHgM= +k8s.io/kubectl v0.28.2/go.mod h1:6EQWTPySF1fn7yKoQZHYf9TPwIl2AygHEcJoxFekr64= +k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= +k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= +sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= +sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0= +sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= +sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U= +sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/tools/citool/main.go b/tools/citool/main.go new file mode 100644 index 000000000..4fa6cac56 --- /dev/null +++ b/tools/citool/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "github.com/smartcontractkit/chainlink/integration-tests/citool/cmd" +) + +func main() { + cmd.Execute() +} diff --git a/tools/citool/package.json b/tools/citool/package.json new file mode 100644 index 000000000..73a15f853 --- /dev/null +++ b/tools/citool/package.json @@ -0,0 +1,5 @@ +{ + "name": "citool", + "description": "Tool to manage E2E tests on Github CI", + "version": "1.0.0" +} From 1875c8a4ea1fcebe781f936e0dc4338efc1b3069 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Fri, 9 Aug 2024 14:14:54 +0200 Subject: [PATCH 18/26] fix flaky logstream unit test (#1050) --- logstream/logstream_test.go | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/logstream/logstream_test.go b/logstream/logstream_test.go index bb7b9fe56..a117b8706 100644 --- a/logstream/logstream_test.go +++ b/logstream/logstream_test.go @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" + tcwait "github.com/testcontainers/testcontainers-go/wait" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/config" @@ -75,9 +76,10 @@ func startTestContainer(ctx context.Context, containerName string, msg string, a )} } req := testcontainers.ContainerRequest{ - Name: containerName, - Image: "ubuntu:latest", - Cmd: cmd, + Name: containerName, + Image: "ubuntu:latest", + Cmd: cmd, + WaitingFor: tcwait.ForLog(msg).WithPollInterval(100 * time.Millisecond).WithStartupTimeout(10 * time.Second), } return testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, @@ -281,17 +283,25 @@ func TestLogStream_GetAllLogs_TwoConsumers_FirstErrorsAfterFiveLogs(t *testing.T lw, err := newDefaultLogStream() require.NoError(t, err) - container_1, err := startTestContainer(ctx, containerName_1, message, amount, interval, false) - require.NoError(t, err) - err = lw.ConnectContainer(context.Background(), container_1, containerName_1) - require.NoError(t, err) + var container_1, container_2 testcontainers.Container - container_2, err := startTestContainer(ctx, containerName_2, message, amount, interval, false) - require.NoError(t, err) + go func() { + var err error + container_1, err = startTestContainer(ctx, containerName_1, message, amount, interval, false) + require.NoError(t, err) + err = lw.ConnectContainer(ctx, container_1, containerName_1) + require.NoError(t, err) + }() - err = lw.ConnectContainer(context.Background(), container_2, containerName_2) - require.NoError(t, err) + go func() { + var err error + container_2, err = startTestContainer(ctx, containerName_2, message, amount, interval, false) + require.NoError(t, err) + + err = lw.ConnectContainer(ctx, container_2, containerName_2) + require.NoError(t, err) + }() time.Sleep(time.Duration(int(interval*float64(amount)))*time.Second + 10*time.Second) @@ -308,7 +318,9 @@ func TestLogStream_GetAllLogs_TwoConsumers_FirstErrorsAfterFiveLogs(t *testing.T } else { logsProcessed[name] = append(logsProcessed[name], string(log.Content)) } - count++ + if name == containerName_1 { + count++ + } return nil } From 733e36c8ae9b3864a38063e7954df21fac355063 Mon Sep 17 00:00:00 2001 From: Balamurali Gopalswami <167726375+b-gopalswami@users.noreply.github.com> Date: Mon, 12 Aug 2024 15:09:39 -0400 Subject: [PATCH 19/26] QA-1405: Adding ZKSync network details (#1053) * QA-1405: Adding ZKSync network details * Toggle case --- networks/known_networks.go | 56 ++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/networks/known_networks.go b/networks/known_networks.go index 5868aa03c..a6e683067 100644 --- a/networks/known_networks.go +++ b/networks/known_networks.go @@ -502,18 +502,6 @@ var ( DefaultGasLimit: 6000000, } - CeloAlfajores = blockchain.EVMNetwork{ - Name: "Celo Alfajores", - SupportsEIP1559: false, - ClientImplementation: blockchain.CeloClientImplementation, - ChainID: 44787, - Simulated: false, - ChainlinkTransactionLimit: 5000, - Timeout: blockchain.StrDuration{Duration: 3 * time.Minute}, - MinimumConfirmations: 1, - GasEstimationBuffer: 1000, - } - ScrollSepolia = blockchain.EVMNetwork{ Name: "Scroll Sepolia", ClientImplementation: blockchain.ScrollClientImplementation, @@ -536,6 +524,19 @@ var ( GasEstimationBuffer: 0, } + CeloAlfajores = blockchain.EVMNetwork{ + Name: "Celo Alfajores", + SupportsEIP1559: false, + ClientImplementation: blockchain.CeloClientImplementation, + ChainID: 44787, + Simulated: false, + ChainlinkTransactionLimit: 5000, + Timeout: blockchain.StrDuration{Duration: 3 * time.Minute}, + MinimumConfirmations: 1, + GasEstimationBuffer: 1000, + FinalityDepth: 10, + } + CeloMainnet = blockchain.EVMNetwork{ Name: "Celo", ClientImplementation: blockchain.CeloClientImplementation, @@ -545,6 +546,7 @@ var ( Timeout: blockchain.StrDuration{Duration: time.Minute}, MinimumConfirmations: 1, GasEstimationBuffer: 1000, + FinalityDepth: 10, } BaseMainnet blockchain.EVMNetwork = blockchain.EVMNetwork{ @@ -881,6 +883,34 @@ var ( DefaultGasLimit: 6000000, } + ZKSyncSepolia = blockchain.EVMNetwork{ + Name: "ZKSync Sepolia", + SupportsEIP1559: false, + ClientImplementation: blockchain.EthereumClientImplementation, + ChainID: 300, + Simulated: false, + ChainlinkTransactionLimit: 5000, + Timeout: blockchain.StrDuration{Duration: 3 * time.Minute}, + MinimumConfirmations: 1, + GasEstimationBuffer: 10000, + FinalityDepth: 200, + DefaultGasLimit: 6000000, + } + + ZKSyncMainnet = blockchain.EVMNetwork{ + Name: "ZKSync Mainnet", + SupportsEIP1559: false, + ClientImplementation: blockchain.EthereumClientImplementation, + ChainID: 324, + Simulated: false, + ChainlinkTransactionLimit: 5000, + Timeout: blockchain.StrDuration{Duration: 3 * time.Minute}, + MinimumConfirmations: 1, + GasEstimationBuffer: 10000, + FinalityDepth: 1200, + DefaultGasLimit: 6000000, + } + MappedNetworks = map[string]blockchain.EVMNetwork{ "SIMULATED": SimulatedEVM, "ANVIL": Anvil, @@ -942,6 +972,8 @@ var ( "BLAST_MAINNET": BlastMainnet, "MODE_SEPOLIA": ModeSepolia, "MODE_MAINNET": ModeMainnet, + "ZKSYNC_SEPOLIA": ZKSyncSepolia, + "ZKSYNC_MAINNET": ZKSyncMainnet, } ) From c248cd988323a194d53a7b61f4c6dfa910038a40 Mon Sep 17 00:00:00 2001 From: David Cauchi <13139524+davidcauchi@users.noreply.github.com> Date: Tue, 20 Aug 2024 13:10:59 +0200 Subject: [PATCH 20/26] Enables Astar (#1076) --- networks/known_networks.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/networks/known_networks.go b/networks/known_networks.go index a6e683067..b3ab936c7 100644 --- a/networks/known_networks.go +++ b/networks/known_networks.go @@ -911,6 +911,34 @@ var ( DefaultGasLimit: 6000000, } + AstarShibuya = blockchain.EVMNetwork{ + Name: "Astar Shibuya", + SupportsEIP1559: true, + ClientImplementation: blockchain.EthereumClientImplementation, + ChainID: 81, + Simulated: false, + ChainlinkTransactionLimit: 5000, + Timeout: blockchain.StrDuration{Duration: 3 * time.Minute}, + MinimumConfirmations: 1, + GasEstimationBuffer: 10000, + FinalityDepth: 100, + DefaultGasLimit: 8000000, + } + + AstarMainnet = blockchain.EVMNetwork{ + Name: "Astar Mainnet", + SupportsEIP1559: true, + ClientImplementation: blockchain.EthereumClientImplementation, + ChainID: 592, + Simulated: false, + ChainlinkTransactionLimit: 5000, + Timeout: blockchain.StrDuration{Duration: 3 * time.Minute}, + MinimumConfirmations: 1, + GasEstimationBuffer: 10000, + FinalityDepth: 100, + DefaultGasLimit: 8000000, + } + MappedNetworks = map[string]blockchain.EVMNetwork{ "SIMULATED": SimulatedEVM, "ANVIL": Anvil, @@ -974,6 +1002,8 @@ var ( "MODE_MAINNET": ModeMainnet, "ZKSYNC_SEPOLIA": ZKSyncSepolia, "ZKSYNC_MAINNET": ZKSyncMainnet, + "ASTAR_SHIBUYA": AstarShibuya, + "ASTAR_MAINNET": AstarMainnet, } ) From a49f2dff000fcf020ab9978b33e3726d7df5bf96 Mon Sep 17 00:00:00 2001 From: Lukasz <120112546+lukaszcl@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:21:36 +0200 Subject: [PATCH 21/26] Update envs for test config (#1077) --- config/env.go | 67 +- config/testconfig.go | 66 ++ config/testconfig_test.go | 9 +- tools/citool/cmd/create_test_config_cmd.go | 179 ----- tools/citool/cmd/csv_export_cmd.go | 2 +- tools/citool/cmd/filter_cmd.go | 16 +- tools/citool/cmd/root_cmd.go | 2 - tools/citool/cmd/test_config_cmd.go | 123 --- tools/citool/cmd/test_config_cmd_test.go | 75 -- tools/citool/cmd/types.go | 11 +- tools/citool/go.mod | 183 +---- tools/citool/go.sum | 850 +-------------------- tools/citool/main.go | 4 +- 13 files changed, 134 insertions(+), 1453 deletions(-) delete mode 100644 tools/citool/cmd/create_test_config_cmd.go delete mode 100644 tools/citool/cmd/test_config_cmd.go delete mode 100644 tools/citool/cmd/test_config_cmd_test.go diff --git a/config/env.go b/config/env.go index 9802e8989..2d19ce4f4 100644 --- a/config/env.go +++ b/config/env.go @@ -7,29 +7,37 @@ import ( "strconv" "strings" + "github.com/smartcontractkit/chainlink-testing-framework/utils" "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" ) const ( - E2E_TEST_LOKI_TENANT_ID_ENV = "E2E_TEST_LOKI_TENANT_ID" - E2E_TEST_LOKI_ENDPOINT_ENV = "E2E_TEST_LOKI_ENDPOINT" - E2E_TEST_LOKI_BASIC_AUTH_ENV = "E2E_TEST_LOKI_BASIC_AUTH" - E2E_TEST_LOKI_BEARER_TOKEN_ENV = "E2E_TEST_LOKI_BEARER_TOKEN" // #nosec G101 - E2E_TEST_GRAFANA_BASE_URL_ENV = "E2E_TEST_GRAFANA_BASE_URL" - E2E_TEST_GRAFANA_DASHBOARD_URL_ENV = "E2E_TEST_GRAFANA_DASHBOARD_URL" - E2E_TEST_GRAFANA_BEARER_TOKEN_ENV = "E2E_TEST_GRAFANA_BEARER_TOKEN" // #nosec G101 - E2E_TEST_PYROSCOPE_ENABLED_ENV = "E2E_TEST_PYROSCOPE_ENABLED" - E2E_TEST_PYROSCOPE_SERVER_URL_ENV = "E2E_TEST_PYROSCOPE_SERVER_URL" - E2E_TEST_PYROSCOPE_KEY_ENV = "E2E_TEST_PYROSCOPE_KEY" - E2E_TEST_PYROSCOPE_ENVIRONMENT_ENV = "E2E_TEST_PYROSCOPE_ENVIRONMENT" - E2E_TEST_CHAINLINK_IMAGE_ENV = "E2E_TEST_CHAINLINK_IMAGE" - E2E_TEST_CHAINLINK_UPGRADE_IMAGE_ENV = "E2E_TEST_CHAINLINK_UPGRADE_IMAGE" - E2E_TEST_WALLET_KEY_ENV = `E2E_TEST_(.+)_WALLET_KEY$` - E2E_TEST_WALLET_KEYS_ENV = `E2E_TEST_(.+)_WALLET_KEY_(\d+)$` - E2E_TEST_RPC_HTTP_URL_ENV = `E2E_TEST_(.+)_RPC_HTTP_URL$` - E2E_TEST_RPC_HTTP_URLS_ENV = `E2E_TEST_(.+)_RPC_HTTP_URL_(\d+)$` - E2E_TEST_RPC_WS_URL_ENV = `E2E_TEST_(.+)_RPC_WS_URL$` - E2E_TEST_RPC_WS_URLS_ENV = `E2E_TEST_(.+)_RPC_WS_URL_(\d+)$` + E2E_TEST_LOG_COLLECT_ENV = "E2E_TEST_LOG_COLLECT" + E2E_TEST_LOGGING_RUN_ID_ENV = "E2E_TEST_LOGGING_RUN_ID" + E2E_TEST_LOG_STREAM_LOG_TARGETS_ENV = "E2E_TEST_LOG_STREAM_LOG_TARGETS" + E2E_TEST_LOKI_TENANT_ID_ENV = "E2E_TEST_LOKI_TENANT_ID" + E2E_TEST_LOKI_ENDPOINT_ENV = "E2E_TEST_LOKI_ENDPOINT" + E2E_TEST_LOKI_BASIC_AUTH_ENV = "E2E_TEST_LOKI_BASIC_AUTH" + E2E_TEST_LOKI_BEARER_TOKEN_ENV = "E2E_TEST_LOKI_BEARER_TOKEN" // #nosec G101 + E2E_TEST_GRAFANA_BASE_URL_ENV = "E2E_TEST_GRAFANA_BASE_URL" + E2E_TEST_GRAFANA_DASHBOARD_URL_ENV = "E2E_TEST_GRAFANA_DASHBOARD_URL" + E2E_TEST_GRAFANA_BEARER_TOKEN_ENV = "E2E_TEST_GRAFANA_BEARER_TOKEN" // #nosec G101 + E2E_TEST_PYROSCOPE_ENABLED_ENV = "E2E_TEST_PYROSCOPE_ENABLED" + E2E_TEST_PYROSCOPE_SERVER_URL_ENV = "E2E_TEST_PYROSCOPE_SERVER_URL" + E2E_TEST_PYROSCOPE_KEY_ENV = "E2E_TEST_PYROSCOPE_KEY" + E2E_TEST_PYROSCOPE_ENVIRONMENT_ENV = "E2E_TEST_PYROSCOPE_ENVIRONMENT" + E2E_TEST_CHAINLINK_IMAGE_ENV = "E2E_TEST_CHAINLINK_IMAGE" + E2E_TEST_CHAINLINK_VERSION_ENV = "E2E_TEST_CHAINLINK_VERSION" + E2E_TEST_CHAINLINK_POSTGRES_VERSION_ENV = "E2E_TEST_CHAINLINK_POSTGRES_VERSION" + E2E_TEST_CHAINLINK_UPGRADE_IMAGE_ENV = "E2E_TEST_CHAINLINK_UPGRADE_IMAGE" + E2E_TEST_CHAINLINK_UPGRADE_VERSION_ENV = "E2E_TEST_CHAINLINK_UPGRADE_VERSION" + E2E_TEST_SELECTED_NETWORK_ENV = `E2E_TEST_SELECTED_NETWORK` + E2E_TEST_WALLET_KEY_ENV = `E2E_TEST_(.+)_WALLET_KEY$` + E2E_TEST_WALLET_KEYS_ENV = `E2E_TEST_(.+)_WALLET_KEY_(\d+)$` + E2E_TEST_RPC_HTTP_URL_ENV = `E2E_TEST_(.+)_RPC_HTTP_URL$` + E2E_TEST_RPC_HTTP_URLS_ENV = `E2E_TEST_(.+)_RPC_HTTP_URL_(\d+)$` + E2E_TEST_RPC_WS_URL_ENV = `E2E_TEST_(.+)_RPC_WS_URL$` + E2E_TEST_RPC_WS_URLS_ENV = `E2E_TEST_(.+)_RPC_WS_URL_(\d+)$` ) func MustReadEnvVar_String(name string) string { @@ -43,6 +51,18 @@ func MustReadEnvVar_String(name string) string { return value.(string) } +func MustReadEnvVar_Strings(name, sep string) []string { + value, err := readEnvVarValue(name, String) + if err != nil { + panic(err) + } + if value == nil { + return nil + } + strVal := value.(string) + return strings.Split(strVal, sep) +} + func MustReadEnvVar_Boolean(name string) *bool { value, err := readEnvVarValue(name, Boolean) if err != nil { @@ -66,7 +86,7 @@ func ReadEnvVarSlice_String(pattern string) []string { } key, value := pair[0], pair[1] if re.MatchString(key) && value != "" { - values = append(values, value) + values = append(values, utils.MustResolveEnvPlaceholder(value)) } } return values @@ -91,8 +111,9 @@ func readEnvVarValue(envVarName string, valueType EnvValueType) (interface{}, er return nil, nil } if isSet && value == "" { - return "", nil // Return "" if the environment variable is not set + return nil, nil } + value = utils.MustResolveEnvPlaceholder(value) // Parse the value according to the specified type switch valueType { @@ -134,7 +155,7 @@ func readEnvVarGroupedMap(pattern string) map[string][]string { matches := re.FindStringSubmatch(key) if len(matches) > 1 && value != "" { group := matches[1] // Use the first capture group for grouping - groupedVars[group] = append(groupedVars[group], value) + groupedVars[group] = append(groupedVars[group], utils.MustResolveEnvPlaceholder(value)) } } return groupedVars @@ -152,7 +173,7 @@ func readEnvVarSingleMap(pattern string) map[string]string { matches := re.FindStringSubmatch(key) if len(matches) > 1 && value != "" { group := matches[1] // Use the first capture group for grouping - singleVars[group] = value + singleVars[group] = utils.MustResolveEnvPlaceholder(value) } } return singleVars diff --git a/config/testconfig.go b/config/testconfig.go index 65b7ade4b..40f87e638 100644 --- a/config/testconfig.go +++ b/config/testconfig.go @@ -52,6 +52,36 @@ type TestConfig struct { func (c *TestConfig) ReadFromEnvVar() error { logger := logging.GetTestLogger(nil) + testLogCollect := MustReadEnvVar_Boolean(E2E_TEST_LOG_COLLECT_ENV) + if testLogCollect != nil { + if c.Logging == nil { + c.Logging = &LoggingConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.TestLogCollect", E2E_TEST_LOG_COLLECT_ENV) + c.Logging.TestLogCollect = testLogCollect + } + + loggingRunID := MustReadEnvVar_String(E2E_TEST_LOGGING_RUN_ID_ENV) + if loggingRunID != "" { + if c.Logging == nil { + c.Logging = &LoggingConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.RunID", E2E_TEST_LOGGING_RUN_ID_ENV) + c.Logging.RunId = &loggingRunID + } + + logstreamLogTargets := MustReadEnvVar_Strings(E2E_TEST_LOG_STREAM_LOG_TARGETS_ENV, ",") + if len(logstreamLogTargets) > 0 { + if c.Logging == nil { + c.Logging = &LoggingConfig{} + } + if c.Logging.LogStream == nil { + c.Logging.LogStream = &LogStreamConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.LogStream.LogTargets", E2E_TEST_LOG_STREAM_LOG_TARGETS_ENV) + c.Logging.LogStream.LogTargets = logstreamLogTargets + } + lokiTenantID := MustReadEnvVar_String(E2E_TEST_LOKI_TENANT_ID_ENV) if lokiTenantID != "" { if c.Logging == nil { @@ -172,6 +202,15 @@ func (c *TestConfig) ReadFromEnvVar() error { c.Pyroscope.Environment = &pyroscopeEnvironment } + selectedNetworks := MustReadEnvVar_Strings(E2E_TEST_SELECTED_NETWORK_ENV, ",") + if len(selectedNetworks) > 0 { + if c.Network == nil { + c.Network = &NetworkConfig{} + } + logger.Debug().Msgf("Using %s env var to override Network.SelectedNetworks", E2E_TEST_SELECTED_NETWORK_ENV) + c.Network.SelectedNetworks = selectedNetworks + } + walletKeys := ReadEnvVarGroupedMap(E2E_TEST_WALLET_KEY_ENV, E2E_TEST_WALLET_KEYS_ENV) if len(walletKeys) > 0 { if c.Network == nil { @@ -208,6 +247,24 @@ func (c *TestConfig) ReadFromEnvVar() error { c.ChainlinkImage.Image = &chainlinkImage } + chainlinkVersion := MustReadEnvVar_String(E2E_TEST_CHAINLINK_VERSION_ENV) + if chainlinkVersion != "" { + if c.ChainlinkImage == nil { + c.ChainlinkImage = &ChainlinkImageConfig{} + } + logger.Debug().Msgf("Using %s env var to override ChainlinkImage.Version", E2E_TEST_CHAINLINK_VERSION_ENV) + c.ChainlinkImage.Version = &chainlinkVersion + } + + chainlinkPostgresVersion := MustReadEnvVar_String(E2E_TEST_CHAINLINK_POSTGRES_VERSION_ENV) + if chainlinkPostgresVersion != "" { + if c.ChainlinkImage == nil { + c.ChainlinkImage = &ChainlinkImageConfig{} + } + logger.Debug().Msgf("Using %s env var to override ChainlinkImage.PostgresVersion", E2E_TEST_CHAINLINK_POSTGRES_VERSION_ENV) + c.ChainlinkImage.PostgresVersion = &chainlinkPostgresVersion + } + chainlinkUpgradeImage := MustReadEnvVar_String(E2E_TEST_CHAINLINK_UPGRADE_IMAGE_ENV) if chainlinkUpgradeImage != "" { if c.ChainlinkUpgradeImage == nil { @@ -217,6 +274,15 @@ func (c *TestConfig) ReadFromEnvVar() error { c.ChainlinkUpgradeImage.Image = &chainlinkUpgradeImage } + chainlinkUpgradeVersion := MustReadEnvVar_String(E2E_TEST_CHAINLINK_UPGRADE_VERSION_ENV) + if chainlinkUpgradeVersion != "" { + if c.ChainlinkUpgradeImage == nil { + c.ChainlinkUpgradeImage = &ChainlinkImageConfig{} + } + logger.Debug().Msgf("Using %s env var to override ChainlinkUpgradeImage.Version", E2E_TEST_CHAINLINK_UPGRADE_VERSION_ENV) + c.ChainlinkUpgradeImage.Version = &chainlinkUpgradeVersion + } + return nil } diff --git a/config/testconfig_test.go b/config/testconfig_test.go index fd67c7d9c..16807fe65 100644 --- a/config/testconfig_test.go +++ b/config/testconfig_test.go @@ -25,6 +25,7 @@ func TestReadConfigValuesFromEnvVars(t *testing.T) { os.Setenv("E2E_TEST_GROUP3_RPC_WS_URL_1", "wsUrl1") os.Setenv("E2E_TEST_CHAINLINK_IMAGE", "imageValue") os.Setenv("E2E_TEST_PYROSCOPE_ENABLED", "true") + os.Setenv("E2E_TEST_SELECTED_NETWORK", "networkA,networkB") }, cleanupFunc: func() { os.Unsetenv("E2E_TEST_GROUP1_WALLET_KEY_1") @@ -32,12 +33,14 @@ func TestReadConfigValuesFromEnvVars(t *testing.T) { os.Unsetenv("E2E_TEST_GROUP3_RPC_WS_URL_1") os.Unsetenv("E2E_TEST_CHAINLINK_IMAGE") os.Unsetenv("E2E_TEST_PYROSCOPE_ENABLED") + os.Unsetenv("E2E_TEST_SELECTED_NETWORK") }, expectedConfig: TestConfig{ Network: &NetworkConfig{ - WalletKeys: map[string][]string{"GROUP1": {"walletValue1"}}, - RpcHttpUrls: map[string][]string{"GROUP2": {"httpUrl1"}}, - RpcWsUrls: map[string][]string{"GROUP3": {"wsUrl1"}}, + SelectedNetworks: []string{"networkA", "networkB"}, + WalletKeys: map[string][]string{"GROUP1": {"walletValue1"}}, + RpcHttpUrls: map[string][]string{"GROUP2": {"httpUrl1"}}, + RpcWsUrls: map[string][]string{"GROUP3": {"wsUrl1"}}, }, Pyroscope: &PyroscopeConfig{Enabled: ptr.Ptr[bool](true)}, ChainlinkImage: &ChainlinkImageConfig{Image: newString("imageValue")}, diff --git a/tools/citool/cmd/create_test_config_cmd.go b/tools/citool/cmd/create_test_config_cmd.go deleted file mode 100644 index c0cd91b05..000000000 --- a/tools/citool/cmd/create_test_config_cmd.go +++ /dev/null @@ -1,179 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - - "github.com/pelletier/go-toml/v2" - "github.com/spf13/cobra" - - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" -) - -var createTestConfigCmd = &cobra.Command{ - Use: "create", - Short: "Create a test config from the provided flags", - Run: func(cmd *cobra.Command, _ []string) { - var tc ctf_config.TestConfig - - var version, postgresVersion *string - if cmd.Flags().Changed(ChainlinkVersionFlag) { - version = &oc.ChainlinkVersion - } - if cmd.Flags().Changed(ChainlinkPostgresVersionFlag) { - version = &oc.ChainlinkPostgresVersion - } - if version != nil || postgresVersion != nil { - tc.ChainlinkImage = &ctf_config.ChainlinkImageConfig{ - Version: version, - PostgresVersion: postgresVersion, - } - } - - var upgradeVersion *string - if cmd.Flags().Changed(ChainlinkUpgradeVersionFlag) { - upgradeVersion = &oc.ChainlinkUpgradeVersion - } - if upgradeVersion != nil { - tc.ChainlinkUpgradeImage = &ctf_config.ChainlinkImageConfig{ - Version: upgradeVersion, - } - } - - var selectedNetworks *[]string - if cmd.Flags().Changed(SelectedNetworksFlag) { - selectedNetworks = &oc.SelectedNetworks - } - if selectedNetworks != nil { - tc.Network = &ctf_config.NetworkConfig{ - SelectedNetworks: oc.SelectedNetworks, - } - } - - var peryscopeEnabled *bool - var pyroscopeServerURL, pyroscopeEnvironment, pyroscopeKey *string - if cmd.Flags().Changed(PyroscopeEnabledFlag) { - peryscopeEnabled = &oc.PyroscopeEnabled - } - if cmd.Flags().Changed(PyroscopeServerURLFlag) { - pyroscopeServerURL = &oc.PyroscopeServerURL - } - if cmd.Flags().Changed(PyroscopeKeyFlag) { - pyroscopeKey = &oc.PyroscopeKey - } - if cmd.Flags().Changed(PyroscopeEnvironmentFlag) { - pyroscopeEnvironment = &oc.PyroscopeEnvironment - } - if peryscopeEnabled != nil { - tc.Pyroscope = &ctf_config.PyroscopeConfig{ - Enabled: peryscopeEnabled, - ServerUrl: pyroscopeServerURL, - Environment: pyroscopeEnvironment, - Key: pyroscopeKey, - } - } - - var testLogCollect *bool - if cmd.Flags().Changed(LoggingTestLogCollectFlag) { - testLogCollect = &oc.LoggingTestLogCollect - } - var loggingRunID *string - if cmd.Flags().Changed(LoggingRunIDFlag) { - loggingRunID = &oc.LoggingRunID - } - var loggingLogTargets []string - if cmd.Flags().Changed(LoggingLogTargetsFlag) { - loggingLogTargets = oc.LoggingLogTargets - } - var loggingLokiTenantID *string - if cmd.Flags().Changed(LoggingLokiTenantIDFlag) { - loggingLokiTenantID = &oc.LoggingLokiTenantID - } - var loggingLokiBasicAuth *string - if cmd.Flags().Changed(LoggingLokiBasicAuthFlag) { - loggingLokiBasicAuth = &oc.LoggingLokiBasicAuth - } - var loggingLokiEndpoint *string - if cmd.Flags().Changed(LoggingLokiEndpointFlag) { - loggingLokiEndpoint = &oc.LoggingLokiEndpoint - } - var loggingGrafanaBaseURL *string - if cmd.Flags().Changed(LoggingGrafanaBaseURLFlag) { - loggingGrafanaBaseURL = &oc.LoggingGrafanaBaseURL - } - var loggingGrafanaDashboardURL *string - if cmd.Flags().Changed(LoggingGrafanaDashboardURLFlag) { - loggingGrafanaDashboardURL = &oc.LoggingGrafanaDashboardURL - } - var loggingGrafanaBearerToken *string - if cmd.Flags().Changed(LoggingGrafanaBearerTokenFlag) { - loggingGrafanaBearerToken = &oc.LoggingGrafanaBearerToken - } - - if testLogCollect != nil || loggingRunID != nil || loggingLogTargets != nil || loggingLokiEndpoint != nil || loggingLokiTenantID != nil || loggingLokiBasicAuth != nil || loggingGrafanaBaseURL != nil || loggingGrafanaDashboardURL != nil || loggingGrafanaBearerToken != nil { - tc.Logging = &ctf_config.LoggingConfig{} - tc.Logging.TestLogCollect = testLogCollect - tc.Logging.RunId = loggingRunID - if loggingLogTargets != nil { - tc.Logging.LogStream = &ctf_config.LogStreamConfig{ - LogTargets: loggingLogTargets, - } - } - if loggingLokiTenantID != nil || loggingLokiBasicAuth != nil || loggingLokiEndpoint != nil { - tc.Logging.Loki = &ctf_config.LokiConfig{ - TenantId: loggingLokiTenantID, - BasicAuth: loggingLokiBasicAuth, - Endpoint: loggingLokiEndpoint, - } - } - if loggingGrafanaBaseURL != nil || loggingGrafanaDashboardURL != nil || loggingGrafanaBearerToken != nil { - tc.Logging.Grafana = &ctf_config.GrafanaConfig{ - BaseUrl: loggingGrafanaBaseURL, - DashboardUrl: loggingGrafanaDashboardURL, - BearerToken: loggingGrafanaBearerToken, - } - } - } - - var privateEthereumNetworkExecutionLayer *string - if cmd.Flags().Changed(PrivateEthereumNetworkExecutionLayerFlag) { - privateEthereumNetworkExecutionLayer = &oc.PrivateEthereumNetworkExecutionLayer - } - var privateEthereumNetworkEthereumVersion *string - if cmd.Flags().Changed(PrivateEthereumNetworkEthereumVersionFlag) { - privateEthereumNetworkEthereumVersion = &oc.PrivateEthereumNetworkEthereumVersion - } - var privateEthereumNetworkCustomDockerImage *string - if cmd.Flags().Changed(PrivateEthereumNetworkCustomDockerImageFlag) { - privateEthereumNetworkCustomDockerImage = &oc.PrivateEthereumNetworkCustomDockerImages - } - if privateEthereumNetworkExecutionLayer != nil || privateEthereumNetworkEthereumVersion != nil || privateEthereumNetworkCustomDockerImage != nil { - var el ctf_config_types.ExecutionLayer - if privateEthereumNetworkExecutionLayer != nil { - el = ctf_config_types.ExecutionLayer(*privateEthereumNetworkExecutionLayer) - } - var ev ctf_config_types.EthereumVersion - if privateEthereumNetworkEthereumVersion != nil { - ev = ctf_config_types.EthereumVersion(*privateEthereumNetworkEthereumVersion) - } - var customImages map[ctf_config.ContainerType]string - if privateEthereumNetworkCustomDockerImage != nil { - customImages = map[ctf_config.ContainerType]string{"execution_layer": *privateEthereumNetworkCustomDockerImage} - } - tc.PrivateEthereumNetwork = &ctf_config.EthereumNetworkConfig{ - ExecutionLayer: &el, - EthereumVersion: &ev, - CustomDockerImages: customImages, - } - } - - configToml, err := toml.Marshal(tc) - if err != nil { - fmt.Fprintf(os.Stderr, "Error marshalling TestConfig to TOML: %v\n", err) - os.Exit(1) - } - - fmt.Fprintln(cmd.OutOrStdout(), string(configToml)) - }, -} diff --git a/tools/citool/cmd/csv_export_cmd.go b/tools/citool/cmd/csv_export_cmd.go index 8fe13440c..29e16397b 100644 --- a/tools/citool/cmd/csv_export_cmd.go +++ b/tools/citool/cmd/csv_export_cmd.go @@ -64,7 +64,7 @@ func exportConfigToCSV(configFile string) error { for _, test := range config.Tests { workflows := strings.Join(test.Workflows, ", ") // Combine workflows into a single CSV field // Serialize TestInputs - testInputs := serializeMap(test.TestInputs) + testInputs := serializeMap(test.TestEnvVars) record := []string{ test.ID, diff --git a/tools/citool/cmd/filter_cmd.go b/tools/citool/cmd/filter_cmd.go index c1d5f2235..3f6ec92ad 100644 --- a/tools/citool/cmd/filter_cmd.go +++ b/tools/citool/cmd/filter_cmd.go @@ -33,8 +33,8 @@ func filterTests(allTests []CITestConf, workflow, testType, ids string, envresol filteredTests = append(filteredTests, test) } if envresolve { - for k, v := range test.TestInputs { - test.TestInputs[k] = utils.MustResolveEnvPlaceholder(v) + for k, v := range test.TestEnvVars { + test.TestEnvVars[k] = utils.MustResolveEnvPlaceholder(v) } } } @@ -65,18 +65,18 @@ func filterAndMergeTests(allTests []CITestConf, workflow, testType, base64Tests if decodedTest, exists := idFilter[test.ID]; exists && workflowMatch && typeMatch { // Override test inputs from the base64 encoded tests - for k, v := range decodedTest.TestInputs { - if test.TestInputs == nil { - test.TestInputs = make(map[string]string) + for k, v := range decodedTest.TestEnvVars { + if test.TestEnvVars == nil { + test.TestEnvVars = make(map[string]string) } - test.TestInputs[k] = v + test.TestEnvVars[k] = v } test.IDSanitized = sanitizeTestID(test.ID) filteredTests = append(filteredTests, test) } if envresolve { - for k, v := range test.TestInputs { - test.TestInputs[k] = utils.MustResolveEnvPlaceholder(v) + for k, v := range test.TestEnvVars { + test.TestEnvVars[k] = utils.MustResolveEnvPlaceholder(v) } } } diff --git a/tools/citool/cmd/root_cmd.go b/tools/citool/cmd/root_cmd.go index fdb4efd57..f9eb6dbb4 100644 --- a/tools/citool/cmd/root_cmd.go +++ b/tools/citool/cmd/root_cmd.go @@ -27,6 +27,4 @@ func init() { rootCmd.AddCommand(checkTestsCmd) rootCmd.AddCommand(filterCmd) rootCmd.AddCommand(csvExportCmd) - rootCmd.AddCommand(testConfigCmd) - testConfigCmd.AddCommand(createTestConfigCmd) } diff --git a/tools/citool/cmd/test_config_cmd.go b/tools/citool/cmd/test_config_cmd.go deleted file mode 100644 index 0c0e27235..000000000 --- a/tools/citool/cmd/test_config_cmd.go +++ /dev/null @@ -1,123 +0,0 @@ -package cmd - -import ( - "strings" - - "github.com/spf13/cobra" - - "github.com/smartcontractkit/chainlink-testing-framework/utils" -) - -var testConfigCmd = &cobra.Command{ - Use: "test-config", - Short: "Manage test config", -} - -// OverrideConfig holds the configuration data for overrides -type OverrideConfig struct { - ChainlinkImage string - ChainlinkVersion string - ChainlinkUpgradeImage string - ChainlinkUpgradeVersion string - ChainlinkPostgresVersion string - SelectedNetworks []string - PyroscopeEnabled bool - PyroscopeServerURL string - PyroscopeEnvironment string - PyroscopeKey string - LoggingTestLogCollect bool - LoggingRunID string - LoggingLogTargets []string - LoggingLokiTenantID string - LoggingLokiEndpoint string - LoggingLokiBasicAuth string - LoggingGrafanaBaseURL string - LoggingGrafanaDashboardURL string - LoggingGrafanaBearerToken string - PrivateEthereumNetworkExecutionLayer string - PrivateEthereumNetworkEthereumVersion string - PrivateEthereumNetworkCustomDockerImages string -} - -const ( - ChainlinkVersionFlag = "chainlink-version" - ChainlinkUpgradeVersionFlag = "chainlink-upgrade-version" - ChainlinkPostgresVersionFlag = "chainlink-postgres-version" - SelectedNetworksFlag = "selected-networks" - FromBase64ConfigFlag = "from-base64-config" - LoggingLokiBasicAuthFlag = "logging-loki-basic-auth" - LoggingLokiEndpointFlag = "logging-loki-endpoint" - LoggingRunIDFlag = "logging-run-id" - LoggingLokiTenantIDFlag = "logging-loki-tenant-id" - LoggingGrafanaBaseURLFlag = "logging-grafana-base-url" - LoggingGrafanaDashboardURLFlag = "logging-grafana-dashboard-url" - LoggingGrafanaBearerTokenFlag = "logging-grafana-bearer-token" - LoggingLogTargetsFlag = "logging-log-targets" - LoggingTestLogCollectFlag = "logging-test-log-collect" - PyroscopeEnabledFlag = "pyroscope-enabled" - PyroscopeServerURLFlag = "pyroscope-server-url" - PyroscopeKeyFlag = "pyroscope-key" - PyroscopeEnvironmentFlag = "pyroscope-environment" - PrivateEthereumNetworkExecutionLayerFlag = "private-ethereum-network-execution-layer" - PrivateEthereumNetworkEthereumVersionFlag = "private-ethereum-network-ethereum-version" - PrivateEthereumNetworkCustomDockerImageFlag = "private-ethereum-network-custom-docker-image" -) - -var oc OverrideConfig - -func init() { - cmds := []*cobra.Command{createTestConfigCmd} - for _, c := range cmds { - c.Flags().StringArrayVar(&oc.SelectedNetworks, SelectedNetworksFlag, nil, "Selected networks") - c.Flags().StringVar(&oc.ChainlinkVersion, ChainlinkVersionFlag, "", "Chainlink version") - c.Flags().StringVar(&oc.ChainlinkUpgradeVersion, ChainlinkUpgradeVersionFlag, "", "Chainlink upgrade version") - c.Flags().StringVar(&oc.ChainlinkPostgresVersion, ChainlinkPostgresVersionFlag, "", "Chainlink Postgres version") - c.Flags().BoolVar(&oc.PyroscopeEnabled, PyroscopeEnabledFlag, false, "Pyroscope enabled") - c.Flags().StringVar(&oc.PyroscopeServerURL, PyroscopeServerURLFlag, "", "Pyroscope server URL") - c.Flags().StringVar(&oc.PyroscopeKey, PyroscopeKeyFlag, "", "Pyroscope key") - c.Flags().StringVar(&oc.PyroscopeEnvironment, PyroscopeEnvironmentFlag, "", "Pyroscope environment") - c.Flags().BoolVar(&oc.LoggingTestLogCollect, LoggingTestLogCollectFlag, false, "Test log collect") - c.Flags().StringVar(&oc.LoggingRunID, LoggingRunIDFlag, "", "Run ID") - c.Flags().StringArrayVar(&oc.LoggingLogTargets, LoggingLogTargetsFlag, nil, "Logging.LogStream.LogTargets") - c.Flags().StringVar(&oc.LoggingLokiEndpoint, LoggingLokiEndpointFlag, "", "") - c.Flags().StringVar(&oc.LoggingLokiTenantID, LoggingLokiTenantIDFlag, "", "") - c.Flags().StringVar(&oc.LoggingLokiBasicAuth, LoggingLokiBasicAuthFlag, "", "") - c.Flags().StringVar(&oc.LoggingGrafanaBaseURL, LoggingGrafanaBaseURLFlag, "", "") - c.Flags().StringVar(&oc.LoggingGrafanaDashboardURL, LoggingGrafanaDashboardURLFlag, "", "") - c.Flags().StringVar(&oc.LoggingGrafanaBearerToken, LoggingGrafanaBearerTokenFlag, "", "") - c.Flags().StringVar(&oc.PrivateEthereumNetworkExecutionLayer, PrivateEthereumNetworkExecutionLayerFlag, "", "") - c.Flags().StringVar(&oc.PrivateEthereumNetworkEthereumVersion, PrivateEthereumNetworkEthereumVersionFlag, "", "") - c.Flags().StringVar(&oc.PrivateEthereumNetworkCustomDockerImages, PrivateEthereumNetworkCustomDockerImageFlag, "", "") - - c.PreRun = func(_ *cobra.Command, _ []string) { - // Resolve selected networks environment variable if set - if len(oc.SelectedNetworks) > 0 { - _, hasEnvVar := utils.LookupEnvVarName(oc.SelectedNetworks[0]) - if hasEnvVar { - selectedNetworks := utils.MustResolveEnvPlaceholder(oc.SelectedNetworks[0]) - oc.SelectedNetworks = strings.Split(selectedNetworks, ",") - } - } - - // Resolve all other environment variables - oc.ChainlinkImage = utils.MustResolveEnvPlaceholder(oc.ChainlinkImage) - oc.ChainlinkVersion = utils.MustResolveEnvPlaceholder(oc.ChainlinkVersion) - oc.ChainlinkUpgradeImage = utils.MustResolveEnvPlaceholder(oc.ChainlinkUpgradeImage) - oc.ChainlinkUpgradeVersion = utils.MustResolveEnvPlaceholder(oc.ChainlinkUpgradeVersion) - oc.ChainlinkPostgresVersion = utils.MustResolveEnvPlaceholder(oc.ChainlinkPostgresVersion) - oc.PyroscopeServerURL = utils.MustResolveEnvPlaceholder(oc.PyroscopeServerURL) - oc.PyroscopeKey = utils.MustResolveEnvPlaceholder(oc.PyroscopeKey) - oc.PyroscopeEnvironment = utils.MustResolveEnvPlaceholder(oc.PyroscopeEnvironment) - oc.LoggingRunID = utils.MustResolveEnvPlaceholder(oc.LoggingRunID) - oc.LoggingLokiTenantID = utils.MustResolveEnvPlaceholder(oc.LoggingLokiTenantID) - oc.LoggingLokiEndpoint = utils.MustResolveEnvPlaceholder(oc.LoggingLokiEndpoint) - oc.LoggingLokiBasicAuth = utils.MustResolveEnvPlaceholder(oc.LoggingLokiBasicAuth) - oc.LoggingGrafanaBaseURL = utils.MustResolveEnvPlaceholder(oc.LoggingGrafanaBaseURL) - oc.LoggingGrafanaDashboardURL = utils.MustResolveEnvPlaceholder(oc.LoggingGrafanaDashboardURL) - oc.LoggingGrafanaBearerToken = utils.MustResolveEnvPlaceholder(oc.LoggingGrafanaBearerToken) - oc.PrivateEthereumNetworkExecutionLayer = utils.MustResolveEnvPlaceholder(oc.PrivateEthereumNetworkExecutionLayer) - oc.PrivateEthereumNetworkEthereumVersion = utils.MustResolveEnvPlaceholder(oc.PrivateEthereumNetworkEthereumVersion) - oc.PrivateEthereumNetworkCustomDockerImages = utils.MustResolveEnvPlaceholder(oc.PrivateEthereumNetworkCustomDockerImages) - } - } -} diff --git a/tools/citool/cmd/test_config_cmd_test.go b/tools/citool/cmd/test_config_cmd_test.go deleted file mode 100644 index 79185e608..000000000 --- a/tools/citool/cmd/test_config_cmd_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package cmd - -import ( - "bytes" - "testing" - - "github.com/pelletier/go-toml/v2" - "github.com/spf13/cobra" - "github.com/stretchr/testify/assert" - - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" -) - -func TestCreateTestConfigCmd(t *testing.T) { - tests := []struct { - name string - args []string - want interface{} - check func(t *testing.T, tc *ctf_config.TestConfig) - wantErr bool - }{ - { - name: "LoggingLogTargets", - args: []string{"create", "--logging-log-targets=target1", "--logging-log-targets=target2"}, - check: func(t *testing.T, tc *ctf_config.TestConfig) { - assert.NotNil(t, tc.Logging) - assert.NotNil(t, tc.Logging.LogStream) - assert.Equal(t, []string{"target1", "target2"}, tc.Logging.LogStream.LogTargets) - }, - }, - { - name: "PrivateEthereumNetworkExecutionLayerFlag", - args: []string{"create", "--private-ethereum-network-execution-layer=geth", "--private-ethereum-network-ethereum-version=1.10.0"}, - check: func(t *testing.T, tc *ctf_config.TestConfig) { - assert.NotNil(t, tc.PrivateEthereumNetwork) - assert.NotNil(t, tc.PrivateEthereumNetwork.ExecutionLayer) - assert.Equal(t, ctf_config_types.ExecutionLayer("geth"), *tc.PrivateEthereumNetwork.ExecutionLayer) - assert.Equal(t, ctf_config_types.EthereumVersion("1.10.0"), *tc.PrivateEthereumNetwork.EthereumVersion) - }, - }, - { - name: "PrivateEthereumNetworkCustomDockerImageFlag", - args: []string{"create", "--private-ethereum-network-execution-layer=geth", "--private-ethereum-network-ethereum-version=1.10.0", "--private-ethereum-network-custom-docker-image=custom-image:v1.0"}, - check: func(t *testing.T, tc *ctf_config.TestConfig) { - assert.NotNil(t, tc.PrivateEthereumNetwork) - assert.NotNil(t, tc.PrivateEthereumNetwork.ExecutionLayer) - assert.Equal(t, map[ctf_config.ContainerType]string{"execution_layer": "custom-image:v1.0"}, tc.PrivateEthereumNetwork.CustomDockerImages) - }, - }, - } - - rootCmd := &cobra.Command{} - rootCmd.AddCommand(createTestConfigCmd) - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - rootCmd.SetArgs(tt.args) - var out bytes.Buffer - rootCmd.SetOutput(&out) - err := rootCmd.Execute() - if (err != nil) != tt.wantErr { - t.Fatalf("Execute() error = %v, wantErr %v", err, tt.wantErr) - } - var tc ctf_config.TestConfig - err = toml.Unmarshal(out.Bytes(), &tc) - if err != nil { - t.Fatalf("Failed to unmarshal output: %v", err) - } - if tt.check != nil { - tt.check(t, &tc) - } - }) - } -} diff --git a/tools/citool/cmd/types.go b/tools/citool/cmd/types.go index 3c347e940..3508f9a15 100644 --- a/tools/citool/cmd/types.go +++ b/tools/citool/cmd/types.go @@ -13,11 +13,12 @@ type CITestConf struct { TestEnvType string `yaml:"test_env_type" json:"test_env_type"` RunsOn string `yaml:"runs_on" json:"runs_on"` TestCmd string `yaml:"test_cmd" json:"test_cmd"` - TestConfigOverrideRequired bool `yaml:"test_config_override_required" json:"testConfigOverrideRequired"` - TestSecretsRequired bool `yaml:"test_secrets_required" json:"testSecretsRequired"` - TestInputs map[string]string `yaml:"test_inputs" json:"test_inputs"` - RemoteRunnerMemory string `yaml:"remote_runner_memory" json:"remoteRunnerMemory"` - PyroscopeEnv string `yaml:"pyroscope_env" json:"pyroscopeEnv"` + TestConfigOverrideRequired bool `yaml:"test_config_override_required" json:"test_config_override_required"` + TestConfigOverridePath string `yaml:"test_config_override_path" json:"test_config_override_path"` + TestSecretsRequired bool `yaml:"test_secrets_required" json:"test_secrets_required"` + TestEnvVars map[string]string `yaml:"test_env_vars" json:"test_env_vars"` + RemoteRunnerMemory string `yaml:"remote_runner_memory" json:"remote_runner_memory"` + PyroscopeEnv string `yaml:"pyroscope_env" json:"pyroscope_env"` Workflows []string `yaml:"workflows" json:"workflows"` } diff --git a/tools/citool/go.mod b/tools/citool/go.mod index 99c3d3e72..2e6210418 100644 --- a/tools/citool/go.mod +++ b/tools/citool/go.mod @@ -2,197 +2,16 @@ module github.com/smartcontractkit/chainlink-testing-framework/tools/citool go 1.22.5 -replace ( - github.com/go-kit/log => github.com/go-kit/log v0.2.1 - - // replicating the replace directive on cosmos SDK - github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 - -) - require ( - github.com/pelletier/go-toml/v2 v2.2.2 github.com/smartcontractkit/chainlink-testing-framework v1.34.2 - github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240809091712-98b90543972d github.com/spf13/cobra v1.8.1 - github.com/stretchr/testify v1.9.0 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 ) require ( - dario.cat/mergo v1.0.0 // indirect - github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/DataDog/zstd v1.5.2 // indirect - github.com/MakeNowJust/heredoc v1.0.0 // indirect - github.com/Masterminds/semver/v3 v3.2.1 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/Microsoft/hcsshim v0.11.4 // indirect - github.com/VictoriaMetrics/fastcache v1.12.1 // indirect - github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect - github.com/avast/retry-go v3.0.0+incompatible // indirect - github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect - github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect - github.com/aws/jsii-runtime-go v1.75.0 // indirect - github.com/benbjohnson/clock v1.3.5 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.10.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect - github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect - github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/chai2010/gettext-go v1.0.2 // indirect - github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f // indirect - github.com/cockroachdb/errors v1.9.1 // indirect - github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect - github.com/cockroachdb/redact v1.1.3 // indirect - github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/consensys/bavard v0.1.13 // indirect - github.com/consensys/gnark-crypto v0.12.1 // indirect - github.com/containerd/containerd v1.7.12 // indirect - github.com/containerd/log v0.1.0 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect - github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect - github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/deckarep/golang-set/v2 v2.6.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect - github.com/distribution/reference v0.5.0 // indirect - github.com/docker/docker v25.0.2+incompatible // indirect - github.com/docker/go-connections v0.5.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/emicklei/go-restful/v3 v3.12.1 // indirect - github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/ethereum/go-ethereum v1.13.8 // indirect - github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.9.0 // indirect - github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect - github.com/fatih/camelcase v1.0.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/fvbommel/sortorder v1.1.0 // indirect - github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect - github.com/getsentry/sentry-go v0.19.0 // indirect - github.com/go-errors/errors v1.4.2 // indirect - github.com/go-logr/logr v1.4.2 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/jsonreference v0.21.0 // indirect - github.com/go-openapi/swag v0.23.0 // indirect - github.com/go-resty/resty/v2 v2.11.0 // indirect - github.com/gofrs/flock v0.8.1 // indirect - github.com/gogo/protobuf v1.3.3 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect - github.com/google/btree v1.1.2 // indirect - github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.1 // indirect - github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect - github.com/holiman/bloomfilter/v2 v2.0.3 // indirect - github.com/holiman/uint256 v1.2.4 // indirect - github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/joho/godotenv v1.5.1 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/klauspost/compress v1.17.3 // indirect - github.com/kr/pretty v0.3.1 // indirect - github.com/kr/text v0.2.0 // indirect - github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect - github.com/mitchellh/go-wordwrap v1.0.1 // indirect - github.com/mmcloughlin/addchain v0.4.0 // indirect - github.com/moby/patternmatcher v0.6.0 // indirect - github.com/moby/spdystream v0.4.0 // indirect - github.com/moby/sys/sequential v0.5.0 // indirect - github.com/moby/sys/user v0.1.0 // indirect - github.com/moby/term v0.5.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect - github.com/montanaflynn/stats v0.7.1 // indirect - github.com/morikuni/aec v1.0.0 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0-rc5 // indirect - github.com/peterbourgon/diskv v2.0.1+incompatible // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/prometheus/client_golang v1.19.1 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - github.com/rs/zerolog v1.31.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/shirou/gopsutil v3.21.11+incompatible // indirect - github.com/shirou/gopsutil/v3 v3.24.3 // indirect - github.com/shoenig/go-m1cpu v0.1.6 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/seth v1.1.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/supranational/blst v0.3.11 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect - github.com/testcontainers/testcontainers-go v0.28.0 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect - github.com/xlab/treeprint v1.2.0 // indirect - github.com/yusufpapurcu/wmi v1.2.4 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect - go.opentelemetry.io/otel v1.28.0 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect - go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect - go.uber.org/atomic v1.11.0 // indirect - go.uber.org/ratelimit v0.3.0 // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/term v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.23.0 // indirect - gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/grpc v1.65.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - k8s.io/api v0.28.2 // indirect - k8s.io/apiextensions-apiserver v0.28.2 // indirect - k8s.io/apimachinery v0.28.2 // indirect - k8s.io/cli-runtime v0.28.2 // indirect - k8s.io/client-go v0.28.2 // indirect - k8s.io/component-base v0.28.2 // indirect - k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f // indirect - k8s.io/kubectl v0.28.2 // indirect - k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect - rsc.io/tmplfunc v0.0.3 // indirect - sigs.k8s.io/controller-runtime v0.16.2 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect - sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) diff --git a/tools/citool/go.sum b/tools/citool/go.sum index 76e3a8a7b..1128e8663 100644 --- a/tools/citool/go.sum +++ b/tools/citool/go.sum @@ -1,874 +1,26 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= -github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= -github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= -github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= -github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= -github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= -github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= -github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= -github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= -github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= -github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= -github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 h1:t3eaIm0rUkzbrIewtiFmMK5RXHej2XnoXNhxVsAYUfg= -github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= -github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= -github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= -github.com/awalterschulze/gographviz v2.0.3+incompatible h1:9sVEXJBJLwGX7EQVhLm2elIKCm7P2YHFC8v6096G09E= -github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs= -github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3sWOxO2Dfja0iA1W7ZcI7g= -github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= -github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= -github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYSN6/mGyHI6O3I= -github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= -github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= -github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= -github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= -github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= -github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= -github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= -github.com/bxcodec/faker v2.0.1+incompatible/go.mod h1:BNzfpVdTwnFJ6GtfYTcQu6l6rHShT+veBxNCnjCx5XM= -github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 h1:rvc39Ol6z3MvaBzXkxFC6Nfsnixq/dRypushKDd7Nc0= -github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5/go.mod h1:R/pdNYDYFQk+tuuOo7QES1kkv6OLmp5ze2XBZQIVffM= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= -github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= -github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= -github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f h1:onZ3oc6l1Gz8pVpQ0c1U1Cb11kIMoDb3xtEy/iZbYZM= -github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f/go.mod h1:x11iCbZV6hzzSQWMq610B6Wl5Lg1dhwqcVfeiWQQnQQ= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= -github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= -github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= -github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= -github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= -github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= -github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= -github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= -github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= -github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= -github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= -github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= -github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= -github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= -github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= -github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v25.0.2+incompatible h1:/OaKeauroa10K4Nqavw4zlhcDq/WBcPMc5DbjOGgozY= -github.com/docker/docker v25.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= -github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= -github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= -github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= -github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= -github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= -github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= -github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= -github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= -github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= -github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= -github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= -github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= -github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= -github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= -github.com/getsentry/sentry-go v0.19.0 h1:BcCH3CN5tXt5aML+gwmbFwVptLLQA+eT866fCO9wVOM= -github.com/getsentry/sentry-go v0.19.0/go.mod h1:y3+lGEFEFexZtpbG1GUE2WD/f9zGyKYwpEqryTOC/nE= -github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= -github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= -github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= -github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= -github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= -github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= -github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= -github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= -github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= -github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= -github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= -github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= -github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= -github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= -github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= -github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= -github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= -github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= -github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= -github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= -github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= -github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= -github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= -github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= -github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= -github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= -github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= -github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= -github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= -github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= -github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= -github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= -github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= -github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= -github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= -github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= -github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= -github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= -github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= -github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= -github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= -github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= -github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= -github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= -github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= -github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= -github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= -github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= -github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= -github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= -github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= -github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= -github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= -github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= -github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= -github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= -github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= -github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= -github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= -github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= -github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= -github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= -github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartcontractkit/chainlink-testing-framework v1.34.2 h1:YL3ft7KJB7SAopdmJeyeR4/kv0j4jOdagNihXq8OZ38= github.com/smartcontractkit/chainlink-testing-framework v1.34.2/go.mod h1:hRZEDh2+afO8MSZb9qYNscmWb+3mHZf01J5ACZuIdTQ= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240809091712-98b90543972d h1:6FxG5HxqBChkibqk8w3sOtrdQjgoquz44gBA6+IcBDA= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240809091712-98b90543972d/go.mod h1:dvQ1dAmlXaz9i1vzq9jpuLH33krZNC9E+ziHgqwIxws= -github.com/smartcontractkit/seth v1.1.1 h1:6hvexjJD7ek8ht/CLlEwQcH21K2E/WEYwbSRdKInZmM= -github.com/smartcontractkit/seth v1.1.1/go.mod h1:cDfKHi/hJLpO9sRpVbrflrHCOV+MJPAMJHloExJnIXk= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= -github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= -github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= -github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= -github.com/testcontainers/testcontainers-go v0.28.0 h1:1HLm9qm+J5VikzFDYhOd+Zw12NtOl+8drH2E8nTY1r8= -github.com/testcontainers/testcontainers-go v0.28.0/go.mod h1:COlDpUXbwW3owtpMkEB1zo9gwb1CoKVKlyrVPejF4AU= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli v1.22.12 h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8= -github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= -github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= -github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= -github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= -github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= -github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= -github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= -github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= -go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= -go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= -go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= -go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= -go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/ratelimit v0.3.0 h1:IdZd9wqvFXnvLvSEBo0KPcGfkoBGNkpTHlrE3Rcjkjw= -go.uber.org/ratelimit v0.3.0/go.mod h1:So5LG7CV1zWpY1sHe+DXTJqQvOx+FFPFaAs2SnoyBaI= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= -gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= -gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= -gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= -gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= -k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= -k8s.io/apiextensions-apiserver v0.28.2 h1:J6/QRWIKV2/HwBhHRVITMLYoypCoPY1ftigDM0Kn+QU= -k8s.io/apiextensions-apiserver v0.28.2/go.mod h1:5tnkxLGa9nefefYzWuAlWZ7RZYuN/765Au8cWLA6SRg= -k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= -k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= -k8s.io/cli-runtime v0.28.2 h1:64meB2fDj10/ThIMEJLO29a1oujSm0GQmKzh1RtA/uk= -k8s.io/cli-runtime v0.28.2/go.mod h1:bTpGOvpdsPtDKoyfG4EG041WIyFZLV9qq4rPlkyYfDA= -k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= -k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= -k8s.io/component-base v0.28.2 h1:Yc1yU+6AQSlpJZyvehm/NkJBII72rzlEsd6MkBQ+G0E= -k8s.io/component-base v0.28.2/go.mod h1:4IuQPQviQCg3du4si8GpMrhAIegxpsgPngPRR/zWpzc= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f h1:2sXuKesAYbRHxL3aE2PN6zX/gcJr22cjrsej+W784Tc= -k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc= -k8s.io/kubectl v0.28.2 h1:fOWOtU6S0smdNjG1PB9WFbqEIMlkzU5ahyHkc7ESHgM= -k8s.io/kubectl v0.28.2/go.mod h1:6EQWTPySF1fn7yKoQZHYf9TPwIl2AygHEcJoxFekr64= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= -rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= -sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= -sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/tools/citool/main.go b/tools/citool/main.go index 4fa6cac56..12aa3ec59 100644 --- a/tools/citool/main.go +++ b/tools/citool/main.go @@ -1,8 +1,6 @@ package main -import ( - "github.com/smartcontractkit/chainlink/integration-tests/citool/cmd" -) +import "github.com/smartcontractkit/chainlink-testing-framework/tools/citool/cmd" func main() { cmd.Execute() From 6f61d6a6f0df9f2c1ec3c82032dea695fa5ac9d3 Mon Sep 17 00:00:00 2001 From: David Cauchi <13139524+davidcauchi@users.noreply.github.com> Date: Tue, 20 Aug 2024 18:08:14 +0200 Subject: [PATCH 22/26] [SHIP-2887]Enable chains in CTF (#1078) * Enable chains in CTF * Updates Astar to use Finality tag --------- Co-authored-by: Lukasz <120112546+lukaszcl@users.noreply.github.com> --- networks/known_networks.go | 60 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/networks/known_networks.go b/networks/known_networks.go index b3ab936c7..ac8437924 100644 --- a/networks/known_networks.go +++ b/networks/known_networks.go @@ -921,7 +921,7 @@ var ( Timeout: blockchain.StrDuration{Duration: 3 * time.Minute}, MinimumConfirmations: 1, GasEstimationBuffer: 10000, - FinalityDepth: 100, + FinalityTag: true, DefaultGasLimit: 8000000, } @@ -935,10 +935,62 @@ var ( Timeout: blockchain.StrDuration{Duration: 3 * time.Minute}, MinimumConfirmations: 1, GasEstimationBuffer: 10000, - FinalityDepth: 100, + FinalityTag: true, DefaultGasLimit: 8000000, } + HederaTestnet = blockchain.EVMNetwork{ + Name: "Hedera Testnet", + SupportsEIP1559: false, + ClientImplementation: blockchain.EthereumClientImplementation, + ChainID: 296, + Simulated: false, + ChainlinkTransactionLimit: 5000, + Timeout: blockchain.StrDuration{Duration: 3 * time.Minute}, + MinimumConfirmations: 1, + GasEstimationBuffer: 10000, + DefaultGasLimit: 6000000, + } + + XLayerSepolia = blockchain.EVMNetwork{ + Name: "XLayer Sepolia", + SupportsEIP1559: false, + ClientImplementation: blockchain.EthereumClientImplementation, + ChainID: 195, + Simulated: false, + ChainlinkTransactionLimit: 5000, + Timeout: blockchain.StrDuration{Duration: 3 * time.Minute}, + MinimumConfirmations: 1, + GasEstimationBuffer: 10000, + DefaultGasLimit: 6000000, + } + + XLayerMainnet = blockchain.EVMNetwork{ + Name: "XLayer Mainnet", + SupportsEIP1559: false, + ClientImplementation: blockchain.EthereumClientImplementation, + ChainID: 196, + Simulated: false, + ChainlinkTransactionLimit: 5000, + Timeout: blockchain.StrDuration{Duration: 3 * time.Minute}, + MinimumConfirmations: 1, + GasEstimationBuffer: 10000, + DefaultGasLimit: 6000000, + } + + TreasureRuby = blockchain.EVMNetwork{ + Name: "Treasure Ruby", + SupportsEIP1559: true, + ClientImplementation: blockchain.EthereumClientImplementation, + ChainID: 978657, + Simulated: false, + ChainlinkTransactionLimit: 5000, + Timeout: blockchain.StrDuration{Duration: 3 * time.Minute}, + MinimumConfirmations: 1, + GasEstimationBuffer: 10000, + DefaultGasLimit: 6000000, + } + MappedNetworks = map[string]blockchain.EVMNetwork{ "SIMULATED": SimulatedEVM, "ANVIL": Anvil, @@ -1004,6 +1056,10 @@ var ( "ZKSYNC_MAINNET": ZKSyncMainnet, "ASTAR_SHIBUYA": AstarShibuya, "ASTAR_MAINNET": AstarMainnet, + "HEDERA_TESTNET": HederaTestnet, + "X_LAYER_SEPOLIA": XLayerSepolia, + "X_LAYER_MAINNET": XLayerMainnet, + "TREASURE_RUBY": TreasureRuby, } ) From 3e7c014532f6b9eb61ffe420a82e4463c8a4758d Mon Sep 17 00:00:00 2001 From: Rafael Felix Correa Date: Wed, 21 Aug 2024 14:19:17 +0200 Subject: [PATCH 23/26] CRIB-317 - Use the kyverno's label instead of kube-janitor's annotation for clean up (#1080) --- k8s/TUTORIAL.md | 2 +- k8s/environment/environment.go | 5 +++-- k8s/pkg/alias/alias.go | 2 +- k8s/pkg/common.go | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/k8s/TUTORIAL.md b/k8s/TUTORIAL.md index d31335af8..db85091a2 100644 --- a/k8s/TUTORIAL.md +++ b/k8s/TUTORIAL.md @@ -450,7 +450,7 @@ const ( ```golang // Config is an environment common configuration, labels, annotations, connection types, readiness check, etc. type Config struct { - // TTL is time to live for the environment, used with kube-janitor + // TTL is time to live for the environment, used with kyverno TTL time.Duration // NamespacePrefix is a static namespace prefix NamespacePrefix string diff --git a/k8s/environment/environment.go b/k8s/environment/environment.go index 5fee8b687..6505e8f52 100644 --- a/k8s/environment/environment.go +++ b/k8s/environment/environment.go @@ -70,7 +70,7 @@ type ConnectedChart interface { // Config is an environment common configuration, labels, annotations, connection types, readiness check, etc. type Config struct { - // TTL is time to live for the environment, used with kube-janitor + // TTL is time to live for the environment, used with kyverno TTL time.Duration // NamespacePrefix is a static namespace prefix NamespacePrefix string @@ -272,11 +272,12 @@ func (m *Environment) initApp() error { } } + m.Cfg.Labels = append(m.Cfg.Labels, fmt.Sprintf("%s=%s", pkg.TTLLabelKey, *a.ShortDur(m.Cfg.TTL))) nsLabels, err := a.ConvertLabels(m.Cfg.Labels) if err != nil { return err } - defaultNamespaceAnnotations[pkg.TTLLabelKey] = a.ShortDur(m.Cfg.TTL) + m.root = cdk8s.NewChart(m.App, ptr.Ptr(fmt.Sprintf("root-chart-%s", m.Cfg.Namespace)), &cdk8s.ChartProps{ Labels: nsLabels, Namespace: ptr.Ptr(m.Cfg.Namespace), diff --git a/k8s/pkg/alias/alias.go b/k8s/pkg/alias/alias.go index 5808fbc45..bc262a4dc 100644 --- a/k8s/pkg/alias/alias.go +++ b/k8s/pkg/alias/alias.go @@ -9,7 +9,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" ) -// ShortDur is a helper method for kube-janitor duration format +// ShortDur is a helper method for kyverno duration format func ShortDur(d time.Duration) *string { s := d.String() if strings.HasSuffix(s, "m0s") { diff --git a/k8s/pkg/common.go b/k8s/pkg/common.go index 8b394ee56..d3619856d 100644 --- a/k8s/pkg/common.go +++ b/k8s/pkg/common.go @@ -4,7 +4,7 @@ import "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" // Common labels for k8s envs const ( - TTLLabelKey = "janitor/ttl" + TTLLabelKey = "cleanup.kyverno.io/ttl" NamespaceLabelKey = "namespace" ) From 2738403d6c716c3117390f2e86565157798ad8a3 Mon Sep 17 00:00:00 2001 From: Sergey Kudasov Date: Wed, 21 Aug 2024 16:07:37 +0200 Subject: [PATCH 24/26] aws secrets manager wrapper (#1081) --- README.md | 4 ++ SECRETS.md | 24 +++++++ client/secretsmanager.go | 131 ++++++++++++++++++++++++++++++++++ client/secretsmanager_test.go | 67 +++++++++++++++++ go.mod | 22 +++++- go.sum | 28 ++++++++ 6 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 SECRETS.md create mode 100644 client/secretsmanager.go create mode 100644 client/secretsmanager_test.go diff --git a/README.md b/README.md index 2670d2aab..ea1b7cc2a 100644 --- a/README.md +++ b/README.md @@ -423,3 +423,7 @@ We have two ways to add new images to the ecr. The first two requirements are th export SETH_LOG_LEVEL=info export RESTY_DEBUG=true ``` + +## Using AWS Secrets Manager + +Check the [docs](SECRETS.md) diff --git a/SECRETS.md b/SECRETS.md new file mode 100644 index 000000000..d407b1ac5 --- /dev/null +++ b/SECRETS.md @@ -0,0 +1,24 @@ +## Using AWSSecretsManager from code + +`client/secretsmanager.go` has a simple API to read/write/delete secrets. + +It uses a struct to protect such secrets from accidental printing or marshalling, see an [example](client/secretsmanager_test.go) test + +## Using AWSSecretsManager via CLI + +To create a static secret use `aws cli` + +``` +aws --region us-west-2 secretsmanager create-secret \ + --name MyTestSecret \ + --description "My test secret created with the CLI." \ + --secret-string "{\"user\":\"diegor\",\"password\":\"EXAMPLE-PASSWORD\"}" +``` + +Example of reading the secret + +``` +aws --region us-west-2 secretsmanager get-secret-value --secret-id MyTestSecret +``` + +For more information check [AWS CLI Reference](https://docs.aws.amazon.com/cli/v1/userguide/cli_secrets-manager_code_examples.html) diff --git a/client/secretsmanager.go b/client/secretsmanager.go new file mode 100644 index 000000000..b4706c4b0 --- /dev/null +++ b/client/secretsmanager.go @@ -0,0 +1,131 @@ +package client + +/* +This client helps us to store and load secrets in AWS Secrets Manager +It also prevents secrets from being printed by mistake +*/ + +import ( + "context" + "encoding" + "encoding/json" + "fmt" + "time" + + "github.com/aws/aws-sdk-go-v2/config" + "github.com/pkg/errors" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + + "github.com/aws/aws-sdk-go-v2/service/secretsmanager" +) + +var ( + redacted = "***" + redactedJSON = "{\"key\":\"is_redacted\"}" + redactedTOML = "[Key]\n\nis = redacted" +) + +// AWSSecret is a wrapper preventing accidental printing or marshalling +type AWSSecret string + +// Value is used to return masked secret value +func (s AWSSecret) Value() string { return string(s) } + +// The String method is used to print values passed as an operand +// to any format that accepts a string or to an unformatted printer +// such as Print. +func (s AWSSecret) String() string { return redacted } + +// The GoString method is used to print values passed as an operand +// to a %#v format. +func (s AWSSecret) GoString() string { return redacted } + +// MarshalText encodes the receiver into UTF-8-encoded text and returns the result. +func (s AWSSecret) MarshalText() ([]byte, error) { return []byte(redactedTOML), nil } + +// MarshalJSON Marshaler is the interface implemented by types that +// can marshal themselves into valid JSON. +func (s AWSSecret) MarshalJSON() ([]byte, error) { return []byte(redactedJSON), nil } + +var ( + _ fmt.Stringer = (*AWSSecret)(nil) + _ fmt.GoStringer = (*AWSSecret)(nil) + _ encoding.TextMarshaler = (*AWSSecret)(nil) + _ json.Marshaler = (*AWSSecret)(nil) +) + +// AWSSecretsManager is an AWS Secrets Manager service wrapper +type AWSSecretsManager struct { + Client *secretsmanager.Client + RequestTimeout time.Duration + l zerolog.Logger +} + +// NewAWSSecretsManager create a new connection to AWS Secrets Manager +func NewAWSSecretsManager(requestTimeout time.Duration) (*AWSSecretsManager, error) { + cfg, err := config.LoadDefaultConfig(context.TODO()) + if err != nil { + return nil, fmt.Errorf("unable to load AWS SDK config, %v", err) + } + l := log.Logger.With().Str("Component", "AWSSecretsManager").Logger() + l.Info().Msg("Connecting to AWS Secrets Manager") + return &AWSSecretsManager{ + Client: secretsmanager.NewFromConfig(cfg), + RequestTimeout: requestTimeout, + l: l, + }, nil +} + +// CreateSecret creates a specific secret by key +func (sm *AWSSecretsManager) CreateSecret(key string, val string, override bool) error { + ctx, cancel := context.WithTimeout(context.Background(), sm.RequestTimeout) + defer cancel() + + sm.l.Debug().Str("Key", key).Msg("Creating secret by key") + k := &key + v := &val + _, err := sm.Client.CreateSecret(ctx, &secretsmanager.CreateSecretInput{ + Name: k, + SecretString: v, + ForceOverwriteReplicaSecret: override, + }) + if err != nil { + return errors.Wrapf(err, "failed to create a secret by key") + } + return nil +} + +// GetSecret gets a specific secret by key +func (sm *AWSSecretsManager) GetSecret(key string) (AWSSecret, error) { + ctx, cancel := context.WithTimeout(context.Background(), sm.RequestTimeout) + defer cancel() + + sm.l.Debug().Str("Key", key).Msg("Reading secret by key") + k := &key + out, err := sm.Client.GetSecretValue(ctx, &secretsmanager.GetSecretValueInput{ + SecretId: k, + }) + if err != nil { + return "", errors.Wrapf(err, "failed to read a secret by key") + } + return AWSSecret(*out.SecretString), nil +} + +// RemoveSecret removes a specific secret by key +func (sm *AWSSecretsManager) RemoveSecret(key string, noRecovery bool) error { + ctx, cancel := context.WithTimeout(context.Background(), sm.RequestTimeout) + defer cancel() + + sm.l.Debug().Str("Key", key).Msg("Removing secret by key") + k := &key + b := &noRecovery + _, err := sm.Client.DeleteSecret(ctx, &secretsmanager.DeleteSecretInput{ + SecretId: k, + ForceDeleteWithoutRecovery: b, + }) + if err != nil { + return errors.Wrapf(err, "failed to remove a secret by key") + } + return nil +} diff --git a/client/secretsmanager_test.go b/client/secretsmanager_test.go new file mode 100644 index 000000000..e4679c7a7 --- /dev/null +++ b/client/secretsmanager_test.go @@ -0,0 +1,67 @@ +package client + +import ( + "encoding/json" + "fmt" + "testing" + "time" + + "github.com/davecgh/go-spew/spew" + "github.com/google/uuid" + "github.com/pelletier/go-toml/v2" + "github.com/stretchr/testify/require" +) + +func TestSecretsPrintMarshal(t *testing.T) { + s := AWSSecret("1") + t.Run("print the whole struct as string", func(t *testing.T) { + //nolint + output := fmt.Sprintf("%s", s) + require.Equal(t, redacted, output) + }) + t.Run("print the whole struct as +v%", func(t *testing.T) { + output := fmt.Sprintf("%+v", s) + require.Equal(t, redacted, output) + }) + t.Run("spew library should not work either", func(t *testing.T) { + output := spew.Sdump(s) + require.Equal(t, "(client.AWSSecret) (len=1) ***", output[:len(output)-1]) + }) + t.Run("marshal the whole struct as JSON", func(t *testing.T) { + d, err := json.Marshal(s) + require.NoError(t, err) + require.Equal(t, redactedJSON, string(d)) + }) + t.Run("marshal the whole struct as TOML results in err", func(t *testing.T) { + // github.com/pelletier/go-toml/v2 since version 2 does not allow any struct to implement MarshalText() + // so it results in error if we try to marshal secrets + _, err := toml.Marshal(s) + require.Error(t, err) + }) +} + +func TestManualSecretsCRUD(t *testing.T) { + t.Skip("Need AWS role to be enabled") + // fill .envrc with AWS auth values and run manually + // export AWS_REGION="us-west-2" + // export AWS_ACCESS_KEY_ID= + // export AWS_SECRET_ACCESS_KEY= + // export AWS_SESSION_TOKEN= + sm, err := NewAWSSecretsManager(1 * time.Minute) + require.NoError(t, err) + + t.Run("basic single value CRUD", func(t *testing.T) { + k := uuid.NewString() + v := uuid.NewString() + t.Cleanup(func() { + err = sm.RemoveSecret(k, true) + require.NoError(t, err) + }) + err = sm.CreateSecret(k, v, true) + require.NoError(t, err) + secret, err := sm.GetSecret(k) + require.NoError(t, err) + require.Equal(t, secret, AWSSecret(v)) + require.Equal(t, v, AWSSecret(v).Value()) + }) +} diff --git a/go.mod b/go.mod index 39693844c..e4e9d3e33 100644 --- a/go.mod +++ b/go.mod @@ -98,7 +98,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc github.com/deckarep/golang-set/v2 v2.3.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/dennwc/varint v1.0.0 // indirect @@ -316,6 +316,26 @@ require ( sigs.k8s.io/yaml v1.3.0 // indirect ) +require ( + github.com/aws/aws-sdk-go-v2/config v1.27.28 + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 +) + +require ( + github.com/aws/aws-sdk-go-v2 v1.30.4 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.28 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 // indirect + github.com/aws/smithy-go v1.20.4 // indirect +) + // avoids ambigious imports of indirect dependencies exclude github.com/hashicorp/consul v1.2.1 diff --git a/go.sum b/go.sum index 6f326b2fe..5774638a8 100644 --- a/go.sum +++ b/go.sum @@ -136,10 +136,38 @@ github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4= github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go-v2 v1.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8= +github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0= +github.com/aws/aws-sdk-go-v2/config v1.27.28 h1:OTxWGW/91C61QlneCtnD62NLb4W616/NM1jA8LhJqbg= +github.com/aws/aws-sdk-go-v2/config v1.27.28/go.mod h1:uzVRVtJSU5EFv6Fu82AoVFKozJi2ZCY6WRCXj06rbvs= +github.com/aws/aws-sdk-go-v2/credentials v1.17.28 h1:m8+AHY/ND8CMHJnPoH7PJIRakWGa4gbfbxuY9TGTUXM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.28/go.mod h1:6TF7dSc78ehD1SL6KpRIPKMA1GyyWflIkjqg+qmf4+c= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 h1:yjwoSyDZF8Jth+mUk5lSPJCkMC0lMy6FaCD51jm6ayE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12/go.mod h1:fuR57fAgMk7ot3WcNQfb6rSEn+SUffl7ri+aa8uKysI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 h1:tJ5RnkHCiSH0jyd6gROjlJtNwov0eGYNz8s8nFcR0jQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18/go.mod h1:++NHzT+nAF7ZPrHPsA+ENvsXkOO8wEu+C6RXltAG4/c= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 h1:UDXu9dqpCZYonj7poM4kFISjzTdWI0v3WUusM+w+Gfc= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5/go.mod h1:5NPkI3RsTOhwz1CuG7VVSgJCm3CINKkoIaUbUZWQ67w= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 h1:zCsFCKvbj25i7p1u94imVoO447I/sFv8qq+lGJhRN0c= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.5/go.mod h1:ZeDX1SnKsVlejeuz41GiajjZpRSWR7/42q/EyA/QEiM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 h1:SKvPgvdvmiTWoi0GAJ7AsJfOz3ngVkD/ERbs5pUnHNI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5/go.mod h1:20sz31hv/WsPa3HhU3hfrIet2kxM4Pe0r20eBZ20Tac= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 h1:iAckBT2OeEK/kBDyN/jDtpEExhjeeA/Im2q4X0rJZT8= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.4/go.mod h1:vmSqFK+BVIwVpDAGZB3CoCXHzurt4qBE8lf+I/kRTh0= github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3sWOxO2Dfja0iA1W7ZcI7g= github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYSN6/mGyHI6O3I= +github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= +github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= From 34d49f1010a70d7452bb42bf454f3508daa36caa Mon Sep 17 00:00:00 2001 From: Sergey Kudasov Date: Thu, 22 Aug 2024 10:22:09 +0200 Subject: [PATCH 25/26] Merge WASP library (#1082) * init * change mod name, add CI * try to trigger * commit go.sum * fix lint * move wasp to the root folder * fix lint * fix lint again * link readmes * change workflow to paths * move back to dorny for required checks * fix readme lint * try trigger CI --- .github/workflows/wasp-lint.yml | 28 + .github/workflows/wasp-test-e2e.yml | 31 + .github/workflows/wasp-test.yml | 27 + .golangci.yaml | 2 + .prettierignore | 1 + README.md | 12 +- _typos.toml | 10 +- wasp/.dockerignore | 1 + wasp/.env | 7 + wasp/.gitignore | 7 + wasp/.golangci.yaml | 15 + wasp/CODEOWNERS | 1 + wasp/DockerfileWasp | 22 + wasp/DockerfileWasp.dockerignore | 31 + wasp/HOW_IT_WORKS.md | 235 ++++ wasp/LICENSE | 21 + wasp/Makefile | 53 + wasp/README.md | 171 +++ wasp/SECURITY.md | 11 + wasp/alert.go | 104 ++ wasp/buffer.go | 26 + wasp/charts/wasp/.helmignore | 23 + wasp/charts/wasp/Chart.yaml | 6 + wasp/charts/wasp/namespace_setup/setup.yaml | 25 + wasp/charts/wasp/templates/_helpers.tpl | 62 + wasp/charts/wasp/templates/job.yaml | 69 + wasp/charts/wasp/values.yaml | 35 + wasp/charts/wasp/wasp-0.1.8.tgz | Bin 0 -> 2135 bytes wasp/cluster.go | 235 ++++ wasp/cmd.go | 49 + wasp/compose/conf/defaults.ini | 1238 +++++++++++++++++ wasp/compose/conf/grafana.ini | 1160 +++++++++++++++ .../provisioning/access-control/sample.yaml | 68 + .../conf/provisioning/dashboards/sample.yaml | 10 + .../conf/provisioning/datasources/loki.yaml | 10 + .../conf/provisioning/notifiers/sample.yaml | 24 + .../conf/provisioning/plugins/sample.yaml | 10 + .../compose/conf/provisioning/rules/rules.yml | 9 + wasp/compose/docker-compose.yaml | 31 + wasp/compose/loki-config.yaml | 47 + wasp/compose/pyroscope-compose.yaml | 9 + wasp/dashboard/cmd/main.go | 23 + wasp/dashboard/dashboard.go | 467 +++++++ wasp/dashboard/grafanasdk/panels.go | 381 +++++ wasp/dashboard/panels.go | 80 ++ wasp/docs/dashboard_basic.png | Bin 0 -> 651751 bytes wasp/docs/how-it-works.png | Bin 0 -> 130430 bytes wasp/docs/wasp-2.png | Bin 0 -> 36767 bytes wasp/examples/README.md | 122 ++ wasp/examples/alerts/gun.go | 35 + wasp/examples/alerts/main_test.go | 195 +++ wasp/examples/go.mod | 193 +++ wasp/examples/go.sum | 1186 ++++++++++++++++ wasp/examples/profiles/gun.go | 35 + wasp/examples/profiles/node_rps_test.go | 40 + wasp/examples/profiles/node_vu_test.go | 40 + wasp/examples/profiles/vu.go | 74 + wasp/examples/scenario/main_test.go | 32 + wasp/examples/scenario/vu.go | 79 ++ wasp/examples/simple_rps/gun.go | 35 + wasp/examples/simple_rps/main.go | 38 + wasp/examples/simple_vu/main_test.go | 46 + wasp/examples/simple_vu/vu.go | 61 + wasp/examples/zcluster/Dockerfile | 22 + wasp/examples/zcluster/build.sh | 38 + wasp/examples/zcluster/cluster_test.go | 34 + wasp/flake.lock | 61 + wasp/flake.nix | 15 + wasp/go.mod | 212 +++ wasp/go.sum | 1234 ++++++++++++++++ wasp/gun_http_mock.go | 39 + wasp/gun_sleep_mock.go | 67 + wasp/http_server_mock.go | 56 + wasp/k8s.go | 150 ++ wasp/log.go | 47 + wasp/loki_client.go | 226 +++ wasp/loki_client_test.go | 72 + wasp/perf_test.go | 250 ++++ wasp/profile.go | 223 +++ wasp/responses.go | 37 + wasp/sampler.go | 44 + wasp/schedule.go | 59 + wasp/schedule_test.go | 114 ++ wasp/shell.nix | 18 + wasp/stat.go | 46 + wasp/vu_sleep_mock.go | 81 ++ wasp/vu_ws_mock.go | 66 + wasp/wasp.go | 823 +++++++++++ wasp/wasp_bench_test.go | 29 + wasp/wasp_test.go | 1041 ++++++++++++++ wasp/ws_server_mock.go | 47 + 91 files changed, 12247 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/wasp-lint.yml create mode 100644 .github/workflows/wasp-test-e2e.yml create mode 100644 .github/workflows/wasp-test.yml create mode 100644 wasp/.dockerignore create mode 100644 wasp/.env create mode 100644 wasp/.gitignore create mode 100644 wasp/.golangci.yaml create mode 100644 wasp/CODEOWNERS create mode 100644 wasp/DockerfileWasp create mode 100644 wasp/DockerfileWasp.dockerignore create mode 100644 wasp/HOW_IT_WORKS.md create mode 100644 wasp/LICENSE create mode 100644 wasp/Makefile create mode 100644 wasp/README.md create mode 100644 wasp/SECURITY.md create mode 100644 wasp/alert.go create mode 100644 wasp/buffer.go create mode 100644 wasp/charts/wasp/.helmignore create mode 100644 wasp/charts/wasp/Chart.yaml create mode 100644 wasp/charts/wasp/namespace_setup/setup.yaml create mode 100644 wasp/charts/wasp/templates/_helpers.tpl create mode 100644 wasp/charts/wasp/templates/job.yaml create mode 100644 wasp/charts/wasp/values.yaml create mode 100644 wasp/charts/wasp/wasp-0.1.8.tgz create mode 100644 wasp/cluster.go create mode 100644 wasp/cmd.go create mode 100644 wasp/compose/conf/defaults.ini create mode 100644 wasp/compose/conf/grafana.ini create mode 100644 wasp/compose/conf/provisioning/access-control/sample.yaml create mode 100644 wasp/compose/conf/provisioning/dashboards/sample.yaml create mode 100644 wasp/compose/conf/provisioning/datasources/loki.yaml create mode 100644 wasp/compose/conf/provisioning/notifiers/sample.yaml create mode 100644 wasp/compose/conf/provisioning/plugins/sample.yaml create mode 100644 wasp/compose/conf/provisioning/rules/rules.yml create mode 100644 wasp/compose/docker-compose.yaml create mode 100644 wasp/compose/loki-config.yaml create mode 100644 wasp/compose/pyroscope-compose.yaml create mode 100644 wasp/dashboard/cmd/main.go create mode 100644 wasp/dashboard/dashboard.go create mode 100644 wasp/dashboard/grafanasdk/panels.go create mode 100644 wasp/dashboard/panels.go create mode 100644 wasp/docs/dashboard_basic.png create mode 100644 wasp/docs/how-it-works.png create mode 100644 wasp/docs/wasp-2.png create mode 100644 wasp/examples/README.md create mode 100644 wasp/examples/alerts/gun.go create mode 100644 wasp/examples/alerts/main_test.go create mode 100644 wasp/examples/go.mod create mode 100644 wasp/examples/go.sum create mode 100644 wasp/examples/profiles/gun.go create mode 100644 wasp/examples/profiles/node_rps_test.go create mode 100644 wasp/examples/profiles/node_vu_test.go create mode 100644 wasp/examples/profiles/vu.go create mode 100644 wasp/examples/scenario/main_test.go create mode 100644 wasp/examples/scenario/vu.go create mode 100644 wasp/examples/simple_rps/gun.go create mode 100644 wasp/examples/simple_rps/main.go create mode 100644 wasp/examples/simple_vu/main_test.go create mode 100644 wasp/examples/simple_vu/vu.go create mode 100755 wasp/examples/zcluster/Dockerfile create mode 100755 wasp/examples/zcluster/build.sh create mode 100644 wasp/examples/zcluster/cluster_test.go create mode 100644 wasp/flake.lock create mode 100644 wasp/flake.nix create mode 100644 wasp/go.mod create mode 100644 wasp/go.sum create mode 100644 wasp/gun_http_mock.go create mode 100644 wasp/gun_sleep_mock.go create mode 100644 wasp/http_server_mock.go create mode 100644 wasp/k8s.go create mode 100644 wasp/log.go create mode 100644 wasp/loki_client.go create mode 100644 wasp/loki_client_test.go create mode 100644 wasp/perf_test.go create mode 100644 wasp/profile.go create mode 100644 wasp/responses.go create mode 100644 wasp/sampler.go create mode 100644 wasp/schedule.go create mode 100644 wasp/schedule_test.go create mode 100644 wasp/shell.nix create mode 100644 wasp/stat.go create mode 100644 wasp/vu_sleep_mock.go create mode 100644 wasp/vu_ws_mock.go create mode 100644 wasp/wasp.go create mode 100644 wasp/wasp_bench_test.go create mode 100644 wasp/wasp_test.go create mode 100644 wasp/ws_server_mock.go diff --git a/.github/workflows/wasp-lint.yml b/.github/workflows/wasp-lint.yml new file mode 100644 index 000000000..effc9a8b2 --- /dev/null +++ b/.github/workflows/wasp-lint.yml @@ -0,0 +1,28 @@ +name: WASP Lint +on: + push: +permissions: + contents: read +jobs: + golangci: + defaults: + run: + working-directory: wasp + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dorny/paths-filter@v3 + id: changes + with: + filters: | + src: + - 'wasp/**' + - uses: cachix/install-nix-action@v18 + if: steps.changes.outputs.src == 'true' + with: + nix_path: nixpkgs=channel:nixos-unstable + - name: Run lint + if: steps.changes.outputs.src == 'true' + run: |- + nix develop -c make lint diff --git a/.github/workflows/wasp-test-e2e.yml b/.github/workflows/wasp-test-e2e.yml new file mode 100644 index 000000000..dc297c34d --- /dev/null +++ b/.github/workflows/wasp-test-e2e.yml @@ -0,0 +1,31 @@ +name: WASP E2E tests +on: [push] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +jobs: + test: + defaults: + run: + working-directory: wasp + env: + LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} + LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + LOKI_URL: ${{ secrets.LOKI_URL }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dorny/paths-filter@v3 + id: changes + with: + filters: | + src: + - 'wasp/**' + - uses: cachix/install-nix-action@v18 + if: steps.changes.outputs.src == 'true' + with: + nix_path: nixpkgs=channel:nixos-unstable + - name: Run tests + if: steps.changes.outputs.src == 'true' + run: |- + nix develop -c make test_loki diff --git a/.github/workflows/wasp-test.yml b/.github/workflows/wasp-test.yml new file mode 100644 index 000000000..15dae11ee --- /dev/null +++ b/.github/workflows/wasp-test.yml @@ -0,0 +1,27 @@ +name: WASP Go Tests +on: [push] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +jobs: + test: + defaults: + run: + working-directory: wasp + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: dorny/paths-filter@v3 + id: changes + with: + filters: | + src: + - 'wasp/**' + - uses: cachix/install-nix-action@v18 + if: steps.changes.outputs.src == 'true' + with: + nix_path: nixpkgs=channel:nixos-unstable + - name: Run tests + if: steps.changes.outputs.src == 'true' + run: |- + nix develop -c make test_race diff --git a/.golangci.yaml b/.golangci.yaml index d24f15561..97a940f47 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -84,3 +84,5 @@ issues: - contracts/ethereum - examples - imports + - wasp/examples/* + - k8s diff --git a/.prettierignore b/.prettierignore index 6e486a834..5c08ba825 100644 --- a/.prettierignore +++ b/.prettierignore @@ -6,3 +6,4 @@ charts/**/README.md k8s-test-runner/chart/**/*.yaml node_modules/ index.yaml +wasp/** diff --git a/README.md b/README.md index ea1b7cc2a..2616bedb7 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,20 @@ -The Chainlink Testing Framework is a blockchain development framework written in Go. Its primary purpose is to help chainlink developers create extensive integration, e2e, performance, and chaos tests to ensure the stability of the chainlink project. It can also be helpful to those who just want to use chainlink oracles in their projects to help test their contracts, or even for those that aren't using chainlink. +The Chainlink Testing Framework (CTF) is a blockchain development framework written in Go. Its primary purpose is to help chainlink developers create extensive integration, e2e, performance, and chaos tests to ensure the stability of the chainlink project. It can also be helpful to those who just want to use chainlink oracles in their projects to help test their contracts, or even for those that aren't using chainlink. If you're looking to implement a new chain integration for the testing framework, head over to the [blockchain](./blockchain/) directory for more info. +# Content + +1. [Libraries](#libraries) + +## Libraries + +CTF contains a set of useful libraries: + +- [WASP](wasp/README.md) - Scalable protocol-agnostic load testing library for `Go` + ## k8s package We have a k8s package we are using in tests, it provides: diff --git a/_typos.toml b/_typos.toml index 590f56770..1d04c9b9b 100644 --- a/_typos.toml +++ b/_typos.toml @@ -1,2 +1,10 @@ [files] -extend-exclude = ["**/go.mod", "**/go.sum", "charts", "**/*.tgz", "**/*.png"] +extend-exclude = [ + "**/go.mod", + "**/go.sum", + "charts", + "**/*.tgz", + "**/*.png", + "wasp/HOW_IT_WORKS.md", + "wasp/dashboard/**" +] diff --git a/wasp/.dockerignore b/wasp/.dockerignore new file mode 100644 index 000000000..2d2ecd68d --- /dev/null +++ b/wasp/.dockerignore @@ -0,0 +1 @@ +.git/ diff --git a/wasp/.env b/wasp/.env new file mode 100644 index 000000000..cc4331cca --- /dev/null +++ b/wasp/.env @@ -0,0 +1,7 @@ +export LOKI_TOKEN= +export LOKI_URL=http://localhost:3030/loki/api/v1/push +export GRAFANA_URL=http://localhost:3000 +export GRAFANA_TOKEN= +export DATA_SOURCE_NAME=Loki +export DASHBOARD_FOLDER=LoadTests +export DASHBOARD_NAME=Wasp diff --git a/wasp/.gitignore b/wasp/.gitignore new file mode 100644 index 000000000..dd187f467 --- /dev/null +++ b/wasp/.gitignore @@ -0,0 +1,7 @@ +bin/ +.vscode/ +.idea/ +.direnv/ + +k3dvolume/ +.private.env diff --git a/wasp/.golangci.yaml b/wasp/.golangci.yaml new file mode 100644 index 000000000..4aaeac0bf --- /dev/null +++ b/wasp/.golangci.yaml @@ -0,0 +1,15 @@ +run: + timeout: 5m +issues: + exclude-use-default: false + exclude-dirs: + - bin + - imports + - examples/* +linters-settings: + revive: + rules: + - name: exported + severity: warning + - name: dot-imports + disabled: true diff --git a/wasp/CODEOWNERS b/wasp/CODEOWNERS new file mode 100644 index 000000000..cfb4f2262 --- /dev/null +++ b/wasp/CODEOWNERS @@ -0,0 +1 @@ +* @smartcontractkit/test-tooling-team diff --git a/wasp/DockerfileWasp b/wasp/DockerfileWasp new file mode 100644 index 000000000..17c68900f --- /dev/null +++ b/wasp/DockerfileWasp @@ -0,0 +1,22 @@ +# Example DockerfileWasp for k8s run +# Builds all the tests in some directory that must have go.mod +# All tests are built as separate binaries with name "module.test" +FROM golang:1.21 as build +ARG TESTS_ROOT + +WORKDIR /go/src +COPY . . + +RUN echo $(pwd) +RUN ls -lah +WORKDIR /go/src/${TESTS_ROOT} +RUN echo $(pwd) +RUN ls -lah +RUN cd /go/src/${TESTS_ROOT} && CGO_ENABLED=0 go test -c ./... + +FROM debian +ARG TESTS_ROOT + +COPY --from=build /go/src/${TESTS_ROOT} . +RUN apt-get update && apt-get install -y ca-certificates +ENTRYPOINT /bin/bash diff --git a/wasp/DockerfileWasp.dockerignore b/wasp/DockerfileWasp.dockerignore new file mode 100644 index 000000000..4eefe522f --- /dev/null +++ b/wasp/DockerfileWasp.dockerignore @@ -0,0 +1,31 @@ +.git-together +.DS_Store +.envrc +*.log +node_modules/ +**/node_modules/ +vendor/ +tmp/ + +contracts/node_modules +examples/ + +integration/ +integration-scripts/ + +tools/gethnet/datadir/geth +tools/clroot/db.bolt +tools/clroot/*.log +tools/clroot/tempkeys + +core/sgx/target/ + +core/*.Dockerfile +chainlink + +# codeship +codeship-*.yml +*.aes +dockercfg +credentials.env +gcr_creds.env diff --git a/wasp/HOW_IT_WORKS.md b/wasp/HOW_IT_WORKS.md new file mode 100644 index 000000000..1cd491359 --- /dev/null +++ b/wasp/HOW_IT_WORKS.md @@ -0,0 +1,235 @@ +# How it works + +## Overview +General idea is to be able to compose load tests programmatically by combining different `Generators` + +- `Generator` is an entity that can execute some workload using some `Gun` or `VU` definition, each `Generator` may have only one `Gun` or `VU` implementation used + +- `Gun` can be an implementation of single or multiple sequential requests workload for stateless protocols + +- `VU` is a stateful implementation that's more suitable for stateful protocols or when your client have some logic/simulating real users + +- Each `Generator` have a `Schedule` that control workload params throughout the test (increase/decrease RPS or VUs) + +- `Generators` can be combined to run multiple workload units in parallel or sequentially + +- `Profiles` are wrappers that allow you to run multiple generators with different `Schedules` and wait for all of them to finish + +- `ClusterProfiles` are high-level wrappers that create multiple profile parts and scale your test in `k8s` + +- `VU` implementations can also include sequential and parallel requests to simulate users behaviour + +- `AlertChecker` can be used in tests to check if any specific alerts with label and dashboardUUID was triggered and update test status + +Example `Syntetic/RPS` test diagram: + +```mermaid +--- +title: Syntetic/RPS test +--- +sequenceDiagram + participant Profile(Test) + participant Scheduler + participant Generator(Gun) + participant Promtail + participant Loki + participant Grafana + loop Test Execution + Profile(Test) ->> Generator(Gun): Start with (API, TestData) + loop Schedule + Scheduler ->> Scheduler: Process schedule segment + Scheduler ->> Generator(Gun): Set new RPS target + loop RPS load + Generator(Gun) ->> Generator(Gun): Execute Call() in parallel + Generator(Gun) ->> Promtail: Save CallResult + end + Promtail ->> Loki: Send batch
when ready or timeout + end + Scheduler ->> Scheduler: All segments done
wait all responses
test ends + Profile(Test) ->> Grafana: Check alert groups
FAIL or PASS the test + end +``` + +Example `VUs` test diagram: + +```mermaid +--- +title: VUs test +--- +sequenceDiagram + participant Profile(Test) + participant Scheduler + participant Generator(VUs) + participant VU1 + participant VU2 + participant Promtail + participant Loki + participant Grafana + loop Test Execution + Profile(Test) ->> Generator(VUs): Start with (API, TestData) + loop Schedule + Scheduler ->> Scheduler: Process schedule segment + Scheduler ->> Generator(VUs): Set new VUs target + loop VUs load + Generator(VUs) ->> Generator(VUs): Add/remove VUs + Generator(VUs) ->> VU1: Start/end + Generator(VUs) ->> VU2: Start/end + VU1 ->> VU1: Run loop, execute multiple calls + VU1 ->> Promtail: Save []CallResult + VU2 ->> VU2: Run loop, execute multiple calls + VU2 ->> Promtail: Save []CallResult + Promtail ->> Loki: Send batch
when ready or timeout + end + end + Scheduler ->> Scheduler: All segments done
wait all responses
test ends + Profile(Test) ->> Grafana: Check alert groups
FAIL or PASS the test + end +``` + +Load workflow testing diagram: +```mermaid +--- +title: Load testing workflow +--- +sequenceDiagram + participant Product repo + participant Runner + participant K8s + participant Loki + participant Grafana + participant Devs + Product repo->>Product repo: Define NFR for different workloads
Define application dashboard
Define dashboard alerts
Define load tests + Product repo->>Grafana: Upload app dashboard
Alerts has "requirement_name" label
Each "requirement_name" groups is based on some NFR + loop CI runs + Product repo->>Runner: CI Runs small load test + Runner->>Runner: Execute load test logic
Run multiple generators + Runner->>Loki: Stream load test data + Runner->>Grafana: Checking "requirement_name": "baseline" alerts + Grafana->>Devs: Notify devs (Dashboard URL/Alert groups) + Product repo->>Runner: CI Runs huge load test + Runner->>K8s: Split workload into multiple jobs
Monitor jobs statuses + K8s->>Loki: Stream load test data + Runner->>Grafana: Checking "requirement_name": "stress" alerts + Grafana->>Devs: Notify devs (Dashboard URL/Alert groups) + end +``` + +Example cluster component diagram: +```mermaid +--- +title: Workload execution. P - Profile, G - Generator, VU - VirtualUser +--- +flowchart TB + ClusterProfile-- generate k8s manifests/deploy/await jobs completion -->P1 + ClusterProfile-->PN + ClusterProfile-- check NFRs -->Grafana + subgraph Pod1 + P1-->P1-G1 + P1-->P1-GN + P1-G1-->P1-G1-VU1 + P1-G1-->P1-G1-VUN + P1-GN-->P1-GN-VU1 + P1-GN--->P1-GN-VUN + + P1-G1-VU1-->P1-Batch + P1-G1-VUN-->P1-Batch + P1-GN-VU1-->P1-Batch + P1-GN-VUN-->P1-Batch + end + subgraph PodN + PN-->PN-G1 + PN-->PN-GN + PN-G1-->PN-G1-VU1 + PN-G1-->PN-G1-VUN + PN-GN-->PN-GN-VU1 + PN-GN--->PN-GN-VUN + + PN-G1-VU1-->PN-Batch + PN-G1-VUN-->PN-Batch + PN-GN-VU1-->PN-Batch + PN-GN-VUN-->PN-Batch + + end + P1-Batch-->Loki + PN-Batch-->Loki + + Loki-->Grafana + +``` + +## Defining NFRs and checking alerts +You can define different non-functional requirements groups +In this example we have 2 groups: +- `baseline` - checking both 99th latencies per `Generator` and errors +- `stress` - checking only errors + +`WaspAlerts` can be defined on default `Generators` metrics, for each alert additional row is generated + +`CustomAlerts` can be defined as [timeseries.Alert](https://pkg.go.dev/github.com/K-Phoen/grabana@v0.21.18/timeseries#Alert) but timeseries won't be included, though `AlertChecker` will check them + +Run 2 tests, change mock latency/status codes to see how it works + +Alert definitions usually defined with your `dashboard` and then constantly updated on each Git commit by your CI + +After each run `AlertChecker` will fail the test if any alert from selected group was raised +- [definitions](https://github.com/smartcontractkit/wasp/blob/master/examples/alerts/main_test.go#L37) +- [wasp alerts](https://github.com/smartcontractkit/wasp/blob/master/examples/alerts/main_test.go#L73) +- [custom alerts](https://github.com/smartcontractkit/wasp/blob/master/examples/alerts/main_test.go#L82) +- [baseline NFR group test](https://github.com/smartcontractkit/wasp/blob/master/examples/alerts/main_test.go#L115) +- [stress NFR group test](https://github.com/smartcontractkit/wasp/blob/master/examples/alerts/main_test.go#L143) +``` +cd examples/alerts +go test -v -count 1 -run TestBaselineRequirements +go test -v -count 1 -run TestStressRequirements +``` +Open [alert groups](http://localhost:3000/alerting/groups) + +Check [dashboard](http://localhost:3000/d/wasp/wasp-load-generator?orgId=1&refresh=5s&var-go_test_name=All&var-gen_name=All&var-branch=generator_healthcheck&var-commit=generator_healthcheck&from=now-5m&to=now), you can see per alert timeseries in the bottom + +## Cluster test with k8s +`Warning`: we don't have Loki + Grafana k8s setup yet, if you have them in your `k8s` set up you can run this test + +Cluster mode [overview](examples/CLUSTER.md) + +You may also need to set your `LOKI_TOKEN` env var, depends on your authorization + +Your `k8s context` should be set up to work with `kubectl` + +Set up your namespace with role/rolebinding to be able to run tests: +``` +cd charts/wasp +kubectl create ns wasp +kubectl -n wasp apply -f setup.yaml +``` +You can build your tests like in example `Dockerfile` in the root dir +``` +docker build -f Dockerfile.test --build-arg BUILD_ROOT=/go/src/examples/cluster -t wasp_test . +docker tag wasp_test:latest ${registry}/wasp_test:latest +docker push ${registry}/wasp_test:latest +``` + +Then run an example test: +``` +cd examples/cluster +go test -v -count 1 -run TestClusterScenario . +``` + +- [cluster test](https://github.com/smartcontractkit/wasp/blob/master/examples/cluster/cluster_test.go#L11) +- [test](https://github.com/smartcontractkit/wasp/blob/master/examples/cluster/node_test.go#L14) +- [vu](https://github.com/smartcontractkit/wasp/blob/master/examples/cluster/vu.go#L70) + +Open [dashboard](http://localhost:3000/d/wasp/wasp-load-generator?orgId=1&refresh=5s) + +## How to choose RPS vs VU workload +Pick `Gun` if: +- You need to figure out if system can respond to some limited workload +- You have a stateless protocol + +Pick `VU` if: +- You need to simulate some client behaviour with user wait time +- You need to execute more than 1 request in a `Call` +- Your protocol is stateful, and you need to test connections or keep some state + +Differences between `Gun` and `VU` entities: +- `Gun` should perform 1 call, elapsed time is measured automatically, RPS is limited +- `VU` can perform multiple calls, elapsed time is **not measured** automatically, implementation of `VU` should care about time measurement and rate limiting diff --git a/wasp/LICENSE b/wasp/LICENSE new file mode 100644 index 000000000..3682fb80f --- /dev/null +++ b/wasp/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 SmartContract ChainLink, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/wasp/Makefile b/wasp/Makefile new file mode 100644 index 000000000..b4833b8b2 --- /dev/null +++ b/wasp/Makefile @@ -0,0 +1,53 @@ +.PHONY: test +test: + go test -v -count 1 `go list ./... | grep -v examples` -run TestSmoke + +.PHONY: test_race +test_race: + go test -v -race -count 1 `go list ./... | grep -v examples` -run TestSmoke + +.PHONY: test_bench +test_bench: + go test -bench=. -benchmem -count 1 -run=^# + +.PHONY: test+cover +test_cover: + go test -v -coverprofile cover.out -count 1 `go list ./... | grep -v examples` -run TestSmoke + go tool cover -html cover.out + +.PHONY: test +test_loki: + go test -v -count 1 `go list ./... | grep -v examples` -run TestPerfRenderLoki + +.PHONY: test +test_pyro_rps: + go test -v -run TestPyroscopeLocalTraceRPSCalls -trace trace.out + +.PHONY: test +test_pyro_vu: + go test -v -run TestPyroscopeLocalTraceVUCalls -trace trace.out + +.PHONY: dashboard +dashboard: + go run dashboard/cmd/main.go + +.PHONY: start +start: + docker compose -f compose/docker-compose.yaml up -d + sleep 5 && curl -X POST -H "Content-Type: application/json" -d '{"name":"test", "role": "Admin"}' http://localhost:3000/api/auth/keys | jq .key + +.PHONY: stop +stop: + docker compose -f compose/docker-compose.yaml down -v + +.PHONY: pyro_start +pyro_start: + docker compose -f compose/pyroscope-compose.yaml up -d + +.PHONY: pyro_stop +pyro_stop: + docker compose -f compose/pyroscope-compose.yaml down -v + +.PHONY: lint +lint: + golangci-lint --color=always run -v diff --git a/wasp/README.md b/wasp/README.md new file mode 100644 index 000000000..948943d75 --- /dev/null +++ b/wasp/README.md @@ -0,0 +1,171 @@ +

+ wasp +

+
+ +[![Go Report Card](https://goreportcard.com/badge/github.com/smartcontractkit/wasp)](https://goreportcard.com/report/github.com/smartcontractkit/wasp) +[![Component Tests](https://github.com/smartcontractkit/chainlink-testing-framework/actions/workflows/wasp-test.yml/badge.svg)](https://github.com/smartcontractkit/chainlink-testing-framework/actions/workflows/wasp-test.yml) +[![E2E tests](https://github.com/smartcontractkit/chainlink-testing-framework/actions/workflows/wasp-test-e2e.yml/badge.svg)](https://github.com/smartcontractkit/chainlink-testing-framework/actions/workflows/wasp-test-e2e.yml) +![gopherbadger-tag-do-not-edit](https://img.shields.io/badge/Go%20Coverage-80%25-brightgreen.svg?longCache=true&style=flat) + +Scalable protocol-agnostic load testing library for `Go` + +
+ +## Goals +- Easy to reuse any custom client `Go` code +- Easy to grasp +- Have a slim codebase (500-1k loc) +- No test harness or CLI, easy to integrate and run with plain `go test` +- Have a predictable performance footprint +- Easy to create synthetic or user-based scenarios +- Scalable in `k8s` without complicated configuration or vendored UI interfaces +- Non-opinionated reporting, push any data to `Loki` + +## Setup +We are using `nix` for deps, see [installation](https://nixos.org/manual/nix/stable/installation/installation.html) guide +```bash +nix develop +``` + + +## Run example tests with Grafana + Loki +```bash +make start +``` +Insert `GRAFANA_TOKEN` created in previous command +```bash +export LOKI_TOKEN= +export LOKI_URL=http://localhost:3030/loki/api/v1/push +export GRAFANA_URL=http://localhost:3000 +export GRAFANA_TOKEN= +export DATA_SOURCE_NAME=Loki +export DASHBOARD_FOLDER=LoadTests +export DASHBOARD_NAME=Wasp + +make dashboard +``` +Run some tests: +``` +make test_loki +``` +Open your [Grafana dashboard](http://localhost:3000/d/wasp/wasp-load-generator?orgId=1&refresh=5s) + +In case you deploy to your own Grafana check `DASHBOARD_FOLDER` and `DASHBOARD_NAME`, defaults are `LoadTests` dir and dashboard is called `Wasp` + +Remove environment: +```bash +make stop +``` + +## Test Layout and examples +Check [examples](examples/README.md) to understand what is the easiest way to structure your tests, run them both locally and remotely, at scale, inside `k8s` + +## Run pyroscope test +``` +make pyro_start +make test_pyro_rps +make test_pyro_vu +make pyro_stop +``` +Open [pyroscope](http://localhost:4040/) + +You can also use `trace.out` in the root folder with `Go` default tracing UI + +## How it works +![img.png](docs/how-it-works.png) + +Check this [doc](./HOW_IT_WORKS.md) for more examples and project overview + +## Loki debug +You can check all the messages the tool sends with env var `WASP_LOG_LEVEL=trace` + +If Loki client fail to deliver a batch test will proceed, if you experience Loki issues, consider setting `Timeout` in `LokiConfig` or set `MaxErrors: 10` to return an error after N Loki errors + +`MaxErrors: -1` can be used to ignore all the errors + +Default Promtail settings are: +``` +&LokiConfig{ + TenantID: os.Getenv("LOKI_TENANT_ID"), + URL: os.Getenv("LOKI_URL"), + Token: os.Getenv("LOKI_TOKEN"), + BasicAuth: os.Getenv("LOKI_BASIC_AUTH"), + MaxErrors: 10, + BatchWait: 5 * time.Second, + BatchSize: 500 * 1024, + Timeout: 20 * time.Second, + DropRateLimitedBatches: false, + ExposePrometheusMetrics: false, + MaxStreams: 600, + MaxLineSize: 999999, + MaxLineSizeTruncate: false, +} +``` +If you see errors like +``` +ERR Malformed promtail log message, skipping Line=["level",{},"component","client","host","...","msg","batch add err","tenant","","error",{}] +``` +Try to increase `MaxStreams` even more or check your `Loki` configuration + + +## WASP Dashboard + +Basic [dashboard](dashboard/dashboard.go): + +![dashboard_img](./docs/dashboard_basic.png) + +### Reusing Dashboard Components + +You can integrate components from the WASP dashboard into your custom dashboards. + +Example: + +``` +import ( + waspdashboard "github.com/smartcontractkit/wasp/dashboard" +) + +func BuildCustomLoadTestDashboard(dashboardName string) (dashboard.Builder, error) { + // Custom key,value used to query for panels + panelQuery := map[string]string{ + "branch": `=~"${branch:pipe}"`, + "commit": `=~"${commit:pipe}"`, + "network_type": `="testnet"`, + } + + return dashboard.New( + dashboardName, + waspdashboard.WASPLoadStatsRow("Loki", panelQuery), + waspdashboard.WASPDebugDataRow("Loki", panelQuery, true), + # other options + ) +} +``` + +## Annotate Dashboards and Monitor Alerts + +To enable dashboard annotations and alert monitoring, utilize the `WithGrafana()` function in conjunction with `wasp.Profile`. This approach allows for the integration of dashboard annotations and the evaluation of dashboard alerts. + +Example: + +``` +_, err = wasp.NewProfile(). + WithGrafana(grafanaOpts). + Add(wasp.NewGenerator(getLatestReportByTimestampCfg)). + Run(true) +require.NoError(t, err) +``` + +Where: + +``` +type GrafanaOpts struct { + GrafanaURL string `toml:"grafana_url"` + GrafanaToken string `toml:"grafana_token_secret"` + WaitBeforeAlertCheck time.Duration `toml:"grafana_wait_before_alert_check"` // Cooldown period to wait before checking for alerts + AnnotateDashboardUIDs []string `toml:"grafana_annotate_dashboard_uids"` // Grafana dashboardUIDs to annotate start and end of the run + CheckDashboardAlertsAfterRun []string `toml:"grafana_check_alerts_after_run_on_dashboard_uids"` // Grafana dashboardIds to check for alerts after run +} + +``` diff --git a/wasp/SECURITY.md b/wasp/SECURITY.md new file mode 100644 index 000000000..b0ee4c04d --- /dev/null +++ b/wasp/SECURITY.md @@ -0,0 +1,11 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 0.1.x | :white_check_mark: | + +## Reporting a Vulnerability + +Open an issue, we'll review it and get back to you promptly. diff --git a/wasp/alert.go b/wasp/alert.go new file mode 100644 index 000000000..04bbd5bfe --- /dev/null +++ b/wasp/alert.go @@ -0,0 +1,104 @@ +package wasp + +import ( + "fmt" + "os" + "sort" + "strings" + "testing" + "time" + + "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink-testing-framework/grafana" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" +) + +// AlertChecker is checking alerts according to dashboardUUID and requirements labels +type AlertChecker struct { + RequirementLabelKey string + T *testing.T + l zerolog.Logger + grafanaClient *grafana.Client +} + +func NewAlertChecker(t *testing.T) *AlertChecker { + url := os.Getenv("GRAFANA_URL") + if url == "" { + panic(fmt.Errorf("GRAFANA_URL env var must be defined")) + } + apiKey := os.Getenv("GRAFANA_TOKEN") + if apiKey == "" { + panic(fmt.Errorf("GRAFANA_TOKEN env var must be defined")) + } + + grafanaClient := grafana.NewGrafanaClient(url, apiKey) + + return &AlertChecker{ + RequirementLabelKey: "requirement_name", + T: t, + grafanaClient: grafanaClient, + l: GetLogger(t, "AlertChecker"), + } +} + +// AnyAlerts check if any alerts with dashboardUUID have been raised +func (m *AlertChecker) AnyAlerts(dashboardUUID, requirementLabelValue string) ([]grafana.AlertGroupsResponse, error) { + raised := false + defer func() { + if m.T != nil && raised { + m.T.Fail() + } + }() + alertGroups, _, err := m.grafanaClient.AlertManager.GetAlertGroups() + if err != nil { + return alertGroups, fmt.Errorf("failed to get alert groups: %s", err) + } + for _, a := range alertGroups { + for _, aa := range a.Alerts { + log.Debug().Interface("Alert", aa).Msg("Scanning alert") + if aa.Annotations.DashboardUID == dashboardUUID && aa.Labels[m.RequirementLabelKey] == requirementLabelValue { + log.Warn(). + Str("Summary", aa.Annotations.Summary). + Str("Description", aa.Annotations.Description). + Str("URL", aa.GeneratorURL). + Interface("Labels", aa.Labels). + Time("StartsAt", aa.StartsAt). + Time("UpdatedAt", aa.UpdatedAt). + Str("State", aa.Status.State). + Msg("Alert fired") + raised = true + } + } + } + return alertGroups, nil +} + +// CheckDashobardAlerts checks for alerts in the given dashboardUUIDs between from and to times +func CheckDashboardAlerts(grafanaClient *grafana.Client, from, to time.Time, dashboardUID string) ([]grafana.Annotation, error) { + annotationType := "alert" + alerts, _, err := grafanaClient.GetAnnotations(grafana.AnnotationsQueryParams{ + DashboardUID: &dashboardUID, + From: &from, + To: &to, + Type: &annotationType, + }) + if err != nil { + return alerts, fmt.Errorf("could not check for alerts: %s", err) + } + + // Sort the annotations by time oldest to newest + sort.Slice(alerts, func(i, j int) bool { + return alerts[i].Time.Before(alerts[j].Time.Time) + }) + + // Check if any alerts are in alerting state + for _, a := range alerts { + if strings.ToLower(a.NewState) == "alerting" { + return alerts, errors.New("at least one alert was firing") + } + } + + return alerts, nil +} diff --git a/wasp/buffer.go b/wasp/buffer.go new file mode 100644 index 000000000..ae9ccdc8c --- /dev/null +++ b/wasp/buffer.go @@ -0,0 +1,26 @@ +package wasp + +// SliceBuffer keeps Capacity of type T, after len => cap overrides old data +type SliceBuffer[T any] struct { + Idx int + Capacity int + Data []T +} + +// NewSliceBuffer creates new limited capacity slice +func NewSliceBuffer[T any](cap int) *SliceBuffer[T] { + return &SliceBuffer[T]{Capacity: cap, Data: make([]T, 0)} +} + +// Append appends T if len <= cap, overrides old data otherwise +func (m *SliceBuffer[T]) Append(s T) { + if m.Idx >= m.Capacity { + m.Idx = 0 + } + if len(m.Data) <= m.Capacity { + m.Data = append(m.Data, s) + } else { + m.Data[m.Idx] = s + } + m.Idx++ +} diff --git a/wasp/charts/wasp/.helmignore b/wasp/charts/wasp/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/wasp/charts/wasp/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/wasp/charts/wasp/Chart.yaml b/wasp/charts/wasp/Chart.yaml new file mode 100644 index 000000000..2154f204f --- /dev/null +++ b/wasp/charts/wasp/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: wasp +description: Wasp cluster test +type: application +version: 0.1.8 +appVersion: "0.1.8" diff --git a/wasp/charts/wasp/namespace_setup/setup.yaml b/wasp/charts/wasp/namespace_setup/setup.yaml new file mode 100644 index 000000000..20f3f6c39 --- /dev/null +++ b/wasp/charts/wasp/namespace_setup/setup.yaml @@ -0,0 +1,25 @@ +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: wasp-role +rules: + - apiGroups: + - "" + - "apps" + - "batch" + resources: + - "*" + verbs: + - "*" +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: wasp-role +subjects: + - kind: ServiceAccount + name: default +roleRef: + kind: Role + name: wasp-role + apiGroup: rbac.authorization.k8s.io diff --git a/wasp/charts/wasp/templates/_helpers.tpl b/wasp/charts/wasp/templates/_helpers.tpl new file mode 100644 index 000000000..0ecdf99d2 --- /dev/null +++ b/wasp/charts/wasp/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "wasp.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "wasp.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "wasp.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "wasp.labels" -}} +helm.sh/chart: {{ include "wasp.chart" . }} +{{ include "wasp.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "wasp.selectorLabels" -}} +app.kubernetes.io/name: {{ include "wasp.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "wasp.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "wasp.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/wasp/charts/wasp/templates/job.yaml b/wasp/charts/wasp/templates/job.yaml new file mode 100644 index 000000000..77ca98e8c --- /dev/null +++ b/wasp/charts/wasp/templates/job.yaml @@ -0,0 +1,69 @@ +{{- range $i, $e := until (int .Values.jobs) }} +apiVersion: batch/v1 +kind: Job +metadata: + name: wasp-{{ $.Release.Name }}-{{ $i }} + labels: + sync: "{{ $.Values.sync }}" +spec: + backoffLimit: 0 + template: + metadata: + name: wasp-{{ $.Release.Name }}-{{ $i }} + {{- with $.Values.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + sync: {{ $.Values.sync }} + {{- with $.Values.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + restartPolicy: Never + containers: + - name: wasp + image: {{ $.Values.image }} + command: + - ./{{ $.Values.test.binaryName }} + - -test.v + - -test.run + - {{ $.Values.test.name }} + - -test.timeout + - {{ $.Values.test.timeout }} + imagePullPolicy: {{ $.Values.imagePullPolicy }} + {{- with $.Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: LOKI_URL + value: {{ $.Values.env.loki.url }} + - name: LOKI_TOKEN + value: {{ $.Values.env.loki.token }} + - name: LOKI_BASIC_AUTH + value: {{ $.Values.env.loki.basic_auth }} + - name: LOKI_TENANT_ID + value: {{ $.Values.env.loki.tenant_id }} + - name: WASP_LOG_LEVEL + value: {{ $.Values.env.wasp.log_level }} + - name: WASP_NODE_ID + value: {{ $i | quote }} + - name: WASP_NAMESPACE + value: {{ $.Values.namespace }} + - name: WASP_SYNC + value: {{ $.Values.sync }} + - name: WASP_JOBS + value: {{ $.Values.jobs | quote }} + {{- range $key, $value := $.Values.test }} + {{- if $value }} + - name: {{ $key | upper}} + {{- if kindIs "string" $value}} + value: {{ $value | quote}} + {{- else }} + value: {{ $value }} + {{- end }} + {{- end }} + {{- end }} +--- +{{- end }} diff --git a/wasp/charts/wasp/values.yaml b/wasp/charts/wasp/values.yaml new file mode 100644 index 000000000..4bb7e288d --- /dev/null +++ b/wasp/charts/wasp/values.yaml @@ -0,0 +1,35 @@ +namespace: wasp +# amount of jobs to spin up +jobs: 1 +# a label jobs will use to sync before starting, a random 5-digit number by default +sync: +# Go test name and timeout +test: + name: "" + timeout: "24h" + binaryName: "" + +# image + tag string - ${IMAGE}:${TAG} format +image: public.ecr.aws/chainlink/wasp-test:latest +imagePullPolicy: Always +labels: + app: wasp +annotations: {} +env: + wasp: + log_level: info + loki: + basic_auth: "" + tenant_id: "" + token: "" + url: "" +resources: + requests: + cpu: 1000m + memory: 512Mi + limits: + cpu: 1000m + memory: 512Mi +nodeSelector: {} +tolerations: [] +affinity: {} diff --git a/wasp/charts/wasp/wasp-0.1.8.tgz b/wasp/charts/wasp/wasp-0.1.8.tgz new file mode 100644 index 0000000000000000000000000000000000000000..818d21a9f8e6ca7c6f71d5d856d0f738c28f31ad GIT binary patch literal 2135 zcmV-d2&nfTiwG0|00000|0w_~VMtOiV@ORlOnEsqVl!4SWK%V1T2nbTPgYhoO;>Dc zVQyr3R8em|NM&qo0PI>{Z`(K$@3TI|oRbCGY%SY~lPv_?gPR7uY}2HuyDb)ngF#6n zn>9tMB<0lW=05v@q-0C7oj-T|gC0B&j!X`JoEdS3Gviznm32-hL~4IdQugRuP`BId zp7i_nZ@1fR{_XaT`;U74F>i*ArHI@5Gh-CCV zN<{?^V0P${EL(o<`aS=d7o&ty|ZMp%yOn+1S7{J+;b={5bo-|OxC|9g<}UzL%lbmBcAsmQqok-$e0 zD$oK{Mmgk}XTAr}Gd#dZh|FRM7KoTB{6pq_59a9ZF zPeYUt&LPHx~BQ zFG~(@4`@op2)}|RV^CUBK87~zFV0^NUY^|q`-^vjmp70InG)?;-T<;ZWHj-Wc1`BWv$j!2SdwLhT?ywx+o-4lSloEX zXNJMdnZE!`j7JP-$O51|5uO>DQa2Y8MWYeP^`y`oKqDtyk7&Fa5mV&LZ@FalS)vlT zjL?cB@l%dUD~B3oc>uj`x0~9pDW*cs132y-zNTh-n$ml*auMSY8Ae)2tD6=KWvS~w z|K*V+p`7Zuo&3=Uen&O3@n2(_*)!c4O^{_Mm9Mj}cNN?b|BsH2x{dhXKklFG;{W%c z#iDcIoqf)1sGXpTyCSjAku3|ngU-#3w^+1Itfm~HWzLLm7+cU@O_?wbzAGh62nPSX zODhcL)eNPiF~S$nGUpMT9N9;j4)Y|TpP|)mL4k!lHjkba?NlPs2xPfKk~21kPdQ;U zp%|MGYlZf`59qKhzcxD<1r&rB5pz8$ks`dxLzEmfDyM2fk;Mv#L>KTdHrJS*Pz8^} zxi!O!%c0>lcZbR_dg6QM2}oo}RAH}3a7`#z&SGwiYIiY)Xzs=shyr4TFQnaURl`uX zEKQb%EGL)7ELgVA-^bWYEphg(;KAST|29`LE=}M-{I||NZfz-NZSaA@Ws-88Kq%pRLW0wG&r)mBu%UQpUVS`#OuW;kfLDzwMP;meu=g>QObZdoBtv_yQ6$ zMk0jPuPtbeS`T*~k*0z>@zfUa+@zClf-Lpbq+>-6V6gzoBbLVvReZNuV^S3rvpym0b3Osk|?q{ycXuLZdJxI z4;=61wxCmI^CP!&BkVt}tGbF}{*!G$ysBHp&r8Tw@zA;#z?v`r=zH~Np+^4qQG{Q= z4RA;P*Y6!3H}b!ulau3J{`Wn|xQrxxjId9i!oI!!bFL{fKCPF&XA1o%E_AK>g(1<= zq%-SzQ_AB2eixyaq9!rXWL2r#s(G=1{bp3NgVbOGtSV-(ErbACc1h{^a~{FXP0KU+ zm*EOYG!;p5VKTM=x}K?r-4PCo0(B*Zp$CX!$Qb3C>d8t1C*X>sDsZ_%i$6)qz=tou zDUXqBcvi?=j#@C?vEudus z>JEs4t&XzRAzCxWYO=m^{oOA+Id#TbgQvcJ!~5?Yu5Z&gl>kL=s;aJg!53Gr&PRW| zy{JtB*!FQ&)i7EAS$<_^9L3?-g>g@6Xc(%)RE8_FP@ceW%_~YF_9ss-Qu-z{0 z+2!E!-RS(qLnJOcb=#0X42Ew;7gsMw7iaI!?rB?>x|c1(TahoXUYy-3F|B6S+hGQ; z&xUUXr)PHyxa=w43OM}p^7L-3dPLj+^ZV8F;oUH{QN2;k$^|&Z`BT`ptIai7^Y5k% zMV4G}ZxPT)FvU51fjrAlHn^4`=K4HW&~gpxRsp)kT~W*JTIjP8woIw-fY`jY84$J% zR|ebdb|w4%(MipY?oBrT_f6qX$6QGK7JJ-6uED$gHN-Laoee9sU6k{$b54ot=!^HF|PGu~MNnPMW(AfXJEci^k*%scQyGW8C8 zotkGM>DW8?x3>rHiKHS|aQ@;<%K;` zsPn92Kfhid;4c3^Ir^>P|Hu8KUH$)E$d&GI1;bitFGCXfCLI=%{$(B3pFVRv+TOMz zUm6gZGgpeVfn@Zh6nVC+Oxop-)Ao^MnW}uX%>?&-t)yu~>%dLTP=<|RlX|SQcuu(q zT3<&Qm50W`3w_)s!&(>8O5&E4|H)uhzQx3>sTg-19F_*UMZzC_Ja)9B9sM8Ee*ypi N|NrN%8>av)001 0") +) + +// ClusterConfig defines k8s jobs settings +type ClusterConfig struct { + ChartPath string + Namespace string + KeepJobs bool + UpdateImage bool + DockerCmdExecPath string + DockerfilePath string + DockerIgnoreFilePath string + BuildScriptPath string + BuildCtxPath string + ImageTag string + RegistryName string + RepoName string + HelmDeployTimeoutSec string + HelmValues map[string]string + // generated values + tmpHelmFilePath string +} + +func (m *ClusterConfig) Defaults() error { + // TODO: will it be more clear if we move Helm values to a struct + // TODO: or should it be like that for extensibility of a chart without reflection? + m.HelmValues["namespace"] = m.Namespace + // nolint + m.HelmValues["sync"] = fmt.Sprintf("a%s", uuid.NewString()[0:5]) + if m.HelmDeployTimeoutSec == "" { + m.HelmDeployTimeoutSec = defaultHelmDeployTimeoutSec + } + if m.HelmValues["test.timeout"] == "" { + m.HelmValues["test.timeout"] = "12h" + } + if m.HelmValues["resources.requests.cpu"] == "" { + m.HelmValues["resources.requests.cpu"] = DefaultRequestsCPU + } + if m.HelmValues["resources.requests.memory"] == "" { + m.HelmValues["resources.requests.memory"] = DefaultRequestsMemory + } + if m.HelmValues["resources.limits.cpu"] == "" { + m.HelmValues["resources.limits.cpu"] = DefaultLimitsCPU + } + if m.HelmValues["resources.limits.memory"] == "" { + m.HelmValues["resources.limits.memory"] = DefaultLimitsMemory + } + if m.ChartPath == "" { + log.Info().Msg("Using default embedded chart") + if err := os.WriteFile(defaultArchiveName, defaultChart, os.ModePerm); err != nil { + return err + } + m.tmpHelmFilePath, m.ChartPath = defaultArchiveName, defaultArchiveName + } + if m.DockerfilePath == "" { + log.Info().Msg("Using default embedded DockerfileWasp") + if err := os.WriteFile(defaultDockerfilePath, DefaultDockerfile, os.ModePerm); err != nil { + return err + } + p, err := filepath.Abs(defaultDockerfilePath) + if err != nil { + return err + } + m.DockerfilePath = p + } + if m.DockerIgnoreFilePath == "" { + log.Info().Msg("Using default embedded DockerfileWasp.dockerignore") + if err := os.WriteFile(defaultDockerfileIgnorePath, DefaultDockerIgnorefile, os.ModePerm); err != nil { + return err + } + p, err := filepath.Abs(defaultDockerfileIgnorePath) + if err != nil { + return err + } + m.DockerIgnoreFilePath = p + } + if m.BuildScriptPath == "" { + log.Info().Msg("Using default build script") + fname := strings.Replace(defaultBuildScriptPath, "./", "", -1) + if err := os.WriteFile(fname, DefaultBuildScript, os.ModePerm); err != nil { + return err + } + m.BuildScriptPath = defaultBuildScriptPath + } + return nil +} + +func (m *ClusterConfig) Validate() (err error) { + if m.Namespace == "" { + err = errors.Join(err, ErrNoNamespace) + } + if m.HelmValues["jobs"] == "" { + err = errors.Join(err, ErrNoJobs) + } + return +} + +// parseECRImageURI parses the ECR image URI and returns its components +func parseECRImageURI(uri string) (registry, repo, tag string, err error) { + re := regexp.MustCompile(`^([^/]+)/([^:]+):(.+)$`) + matches := re.FindStringSubmatch(uri) + if len(matches) != 4 { + return "", "", "", fmt.Errorf("invalid ECR image URI format, must be ${registry}/${repo}:${tag}") + } + return matches[1], matches[2], matches[3], nil +} + +// ClusterProfile is a k8s cluster test for some workload profile +type ClusterProfile struct { + cfg *ClusterConfig + c *K8sClient + Ctx context.Context + Cancel context.CancelFunc +} + +// NewClusterProfile creates new cluster profile +func NewClusterProfile(cfg *ClusterConfig) (*ClusterProfile, error) { + if err := cfg.Validate(); err != nil { + return nil, err + } + if err := cfg.Defaults(); err != nil { + return nil, err + } + log.Info().Interface("Config", cfg).Msg("Cluster configuration") + dur, err := time.ParseDuration(cfg.HelmValues["test.timeout"]) + if err != nil { + return nil, fmt.Errorf("failed to parse test timeout duration") + } + ctx, cancelFunc := context.WithTimeout(context.Background(), dur) + cp := &ClusterProfile{ + cfg: cfg, + c: NewK8sClient(), + Ctx: ctx, + Cancel: cancelFunc, + } + if cp.cfg.UpdateImage { + return cp, cp.buildAndPushImage() + } + return cp, nil +} + +func (m *ClusterProfile) buildAndPushImage() error { + registry, repo, tag, err := parseECRImageURI(m.cfg.HelmValues["image"]) + if err != nil { + return err + } + cmd := fmt.Sprintf("%s %s %s %s %s %s %s", + m.cfg.BuildScriptPath, + m.cfg.DockerfilePath, + m.cfg.BuildCtxPath, + tag, + registry, + repo, + m.cfg.DockerCmdExecPath, + ) + log.Info().Str("Cmd", cmd).Msg("Building docker") + return ExecCmd(cmd) +} + +func (m *ClusterProfile) deployHelm(testName string) error { + //nolint + defer os.Remove(m.cfg.tmpHelmFilePath) + var cmd strings.Builder + cmd.WriteString(fmt.Sprintf("helm install %s %s", testName, m.cfg.ChartPath)) + for k, v := range m.cfg.HelmValues { + cmd.WriteString(fmt.Sprintf(" --set %s=%s", k, v)) + } + cmd.WriteString(fmt.Sprintf(" -n %s", m.cfg.Namespace)) + cmd.WriteString(fmt.Sprintf(" --timeout %s", m.cfg.HelmDeployTimeoutSec)) + log.Info().Str("Cmd", cmd.String()).Msg("Deploying jobs") + return ExecCmd(cmd.String()) +} + +// Run starts a new test +func (m *ClusterProfile) Run() error { + testName := uuid.NewString()[0:8] + tn := []rune(testName) + // replace first letter, since helm does not allow it to start with numbers + tn[0] = 'a' + if err := m.deployHelm(string(tn)); err != nil { + return err + } + jobNum, err := strconv.Atoi(m.cfg.HelmValues["jobs"]) + if err != nil { + return err + } + return m.c.TrackJobs(m.Ctx, m.cfg.Namespace, m.cfg.HelmValues["sync"], jobNum, m.cfg.KeepJobs) +} diff --git a/wasp/cmd.go b/wasp/cmd.go new file mode 100644 index 000000000..ddedbf238 --- /dev/null +++ b/wasp/cmd.go @@ -0,0 +1,49 @@ +package wasp + +import ( + "bufio" + "io" + "os/exec" + "strings" + + "github.com/rs/zerolog/log" +) + +// ExecCmd executes os command, logging both streams +func ExecCmd(command string) error { + return ExecCmdWithStreamFunc(command, func(m string) { + log.Info().Str("Text", m).Msg("Command output") + }) +} + +// readStdPipe continuously read a pipe from the command +func readStdPipe(pipe io.ReadCloser, streamFunc func(string)) { + scanner := bufio.NewScanner(pipe) + scanner.Split(bufio.ScanLines) + for scanner.Scan() { + m := scanner.Text() + if streamFunc != nil { + streamFunc(m) + } + } +} + +// ExecCmdWithStreamFunc executes command with stream function +func ExecCmdWithStreamFunc(command string, outputFunction func(string)) error { + c := strings.Split(command, " ") + cmd := exec.Command(c[0], c[1:]...) + stderr, err := cmd.StderrPipe() + if err != nil { + return err + } + stdout, err := cmd.StdoutPipe() + if err != nil { + return err + } + if err := cmd.Start(); err != nil { + return err + } + go readStdPipe(stderr, outputFunction) + go readStdPipe(stdout, outputFunction) + return cmd.Wait() +} diff --git a/wasp/compose/conf/defaults.ini b/wasp/compose/conf/defaults.ini new file mode 100644 index 000000000..b2034acc9 --- /dev/null +++ b/wasp/compose/conf/defaults.ini @@ -0,0 +1,1238 @@ +##################### Grafana Configuration Defaults ##################### +# +# Do not modify this file in grafana installs +# + +# possible values : production, development +app_mode = production + +# instance name, defaults to HOSTNAME environment variable value or hostname if HOSTNAME var is empty +instance_name = ${HOSTNAME} + +# force migration will run migrations that might cause dataloss +force_migration = false + +#################################### Paths ############################### +[paths] +# Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used) +data = data + +# Temporary files in `data` directory older than given duration will be removed +temp_data_lifetime = 24h + +# Directory where grafana can store logs +logs = data/log + +# Directory where grafana will automatically scan and look for plugins +plugins = data/plugins + +# folder that contains provisioning config files that grafana will apply on startup and while running. +provisioning = conf/provisioning + +#################################### Server ############################## +[server] +# Protocol (http, https, h2, socket) +protocol = http + +# The ip address to bind to, empty will bind to all interfaces +http_addr = + +# The http port to use +http_port = 3000 + +# The public facing domain name used to access grafana from a browser +domain = localhost + +# Redirect to correct domain if host header does not match domain +# Prevents DNS rebinding attacks +enforce_domain = false + +# The full public facing url +root_url = %(protocol)s://%(domain)s:%(http_port)s/ + +# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons. +serve_from_sub_path = false + +# Log web requests +router_logging = false + +# the path relative working path +static_root_path = public + +# enable gzip +enable_gzip = false + +# https certs & key file +cert_file = +cert_key = + +# Unix socket path +socket = /tmp/grafana.sock + +# CDN Url +cdn_url = + +# Sets the maximum time in minutes before timing out read of an incoming request and closing idle connections. +# `0` means there is no timeout for reading the request. +read_timeout = 0 + +#################################### Database ############################ +[database] +# You can configure the database connection by specifying type, host, name, user and password +# as separate properties or as on string using the url property. + +# Either "mysql", "postgres" or "sqlite3", it's your choice +type = sqlite3 +host = 127.0.0.1:3306 +name = grafana +user = root +# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;""" +password = +# Use either URL or the previous fields to configure the database +# Example: mysql://user:secret@host:port/database +url = + +# Max idle conn setting default is 2 +max_idle_conn = 2 + +# Max conn setting default is 0 (mean not set) +max_open_conn = + +# Connection Max Lifetime default is 14400 (means 14400 seconds or 4 hours) +conn_max_lifetime = 14400 + +# Set to true to log the sql calls and execution times. +log_queries = + +# For "postgres", use either "disable", "require" or "verify-full" +# For "mysql", use either "true", "false", or "skip-verify". +ssl_mode = disable + +# Database drivers may support different transaction isolation levels. +# Currently, only "mysql" driver supports isolation levels. +# If the value is empty - driver's default isolation level is applied. +# For "mysql" use "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ" or "SERIALIZABLE". +isolation_level = + +ca_cert_path = +client_key_path = +client_cert_path = +server_cert_name = + +# For "sqlite3" only, path relative to data_path setting +path = grafana.db + +# For "sqlite3" only. cache mode setting used for connecting to the database +cache_mode = private + +# For "mysql" only if lockingMigration feature toggle is set. How many seconds to wait before failing to lock the database for the migrations, default is 0. +locking_attempt_timeout_sec = 0 + +#################################### Cache server ############################# +[remote_cache] +# Either "redis", "memcached" or "database" default is "database" +type = database + +# cache connectionstring options +# database: will use Grafana primary database. +# redis: config like redis server e.g. `addr=127.0.0.1:6379,pool_size=100,db=0,ssl=false`. Only addr is required. ssl may be 'true', 'false', or 'insecure'. +# memcache: 127.0.0.1:11211 +connstr = + +#################################### Data proxy ########################### +[dataproxy] + +# This enables data proxy logging, default is false +logging = false + +# How long the data proxy waits to read the headers of the response before timing out, default is 30 seconds. +# This setting also applies to core backend HTTP data sources where query requests use an HTTP client with timeout set. +timeout = 30 + +# How long the data proxy waits to establish a TCP connection before timing out, default is 10 seconds. +dialTimeout = 10 + +# How many seconds the data proxy waits before sending a keepalive request. +keep_alive_seconds = 30 + +# How many seconds the data proxy waits for a successful TLS Handshake before timing out. +tls_handshake_timeout_seconds = 10 + +# How many seconds the data proxy will wait for a server's first response headers after +# fully writing the request headers if the request has an "Expect: 100-continue" +# header. A value of 0 will result in the body being sent immediately, without +# waiting for the server to approve. +expect_continue_timeout_seconds = 1 + +# Optionally limits the total number of connections per host, including connections in the dialing, +# active, and idle states. On limit violation, dials will block. +# A value of zero (0) means no limit. +max_conns_per_host = 0 + +# The maximum number of idle connections that Grafana will keep alive. +max_idle_connections = 100 + +# How many seconds the data proxy keeps an idle connection open before timing out. +idle_conn_timeout_seconds = 90 + +# If enabled and user is not anonymous, data proxy will add X-Grafana-User header with username into the request. +send_user_header = false + +# Limit the amount of bytes that will be read/accepted from responses of outgoing HTTP requests. +response_limit = 0 + +# Limits the number of rows that Grafana will process from SQL data sources. +row_limit = 1000000 + +#################################### Analytics ########################### +[analytics] +# Server reporting, sends usage counters to stats.grafana.org every 24 hours. +# No ip addresses are being tracked, only simple counters to track +# running instances, dashboard and error counts. It is very helpful to us. +# Change this option to false to disable reporting. +reporting_enabled = true + +# The name of the distributor of the Grafana instance. Ex hosted-grafana, grafana-labs +reporting_distributor = grafana-labs + +# Set to false to disable all checks to https://grafana.com +# for new versions of grafana. The check is used +# in some UI views to notify that a grafana update exists. +# This option does not cause any auto updates, nor send any information +# only a GET request to https://raw.githubusercontent.com/grafana/grafana/main/latest.json to get the latest version. +check_for_updates = true + +# Set to false to disable all checks to https://grafana.com +# for new versions of plugins. The check is used +# in some UI views to notify that a plugin update exists. +# This option does not cause any auto updates, nor send any information +# only a GET request to https://grafana.com to get the latest versions. +check_for_plugin_updates = true + +# Google Analytics universal tracking code, only enabled if you specify an id here +google_analytics_ua_id = + +# Google Tag Manager ID, only enabled if you specify an id here +google_tag_manager_id = + +# Rudderstack write key, enabled only if rudderstack_data_plane_url is also set +rudderstack_write_key = + +# Rudderstack data plane url, enabled only if rudderstack_write_key is also set +rudderstack_data_plane_url = + +# Rudderstack SDK url, optional, only valid if rudderstack_write_key and rudderstack_data_plane_url is also set +rudderstack_sdk_url = + +# Rudderstack Config url, optional, used by Rudderstack SDK to fetch source config +rudderstack_config_url = + +# Application Insights connection string. Specify an URL string to enable this feature. +application_insights_connection_string = + +# Optional. Specifies an Application Insights endpoint URL where the endpoint string is wrapped in backticks ``. +application_insights_endpoint_url = + +# Controls if the UI contains any links to user feedback forms +feedback_links_enabled = true + +#################################### Security ############################ +[security] +# disable creation of admin user on first start of grafana +disable_initial_admin_creation = false + +# default admin user, created on startup +admin_user = admin + +# default admin password, can be changed before first start of grafana, or in profile settings +admin_password = admin + +# used for signing +secret_key = SW2YcwTIb9zpOOhoPsMm + +# current key provider used for envelope encryption, default to static value specified by secret_key +encryption_provider = secretKey.v1 + +# list of configured key providers, space separated (Enterprise only): e.g., awskms.v1 azurekv.v1 +available_encryption_providers = + +# disable gravatar profile images +disable_gravatar = false + +# data source proxy whitelist (ip_or_domain:port separated by spaces) +data_source_proxy_whitelist = + +# disable protection against brute force login attempts +disable_brute_force_login_protection = false + +# set to true if you host Grafana behind HTTPS. default is false. +cookie_secure = false + +# set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict", "none" and "disabled" +cookie_samesite = lax + +# set to true if you want to allow browsers to render Grafana in a ,