mirror of
https://github.com/luxfi/netrunner.git
synced 2026-07-27 00:04:23 +00:00
Remove k8s backend (#131)
* rm k8s implementation and backend type * finish removing k8s and multiple backend stuff * nits * update README * rm implSpecificConfig from json string * remove k8s from go.mod/sum Co-authored-by: Dan Laine <daniel.laine@avalabs.org>
This commit is contained in:
committed by
GitHub
co-authored by
Dan Laine
parent
d83115e00d
commit
6e90fb27d1
@@ -4,7 +4,6 @@ run:
|
||||
tests: false
|
||||
skip-dirs:
|
||||
- api/mocks
|
||||
- k8s/mocks
|
||||
- local/mocks
|
||||
- rpcpb
|
||||
go: "1.17"
|
||||
|
||||
@@ -443,33 +443,40 @@ A node config is defined by this struct:
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
// Configuration specific to a particular implementation of a node.
|
||||
ImplSpecificConfig interface{}
|
||||
// A node's name must be unique from all other nodes
|
||||
// in a network. If Name is the empty string, a
|
||||
// unique name is assigned on node creation.
|
||||
Name string
|
||||
Name string `json:"name"`
|
||||
// True if other nodes should use this node
|
||||
// as a bootstrap beacon.
|
||||
IsBeacon bool
|
||||
// Must not be nil
|
||||
StakingKey []byte
|
||||
// Must not be nil
|
||||
StakingCert []byte
|
||||
IsBeacon bool `json:"isBeacon"`
|
||||
// Must not be nil.
|
||||
StakingKey string `json:"stakingKey"`
|
||||
// Must not be nil.
|
||||
StakingCert string `json:"stakingCert"`
|
||||
// May be nil.
|
||||
ConfigFile []byte
|
||||
ConfigFile string `json:"configFile"`
|
||||
// May be nil.
|
||||
CChainConfigFile []byte
|
||||
CChainConfigFile string `json:"cChainConfigFile"`
|
||||
// Flags can hold additional flags for the node.
|
||||
// It can be empty.
|
||||
// The precedence of flags handling is:
|
||||
// 1. Flags defined in node.Config (this struct) override
|
||||
// 2. Flags defined in network.Config override
|
||||
// 3. Flags defined in the json config file
|
||||
Flags map[string]interface{} `json:"flags"`
|
||||
// What type of node this is
|
||||
BinaryPath string `json:"binaryPath"`
|
||||
// If non-nil, direct this node's Stdout to os.Stdout
|
||||
RedirectStdout bool `json:"redirectStdout"`
|
||||
// If non-nil, direct this node's Stderr to os.Stderr
|
||||
RedirectStderr bool `json:"redirectStderr"`
|
||||
}
|
||||
```
|
||||
|
||||
As you can see, some fields of the config must be set, while others will be auto-generated if not provided.
|
||||
Bootstrap IPs/ IDs will be overwritten even if provided.
|
||||
|
||||
A node's configuration may include fields that are specific to the type of network runner being used (see `ImplSpecificConfig` in the struct above.)
|
||||
For example, a node running in a Kubernetes cluster has a config field that specifies the Docker image that the node runs,
|
||||
whereas a node running locally has a config field that specifies the path of the binary that the node runs.
|
||||
|
||||
## Genesis Generation
|
||||
|
||||
You can create a custom AvalancheGo genesis with function `network.NewAvalancheGoGenesis`:
|
||||
@@ -494,25 +501,32 @@ Later on the genesis contents can be used in network creation.
|
||||
|
||||
## Network Creation
|
||||
|
||||
Each network runner implementation (local/Kubernetes) has a function `NewNetwork` that returns a new network,
|
||||
parameterized on `network.Config`:
|
||||
Th function `NewNetwork` returns a new network, parameterized on `network.Config`:
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
// Configuration specific to a particular implementation of a network.
|
||||
ImplSpecificConfig interface{}
|
||||
// Must not be nil
|
||||
Genesis []byte
|
||||
// Must not be empty
|
||||
Genesis string `json:"genesis"`
|
||||
// May have length 0
|
||||
// (i.e. network may have no nodes on creation.)
|
||||
NodeConfigs []node.Config
|
||||
NodeConfigs []node.Config `json:"nodeConfigs"`
|
||||
// Log level for the whole network
|
||||
LogLevel string
|
||||
LogLevel string `json:"logLevel"`
|
||||
// Name for the network
|
||||
Name string
|
||||
// How many nodes in the network.
|
||||
// TODO move to k8s package?
|
||||
NodeCount int
|
||||
Name string `json:"name"`
|
||||
// Flags that will be passed to each node in this network.
|
||||
// It can be empty.
|
||||
// Config flags may also be passed in a node's config struct
|
||||
// or config file.
|
||||
// The precedence of flags handling is, from highest to lowest:
|
||||
// 1. Flags defined in a node's node.Config
|
||||
// 2. Flags defined in a network's network.Config
|
||||
// 3. Flags defined in a node's config file
|
||||
// For example, if a network.Config has flag W set to X,
|
||||
// and a node within that network has flag W set to Y,
|
||||
// and the node's config file has flag W set to Z,
|
||||
// then the node will be started with flag W set to Y.
|
||||
Flags map[string]interface{} `json:"flags"`
|
||||
}
|
||||
```
|
||||
|
||||
@@ -520,7 +534,7 @@ The function that returns a new network may have additional configuration fields
|
||||
|
||||
## Default Network Creation
|
||||
|
||||
The local network runner implementation includes a helper function `NewDefaultNetwork`, which returns a network using a pre-defined configuration.
|
||||
The helper function `NewDefaultNetwork` returns a network using a pre-defined configuration.
|
||||
This allows users to create a new network without needing to define any configurations.
|
||||
|
||||
```go
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
# Build the manager binary
|
||||
#FROM golang:1.16 as builder
|
||||
FROM golang:1.17-bullseye as builder
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates git linux-headers-amd64 musl-dev gcc bash
|
||||
|
||||
# Copy the predefined netrc file into the location that git depends on
|
||||
COPY ./.netrc /root/.netrc
|
||||
RUN chmod 600 /root/.netrc
|
||||
|
||||
WORKDIR /workspace
|
||||
# Copy the Go Modules manifests
|
||||
COPY go.mod go.mod
|
||||
COPY go.sum go.sum
|
||||
# cache deps before building and copying source so that we don't need to re-download as much
|
||||
# and so that source changes don't invalidate our downloaded layer
|
||||
RUN go mod download
|
||||
|
||||
# Copy the go source
|
||||
copy network/ network/
|
||||
COPY api/ api/
|
||||
COPY k8s/ k8s/
|
||||
#COPY constants/ constants/
|
||||
COPY utils/ utils/
|
||||
COPY examples/ examples/
|
||||
|
||||
# Build
|
||||
RUN GOOS=linux GOARCH=amd64 go build -o simplenet ./examples/k8s/main.go
|
||||
|
||||
# Use distroless as minimal base image to package the manager binary
|
||||
# Refer to https://github.com/GoogleContainerTools/distroless for more details
|
||||
FROM gcr.io/distroless/base-debian11
|
||||
COPY --from=builder /workspace/simplenet /
|
||||
COPY --from=builder /workspace/examples/ /examples/
|
||||
|
||||
ENTRYPOINT ["/simplenet"]
|
||||
@@ -1,71 +0,0 @@
|
||||
# Kubernetes deployment of an avalanche network runner
|
||||
|
||||
## Scope
|
||||
The avalanche network runner can operate in
|
||||
* local
|
||||
* kubernetes
|
||||
|
||||
environments.
|
||||
|
||||
This README is *solely* about the kubernetes environment.
|
||||
|
||||
## Overview
|
||||
Avalanchego is a *stateful* application: It requires a DB and runs with an identity (NodeID).
|
||||
Standard Kubernetes is best suited for *stateless* applications.
|
||||
|
||||
To allow for stateful applications, the **Operator** pattern has been introduced into the kubernetes world [Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/).
|
||||
|
||||
This means that in order to successfully run an avalanchego network with this network runner tool on kubernetes, a "domain-specific" implementation of the pattern is required.
|
||||
This implementation can be found at [avalanchego-operator](https://github.com/ava-labs/avalanchego-operator).
|
||||
|
||||
There only needs to be running **1 operator instance** per kubernetes namespace.
|
||||
Therefore it is very important to distinguish between:
|
||||
|
||||
* A local kubernetes cluster environment
|
||||
* A cloud-based cluster environment
|
||||
|
||||
|
||||
## Cloud-based environment
|
||||
|
||||
### Github action
|
||||
If running in a cloud provided (for Ava Labs, typically AWS), then the **devops** team is responsible for setting up the required infrastructure.
|
||||
|
||||
**Devops would be deploying the `avalanchego-operator`**.
|
||||
|
||||
|
||||
The normal operation is to create a github action which triggers the deployment to the kubernetes cluster in the cloud.
|
||||
An example of such a github action can be found at `examples/github` **TODO**.
|
||||
The github action triggers the deployment of a self-contained pod or a permissioned `main` with access to the cluster.
|
||||
|
||||
In this scenario, devops needs to be informed about a project running such a github action using up kubernetes resources.
|
||||
They will then provide the necessary environment information (namespaces and other potentially required configurations) to be configured on the github action.
|
||||
They will also install the appropriate kubernetes self-hosted runner into the repository so that this integration will work.
|
||||
|
||||
Usually there would be nothing else to be done for the deployment other than implementing the network logic.
|
||||
|
||||
|
||||
### Without github action
|
||||
If a deployment without a github action should be required, then devops involvement is likewise required.
|
||||
They also would deploy the `avalanchego-operator` and provide necessary deployment information (namespace etc.).
|
||||
|
||||
The network runner can then analogously be deployed either via self-contained pod or a `main` binary. Both need to have the required permissions.
|
||||
|
||||
|
||||
## Local kubernetes environment
|
||||
Kubernetes can also be run locally. This is usually only needed for development. In fact, for "normal" avalanchego testing and work, it shouldn't be necessary to run a local kubernetes cluster. However, for developing the integration in this repository, it is highly recommended as it speeds up development time.
|
||||
|
||||
To run a local kubernetes environment:
|
||||
|
||||
|
||||
1. Install a kubernetes environment, e.g. `minikube` or `k3s`. We use `k3s` for this README: [k3s](https://k3s.io/). Follow instructions. This will also install `kubectl`.
|
||||
2. Make sure to run `sudo k3s server --docker --write-kubeconfig-mode 644`. This will allow to use **locally built images** (otherwise you'll need to use a public repo and push there). It may be required to `sudo systemctl stop k3s` service for `k3s` if the installation configured that mode, and disable it: `sudo systemctl disable k3s` (or edit the systemd script). Switch to other terminal.
|
||||
3. Install `kubectx` to allow to set an easy default environment: [kubectx](https://github.com/ahmetb/kubectx)
|
||||
4. Set the `$KUBECONFIG` environment variable to read the `k3s` environment: `export KUBECONFIG=/etc/rancher/k3s/k3s.yaml` (put this into your `.profile` or preferred environment persistance method). Make sure this variable is present in all terminals used for this tool.
|
||||
5. Run `kubectx` to check that the environment is fine (it should print `default` if there are no other kubernetes configs, otherwise, check the `kubectx` docs).
|
||||
6. **Run the avalanchego-operator locally**
|
||||
6a. Clone the repository: `github.com/ava-labs/avalanchego-operator`
|
||||
6b. Run `make install` followed by `make run`. This should be everything needed.
|
||||
7. Install the service account, role and roleconfigs for the network runner pod: `kubectl apply -f examples/k8s/svc-rbac.yaml`.
|
||||
8. Build this app as a pod: `docker build -f ./examples/k8s/Dockerfile -t k8s-netrunner:alpha .`. If you use a different app name than `k8s-netrunner` and/or tag `alpha`, the `examples/k8s/simple-network-pod.yaml` file needs to be updated accordingly.
|
||||
9. Deploy the pod to your local cluster via `kubectl apply -f examples/k8s/simple-netrunner-pod.yaml`. This picks the image built in 8. to deploy as a pod. Then from within this pod it starts all other nodes.
|
||||
10. Check that all is ok with `kubectl get pods`. You will first see the `k8s-netrunner` pod, and after some time, the other configured nodes should appear. To check logs, execute `kubectl logs k8s-netrunner`.
|
||||
@@ -1,48 +0,0 @@
|
||||
{
|
||||
"networkConfig": {
|
||||
"name": "custom-test-net",
|
||||
"logLevel": "DEBUG"
|
||||
},
|
||||
"k8sConfig": [
|
||||
{
|
||||
"namespace": "ci-avalanchego",
|
||||
"identifier": "avalanchego-test-validator-0",
|
||||
"kind": "Avalanchego",
|
||||
"apiVersion": "chain.avax.network/v1alpha1",
|
||||
"image": "avaplatform/avalanchego",
|
||||
"tag": "v1.6.4"
|
||||
},
|
||||
{
|
||||
"namespace": "ci-avalanchego",
|
||||
"identifier": "avalanchego-test-validator-1",
|
||||
"kind": "Avalanchego",
|
||||
"apiVersion": "chain.avax.network/v1alpha1",
|
||||
"image": "avaplatform/avalanchego",
|
||||
"tag": "v1.6.4"
|
||||
},
|
||||
{
|
||||
"namespace": "ci-avalanchego",
|
||||
"identifier": "avalanchego-test-validator-2",
|
||||
"kind": "Avalanchego",
|
||||
"apiVersion": "chain.avax.network/v1alpha1",
|
||||
"image": "avaplatform/avalanchego",
|
||||
"tag": "v1.6.4"
|
||||
},
|
||||
{
|
||||
"namespace": "ci-avalanchego",
|
||||
"identifier": "avalanchego-test-validator-3",
|
||||
"kind": "Avalanchego",
|
||||
"apiVersion": "chain.avax.network/v1alpha1",
|
||||
"image": "avaplatform/avalanchego",
|
||||
"tag": "v1.6.4"
|
||||
},
|
||||
{
|
||||
"namespace": "ci-avalanchego",
|
||||
"identifier": "avalanchego-test-validator-4",
|
||||
"kind": "Avalanchego",
|
||||
"apiVersion": "chain.avax.network/v1alpha1",
|
||||
"image": "avaplatform/avalanchego",
|
||||
"tag": "v1.6.4"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
{
|
||||
"networkID": 1337,
|
||||
"allocations": [
|
||||
{
|
||||
"ethAddr": "0xb3d82b1367d362de99ab59a658165aff520cbd4d",
|
||||
"avaxAddr": "X-custom1g65uqn6t77p656w64023nh8nd9updzmxwd59gh",
|
||||
"initialAmount": 0,
|
||||
"unlockSchedule": [
|
||||
{
|
||||
"amount": 10000000000000000,
|
||||
"locktime": 1633824000
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ethAddr": "0xb3d82b1367d362de99ab59a658165aff520cbd4d",
|
||||
"avaxAddr": "X-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p",
|
||||
"initialAmount": 300000000000000000,
|
||||
"unlockSchedule": [
|
||||
{
|
||||
"amount": 20000000000000000
|
||||
},
|
||||
{
|
||||
"amount": 10000000000000000,
|
||||
"locktime": 1633824000
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ethAddr": "0xb3d82b1367d362de99ab59a658165aff520cbd4d",
|
||||
"avaxAddr": "X-custom1ur873jhz9qnaqv5qthk5sn3e8nj3e0kmzpjrhp",
|
||||
"initialAmount": 10000000000000000,
|
||||
"unlockSchedule": [
|
||||
{
|
||||
"amount": 10000000000000000,
|
||||
"locktime": 1633824000
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"startTime": 1630987200,
|
||||
"initialStakeDuration": 31536000,
|
||||
"initialStakeDurationOffset": 5400,
|
||||
"initialStakedFunds": [
|
||||
"X-custom1g65uqn6t77p656w64023nh8nd9updzmxwd59gh"
|
||||
],
|
||||
"initialStakers": [
|
||||
{
|
||||
"nodeID": "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg",
|
||||
"rewardAddress": "X-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p",
|
||||
"delegationFee": 1000000
|
||||
},
|
||||
{
|
||||
"nodeID": "NodeID-MFrZFVCXPv5iCn6M9K6XduxGTYp891xXZ",
|
||||
"rewardAddress": "X-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p",
|
||||
"delegationFee": 500000
|
||||
},
|
||||
{
|
||||
"nodeID": "NodeID-NFBbbJ4qCmNaCzeW7sxErhvWqvEQMnYcN",
|
||||
"rewardAddress": "X-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p",
|
||||
"delegationFee": 250000
|
||||
},
|
||||
{
|
||||
"nodeID": "NodeID-GWPcbFJZFfZreETSoWjPimr846mXEKCtu",
|
||||
"rewardAddress": "X-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p",
|
||||
"delegationFee": 125000
|
||||
},
|
||||
{
|
||||
"nodeID": "NodeID-P7oB2McjBGgW2NXXWVYjV8JEDFoW9xDE5",
|
||||
"rewardAddress": "X-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p",
|
||||
"delegationFee": 62500
|
||||
}
|
||||
],
|
||||
"cChainGenesis": "{\"config\":{\"chainId\":43112,\"homesteadBlock\":0,\"daoForkBlock\":0,\"daoForkSupport\":true,\"eip150Block\":0,\"eip150Hash\":\"0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0,\"apricotPhase1BlockTimestamp\":0,\"apricotPhase2BlockTimestamp\":0},\"nonce\":\"0x0\",\"timestamp\":\"0x0\",\"extraData\":\"0x00\",\"gasLimit\":\"0x5f5e100\",\"difficulty\":\"0x0\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"coinbase\":\"0x0000000000000000000000000000000000000000\",\"alloc\":{\"8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC\":{\"balance\":\"0x295BE96E64066972000000\"}},\"number\":\"0x0\",\"gasUsed\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}",
|
||||
"message": "{{ fun_quote }}"
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"network-peer-list-gossip-frequency": "250ms",
|
||||
"network-max-reconnect-delay": "1s",
|
||||
"health-check-frequency": "2s",
|
||||
"log-level":"debug"
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,51 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"network-peer-list-gossip-frequency": "250ms",
|
||||
"network-max-reconnect-delay": "1s",
|
||||
"health-check-frequency": "2s",
|
||||
"log-level":"debug"
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,51 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"network-peer-list-gossip-frequency": "250ms",
|
||||
"network-max-reconnect-delay": "1s",
|
||||
"health-check-frequency": "2s",
|
||||
"log-level":"debug"
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,51 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"network-peer-list-gossip-frequency":"250ms",
|
||||
"network-max-reconnect-delay":"1s",
|
||||
"health-check-frequency":"2s",
|
||||
"log-level":"debug"
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,51 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"network-peer-list-gossip-frequency":"250ms",
|
||||
"network-max-reconnect-delay":"1s",
|
||||
"health-check-frequency":"2s",
|
||||
"log-level":"debug"
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,51 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,153 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/ava-labs/avalanche-network-runner/k8s"
|
||||
"github.com/ava-labs/avalanche-network-runner/network"
|
||||
"github.com/ava-labs/avalanche-network-runner/network/node"
|
||||
"github.com/ava-labs/avalanche-network-runner/utils"
|
||||
"github.com/ava-labs/avalanchego/utils/logging"
|
||||
)
|
||||
|
||||
const (
|
||||
// defaultNetworkTimeout to wait network to come up until deemed failed
|
||||
defaultNetworkTimeout = 120 * time.Second
|
||||
configFileName = "/conf.json"
|
||||
)
|
||||
|
||||
// TODO: shouldn't we think of something like Viper for loading config file?
|
||||
var goPath = os.ExpandEnv("$GOPATH")
|
||||
|
||||
// Network and node configs
|
||||
type allConfig struct {
|
||||
NetworkConfig network.Config `json:"networkConfig"`
|
||||
K8sConfig []k8s.ObjectSpec `json:"k8sConfig"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := run(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
// Create the logger
|
||||
logFactory := logging.NewFactory(logging.DefaultConfig)
|
||||
log, err := logFactory.Make("main")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
configDir := fmt.Sprintf("%s/src/github.com/ava-labs/avalanche-network-runner/examples/k8s", goPath)
|
||||
if goPath == "" {
|
||||
configDir = "./examples/k8s"
|
||||
}
|
||||
log.Info("reading config file...")
|
||||
configFile, err := os.ReadFile(configDir + configFileName)
|
||||
if err != nil {
|
||||
log.Fatal("%s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Network and node configs
|
||||
var allConfig allConfig
|
||||
if err := json.Unmarshal(configFile, &allConfig); err != nil {
|
||||
log.Fatal("%s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO maybe do networkConfig validation
|
||||
log.Info("parsing config...")
|
||||
networkConfig, err := readConfig(allConfig)
|
||||
if err != nil {
|
||||
log.Fatal("error reading configs: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
level, err := logging.ToLevel(networkConfig.LogLevel)
|
||||
if err != nil {
|
||||
log.Fatal("couldn't parse log: %s", err)
|
||||
return err
|
||||
}
|
||||
log.SetLogLevel(level)
|
||||
log.SetDisplayLevel(level)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultNetworkTimeout)
|
||||
defer cancel()
|
||||
|
||||
network, err := k8s.NewNetwork(log, networkConfig)
|
||||
if err != nil {
|
||||
log.Fatal("Error creating network: %s", err)
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := network.Stop(ctx); err != nil {
|
||||
log.Error("Error stopping network (ignored): %s", err)
|
||||
}
|
||||
}()
|
||||
|
||||
log.Info("Network created. Booting...")
|
||||
|
||||
errCh := network.Healthy(ctx)
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.Fatal("Timed out waiting for network to boot. Exiting.")
|
||||
return ctx.Err()
|
||||
case err := <-errCh:
|
||||
if err != nil {
|
||||
log.Fatal("Error booting network: %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.Info("Network created!!!")
|
||||
return nil
|
||||
}
|
||||
|
||||
func readConfig(rconfig allConfig) (network.Config, error) {
|
||||
configDir := "./examples/k8s/configs"
|
||||
genesisFile, err := os.ReadFile(fmt.Sprintf("%s/genesis.json", configDir))
|
||||
if err != nil {
|
||||
return network.Config{}, err
|
||||
}
|
||||
netcfg := rconfig.NetworkConfig
|
||||
netcfg.Genesis = string(genesisFile)
|
||||
netcfg.NodeConfigs = make([]node.Config, 0)
|
||||
for i, k := range rconfig.K8sConfig {
|
||||
nodeConfigDir := fmt.Sprintf("%s/node%d", configDir, i)
|
||||
key, err := os.ReadFile(fmt.Sprintf("%s/staking.key", nodeConfigDir))
|
||||
if err != nil {
|
||||
return network.Config{}, err
|
||||
}
|
||||
cert, err := os.ReadFile(fmt.Sprintf("%s/staking.crt", nodeConfigDir))
|
||||
if err != nil {
|
||||
return network.Config{}, err
|
||||
}
|
||||
configFile, err := os.ReadFile(fmt.Sprintf("%s/config.json", nodeConfigDir))
|
||||
if err != nil {
|
||||
return network.Config{}, err
|
||||
}
|
||||
c := node.Config{
|
||||
Name: fmt.Sprintf("validator-%d", i),
|
||||
StakingCert: string(cert),
|
||||
StakingKey: string(key),
|
||||
ConfigFile: string(configFile),
|
||||
ImplSpecificConfig: utils.NewK8sNodeConfigJsonRaw(
|
||||
k.APIVersion,
|
||||
k.Identifier,
|
||||
k.Image,
|
||||
k.Kind,
|
||||
k.Namespace,
|
||||
k.Tag,
|
||||
),
|
||||
IsBeacon: i == 0,
|
||||
}
|
||||
netcfg.NodeConfigs = append(netcfg.NodeConfigs, c)
|
||||
}
|
||||
return netcfg, nil
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: k8s-netrunner
|
||||
namespace: ci-avalanchego
|
||||
spec:
|
||||
containers:
|
||||
- name: k8s-netrunner
|
||||
image: k8s-netrunner:alpha
|
||||
imagePullPolicy: IfNotPresent
|
||||
restartPolicy: Never
|
||||
serviceAccountName: k8s-netrunner
|
||||
@@ -1,116 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: k8s-netrunner
|
||||
namespace: ci-avalanchego
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: k8s-netrunner
|
||||
rules:
|
||||
- apiGroups:
|
||||
- apps
|
||||
resources:
|
||||
- statefulsets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- chain.avax.network
|
||||
resources:
|
||||
- avalanchegoes
|
||||
- deployments
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- chain.avax.network
|
||||
resources:
|
||||
- avalanchegoes/finalizers
|
||||
verbs:
|
||||
- update
|
||||
- apiGroups:
|
||||
- chain.avax.network
|
||||
resources:
|
||||
- avalanchegoes/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
- pods
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- persistentvolumeclaims
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- services
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: k8s-netrunner
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: k8s-netrunner
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: k8s-netrunner
|
||||
namespace: ci-avalanchego
|
||||
---
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/ava-labs/avalanche-network-runner/local"
|
||||
"github.com/ava-labs/avalanche-network-runner/network"
|
||||
"github.com/ava-labs/avalanche-network-runner/network/node"
|
||||
"github.com/ava-labs/avalanche-network-runner/utils"
|
||||
"github.com/ava-labs/avalanchego/config"
|
||||
"github.com/ava-labs/avalanchego/staking"
|
||||
"github.com/ava-labs/avalanchego/utils/logging"
|
||||
@@ -123,10 +122,10 @@ func run(log logging.Logger, binaryPath string) error {
|
||||
return err
|
||||
}
|
||||
nodeConfig := node.Config{
|
||||
Name: "New Node",
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw(binaryPath),
|
||||
StakingKey: string(stakingKey),
|
||||
StakingCert: string(stakingCert),
|
||||
Name: "New Node",
|
||||
BinaryPath: binaryPath,
|
||||
StakingKey: string(stakingKey),
|
||||
StakingCert: string(stakingCert),
|
||||
// The flags below would override the config in this node's config file,
|
||||
// if it had one.
|
||||
Flags: map[string]interface{}{
|
||||
|
||||
@@ -4,7 +4,6 @@ go 1.17
|
||||
|
||||
require (
|
||||
github.com/ava-labs/avalanchego v1.7.11-0.20220416161358-8755486a274e
|
||||
github.com/ava-labs/avalanchego-operator v0.0.0-20211115144351-99f07d2570bf
|
||||
github.com/ava-labs/coreth v0.8.9-rc.1
|
||||
github.com/ethereum/go-ethereum v1.10.16
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.2
|
||||
@@ -18,9 +17,6 @@ require (
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa
|
||||
google.golang.org/grpc v1.43.0
|
||||
google.golang.org/protobuf v1.27.1
|
||||
k8s.io/api v0.22.3
|
||||
k8s.io/apimachinery v0.22.3
|
||||
sigs.k8s.io/controller-runtime v0.10.2
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -35,24 +31,17 @@ require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/deckarep/golang-set v1.8.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v3 v3.0.0-20200627015759-01fd2de07837 // indirect
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
|
||||
github.com/go-logr/logr v0.4.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.1 // indirect
|
||||
github.com/go-stack/stack v1.8.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/go-cmp v0.5.6 // indirect
|
||||
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa // indirect
|
||||
github.com/google/uuid v1.1.5 // indirect
|
||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gorilla/rpc v1.2.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
@@ -66,11 +55,9 @@ require (
|
||||
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
|
||||
github.com/holiman/uint256 v1.2.0 // indirect
|
||||
github.com/huin/goupnp v1.0.2 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/jackpal/gateway v1.0.6 // indirect
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||
github.com/linxGnu/grocksdb v1.6.34 // indirect
|
||||
github.com/magiconair/properties v1.8.5 // indirect
|
||||
@@ -81,14 +68,11 @@ require (
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/mitchellh/pointerstructure v1.2.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.26.0 // indirect
|
||||
@@ -113,25 +97,13 @@ require (
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
||||
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
|
||||
gonum.org/v1/gonum v0.9.1 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.66.2 // indirect
|
||||
gopkg.in/urfave/cli.v1 v1.20.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
k8s.io/apiextensions-apiserver v0.22.2 // indirect
|
||||
k8s.io/client-go v0.22.3 // indirect
|
||||
k8s.io/component-base v0.22.2 // indirect
|
||||
k8s.io/klog/v2 v2.9.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect
|
||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
||||
@@ -125,7 +125,6 @@ github.com/ava-labs/avalanchego v1.7.7-rc.4/go.mod h1:ZFuoVdAoCKS3Q4NFBKsR7TVCGy
|
||||
github.com/ava-labs/avalanchego v1.7.8/go.mod h1:1QNPNIFEYjNevyzaGx+RhdhWGG5LiA6Mn3iomnkf/h0=
|
||||
github.com/ava-labs/avalanchego v1.7.11-0.20220416161358-8755486a274e h1:BC9sVeGLUgT/hPiQQs8WSD6jLlck1r51J8SM4ihJhg4=
|
||||
github.com/ava-labs/avalanchego v1.7.11-0.20220416161358-8755486a274e/go.mod h1:QVjeerfAaeS//G34swRgfrZu77SRpcprOkvkrJ+MeVE=
|
||||
github.com/ava-labs/avalanchego-operator v0.0.0-20211115144351-99f07d2570bf h1:vHIdrlBIqbkqbERfPX3Ut+Ofg2vsqdB8OC6JMegT0qk=
|
||||
github.com/ava-labs/avalanchego-operator v0.0.0-20211115144351-99f07d2570bf/go.mod h1:RTkVkouQ0HBSBVSFAQCUviXPU7Iuxoy+Fui3ykmD9HA=
|
||||
github.com/ava-labs/coreth v0.8.4-rc.1/go.mod h1:bP2Atm7pCJdx8fwzsPT3xU/kWOdHFklpja7aRNT++Qo=
|
||||
github.com/ava-labs/coreth v0.8.4-rc.3/go.mod h1:9TgpLJVY9ot6RV8Lh66F356S4MfalvaL3sAqw4+miTU=
|
||||
@@ -271,7 +270,6 @@ github.com/ethereum/go-ethereum v1.10.16 h1:3oPrumn0bCW/idjcxMn5YYVCdK7VzJYIvwGZ
|
||||
github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y=
|
||||
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs=
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
@@ -315,9 +313,7 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc=
|
||||
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-logr/zapr v0.4.0 h1:uc1uML3hRYL9/ZZPdgHS/n8Nzo+eaYL/Efxkkamf7OM=
|
||||
github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=
|
||||
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
|
||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||
@@ -342,7 +338,6 @@ github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
@@ -356,7 +351,6 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
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/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
@@ -411,7 +405,6 @@ github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64=
|
||||
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
@@ -444,7 +437,6 @@ github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pf
|
||||
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
|
||||
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
||||
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
|
||||
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
|
||||
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
@@ -533,7 +525,6 @@ github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
@@ -570,7 +561,6 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11/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/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
@@ -676,11 +666,9 @@ github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0Gq
|
||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
|
||||
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A=
|
||||
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/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
@@ -1087,7 +1075,6 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
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=
|
||||
@@ -1294,7 +1281,6 @@ 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY=
|
||||
gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY=
|
||||
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||
@@ -1343,7 +1329,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
@@ -1467,7 +1452,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
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/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.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
|
||||
@@ -1509,39 +1493,31 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
|
||||
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
|
||||
k8s.io/api v0.21.2/go.mod h1:Lv6UGJZ1rlMI1qusN8ruAp9PUBFyBwpEHAdG24vIsiU=
|
||||
k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8=
|
||||
k8s.io/api v0.22.3 h1:wOoES2GoSkUsdped2RB4zYypPqWtvprGoKCENTOOjP4=
|
||||
k8s.io/api v0.22.3/go.mod h1:azgiXFiXqiWyLCfI62/eYBOu19rj2LKmIhFPP4+33fs=
|
||||
k8s.io/apiextensions-apiserver v0.21.2/go.mod h1:+Axoz5/l3AYpGLlhJDfcVQzCerVYq3K3CvDMvw6X1RA=
|
||||
k8s.io/apiextensions-apiserver v0.22.2 h1:zK7qI8Ery7j2CaN23UCFaC1hj7dMiI87n01+nKuewd4=
|
||||
k8s.io/apiextensions-apiserver v0.22.2/go.mod h1:2E0Ve/isxNl7tWLSUDgi6+cmwHi5fQRdwGVCxbC+KFA=
|
||||
k8s.io/apimachinery v0.21.2/go.mod h1:CdTY8fU/BlvAbJ2z/8kBwimGki5Zp8/fbVuLY8gJumM=
|
||||
k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
|
||||
k8s.io/apimachinery v0.22.3 h1:mrvBG5CZnEfwgpVqWcrRKvdsYECTrhAR6cApAgdsflk=
|
||||
k8s.io/apimachinery v0.22.3/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
|
||||
k8s.io/apiserver v0.21.2/go.mod h1:lN4yBoGyiNT7SC1dmNk0ue6a5Wi6O3SWOIw91TsucQw=
|
||||
k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI=
|
||||
k8s.io/client-go v0.21.2/go.mod h1:HdJ9iknWpbl3vMGtib6T2PyI/VYxiZfq936WNVHBRrA=
|
||||
k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U=
|
||||
k8s.io/client-go v0.22.3 h1:6onkOSc+YNdwq5zXE0wFXicq64rrym+mXwHu/CPVGO4=
|
||||
k8s.io/client-go v0.22.3/go.mod h1:ElDjYf8gvZsKDYexmsmnMQ0DYO8W9RwBjfQ1PI53yow=
|
||||
k8s.io/code-generator v0.21.2/go.mod h1:8mXJDCB7HcRo1xiEQstcguZkbxZaqeUOrO9SsicWs3U=
|
||||
k8s.io/code-generator v0.22.2/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o=
|
||||
k8s.io/component-base v0.21.2/go.mod h1:9lvmIThzdlrJj5Hp8Z/TOgIkdfsNARQ1pT+3PByuiuc=
|
||||
k8s.io/component-base v0.22.2 h1:vNIvE0AIrLhjX8drH0BgCNJcR4QZxMXcJzBsDplDx9M=
|
||||
k8s.io/component-base v0.22.2/go.mod h1:5Br2QhI9OTe79p+TzPe9JKNQYvEKbq9rTJDWllunGug=
|
||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
|
||||
k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM=
|
||||
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
|
||||
k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE=
|
||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM=
|
||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20210527160623-6fdb442a123b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g=
|
||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
@@ -1550,13 +1526,10 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.19/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
|
||||
sigs.k8s.io/controller-runtime v0.9.2/go.mod h1:TxzMCHyEUpaeuOiZx/bIdc2T81vfs/aKdvJt9wuu0zk=
|
||||
sigs.k8s.io/controller-runtime v0.10.2 h1:jW8qiY+yMnnPx6O9hu63tgcwaKzd1yLYui+mpvClOOc=
|
||||
sigs.k8s.io/controller-runtime v0.10.2/go.mod h1:CQp8eyUQZ/Q7PJvnIrB6/hgfTC1kBkGylwsLgOQi1WY=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package k8s
|
||||
|
||||
import "time"
|
||||
|
||||
// TODO make these configurable
|
||||
const (
|
||||
resourceLimitsCPU = "1"
|
||||
resourceLimitsMemory = "4Gi"
|
||||
resourceRequestCPU = "500m"
|
||||
resourceRequestMemory = "2Gi"
|
||||
stopTimeout = 10 * time.Second
|
||||
removeTimeout = 30 * time.Second
|
||||
nodeReachableCheckFreq = 5 * time.Second
|
||||
healthCheckFreq = 3 * time.Second
|
||||
// TODO export these default ports from the
|
||||
// AvalancheGo operator and use the imported
|
||||
// values instead of re-defining them below.
|
||||
defaultAPIPort = uint16(9650)
|
||||
defaultP2PPort = uint16(9651)
|
||||
)
|
||||
@@ -1,28 +0,0 @@
|
||||
// Code generated by mockery v2.9.4. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// DnsReachableChecker is an autogenerated mock type for the dnsReachableChecker type
|
||||
type DnsReachableChecker struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// Reachable provides a mock function with given fields: ctx, url
|
||||
func (_m *DnsReachableChecker) Reachable(ctx context.Context, url string) bool {
|
||||
ret := _m.Called(ctx, url)
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) bool); ok {
|
||||
r0 = rf(ctx, url)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
// Code generated by mockery v2.9.4. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
client "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
meta "k8s.io/apimachinery/pkg/api/meta"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
// Client is an autogenerated mock type for the Client type
|
||||
type Client struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// Create provides a mock function with given fields: ctx, obj, opts
|
||||
func (_m *Client) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, obj)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.CreateOption) error); ok {
|
||||
r0 = rf(ctx, obj, opts...)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Delete provides a mock function with given fields: ctx, obj, opts
|
||||
func (_m *Client) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, obj)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.DeleteOption) error); ok {
|
||||
r0 = rf(ctx, obj, opts...)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// DeleteAllOf provides a mock function with given fields: ctx, obj, opts
|
||||
func (_m *Client) DeleteAllOf(ctx context.Context, obj client.Object, opts ...client.DeleteAllOfOption) error {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, obj)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.DeleteAllOfOption) error); ok {
|
||||
r0 = rf(ctx, obj, opts...)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Get provides a mock function with given fields: ctx, key, obj
|
||||
func (_m *Client) Get(ctx context.Context, key types.NamespacedName, obj client.Object) error {
|
||||
ret := _m.Called(ctx, key, obj)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, types.NamespacedName, client.Object) error); ok {
|
||||
r0 = rf(ctx, key, obj)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// List provides a mock function with given fields: ctx, list, opts
|
||||
func (_m *Client) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, list)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, client.ObjectList, ...client.ListOption) error); ok {
|
||||
r0 = rf(ctx, list, opts...)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Patch provides a mock function with given fields: ctx, obj, patch, opts
|
||||
func (_m *Client) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, obj, patch)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, client.Object, client.Patch, ...client.PatchOption) error); ok {
|
||||
r0 = rf(ctx, obj, patch, opts...)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// RESTMapper provides a mock function with given fields:
|
||||
func (_m *Client) RESTMapper() meta.RESTMapper {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 meta.RESTMapper
|
||||
if rf, ok := ret.Get(0).(func() meta.RESTMapper); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(meta.RESTMapper)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Scheme provides a mock function with given fields:
|
||||
func (_m *Client) Scheme() *runtime.Scheme {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 *runtime.Scheme
|
||||
if rf, ok := ret.Get(0).(func() *runtime.Scheme); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*runtime.Scheme)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Status provides a mock function with given fields:
|
||||
func (_m *Client) Status() client.StatusWriter {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 client.StatusWriter
|
||||
if rf, ok := ret.Get(0).(func() client.StatusWriter); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(client.StatusWriter)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Update provides a mock function with given fields: ctx, obj, opts
|
||||
func (_m *Client) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, obj)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, client.Object, ...client.UpdateOption) error); ok {
|
||||
r0 = rf(ctx, obj, opts...)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
-461
@@ -1,461 +0,0 @@
|
||||
package k8s
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ava-labs/avalanche-network-runner/api"
|
||||
"github.com/ava-labs/avalanche-network-runner/network"
|
||||
"github.com/ava-labs/avalanche-network-runner/network/node"
|
||||
"github.com/ava-labs/avalanchego/ids"
|
||||
"github.com/ava-labs/avalanchego/utils/constants"
|
||||
"github.com/ava-labs/avalanchego/utils/logging"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
k8sapi "github.com/ava-labs/avalanchego-operator/api/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
k8scli "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
const (
|
||||
// How long we'll wait for a kubernetes pod to become reachable
|
||||
nodeReachableTimeout = 2 * time.Minute
|
||||
// Time between checks to see if a node is reachable
|
||||
nodeReachableRetryFreq = 3 * time.Second
|
||||
// Prefix the avalanchego-operator uses to pass params to avalanchego nodes
|
||||
envVarPrefix = "AVAGO_"
|
||||
)
|
||||
|
||||
var _ network.Network = (*networkImpl)(nil)
|
||||
|
||||
// networkParams encapsulate params to create a network
|
||||
type networkParams struct {
|
||||
conf network.Config
|
||||
log logging.Logger
|
||||
k8sClient k8scli.Client
|
||||
dnsChecker dnsReachableChecker
|
||||
apiClientFunc api.NewAPIClientF
|
||||
}
|
||||
|
||||
// networkImpl is the kubernetes data type representing a kubernetes network adapter.
|
||||
// It implements the network.Network interface.
|
||||
type networkImpl struct {
|
||||
log logging.Logger
|
||||
config network.Config
|
||||
// the kubernetes client
|
||||
k8scli k8scli.Client
|
||||
// Must be held when [nodes.lock] is accessed
|
||||
nodesLock sync.RWMutex
|
||||
// Node name --> The node.
|
||||
// If there is a running k8s pod for a node, it's in [nodes]
|
||||
nodes map[string]*Node
|
||||
// URI of the beacon node
|
||||
// TODO allow multiple beacons
|
||||
beaconURL string
|
||||
// Closed when network is done shutting down
|
||||
closedOnStopCh chan struct{}
|
||||
// Checks if a node is reachable via DNS
|
||||
dnsChecker dnsReachableChecker
|
||||
// Create the K8s API client
|
||||
apiClientFunc api.NewAPIClientF
|
||||
}
|
||||
|
||||
func newK8sClient() (k8scli.Client, error) {
|
||||
// init k8s client
|
||||
scheme := runtime.NewScheme()
|
||||
if err := k8sapi.AddToScheme(scheme); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kubeconfig := ctrl.GetConfigOrDie()
|
||||
return k8scli.New(kubeconfig, k8scli.Options{Scheme: scheme})
|
||||
}
|
||||
|
||||
// If this function returns a nil error, you *must* eventually call
|
||||
// Stop() on the returned network. Failure to do so will cause old
|
||||
// state to linger in k8s.
|
||||
func newNetwork(params networkParams) (network.Network, error) {
|
||||
beacons, nonBeacons, err := createDeploymentFromConfig(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(beacons) == 0 {
|
||||
return nil, errors.New("NodeConfigs don't have any beacon nodes")
|
||||
}
|
||||
net := &networkImpl{
|
||||
config: params.conf,
|
||||
k8scli: params.k8sClient,
|
||||
closedOnStopCh: make(chan struct{}),
|
||||
log: params.log,
|
||||
nodes: make(map[string]*Node, len(params.conf.NodeConfigs)),
|
||||
dnsChecker: params.dnsChecker,
|
||||
apiClientFunc: params.apiClientFunc,
|
||||
}
|
||||
net.log.Debug("launching beacon nodes...")
|
||||
// Start the beacon nodes and wait until they're reachable
|
||||
if err := net.launchNodes(beacons); err != nil {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), stopTimeout)
|
||||
defer cancel()
|
||||
if err := net.Stop(ctx); err != nil {
|
||||
net.log.Warn("error stopping network: %s", err)
|
||||
}
|
||||
return nil, fmt.Errorf("error launching beacons: %w", err)
|
||||
}
|
||||
// Tell future nodes the IP of the beacon node
|
||||
// TODO add support for multiple beacons
|
||||
// TODO don't rely on [beacons] being updated in launchNodes.
|
||||
// It's not a very clean pattern.
|
||||
net.beaconURL = beacons[0].Status.NetworkMembersURI[0]
|
||||
if net.beaconURL == "" {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), stopTimeout)
|
||||
defer cancel()
|
||||
if err := net.Stop(ctx); err != nil {
|
||||
net.log.Warn("error stopping network: %s", err)
|
||||
}
|
||||
return nil, errors.New("Bootstrap URI is set to empty")
|
||||
}
|
||||
net.log.Info("Beacon node started")
|
||||
// Start the non-beacon nodes and wait until they're reachable
|
||||
if err := net.launchNodes(nonBeacons); err != nil {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), stopTimeout)
|
||||
defer cancel()
|
||||
if err := net.Stop(ctx); err != nil {
|
||||
net.log.Warn("error stopping network: %s", err)
|
||||
}
|
||||
return nil, fmt.Errorf("Error launching non-beacons: %s", err)
|
||||
}
|
||||
net.log.Info("All nodes started. Network: %s", net)
|
||||
return net, nil
|
||||
}
|
||||
|
||||
// NewNetwork returns a new network whose initial state is specified in the config
|
||||
func NewNetwork(log logging.Logger, conf network.Config) (network.Network, error) {
|
||||
k8sClient, err := newK8sClient()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't create k8s client: %w", err)
|
||||
}
|
||||
return newNetwork(networkParams{
|
||||
conf: conf,
|
||||
log: log,
|
||||
k8sClient: k8sClient,
|
||||
// TODO is there a better way to wait until the node is reachable?
|
||||
dnsChecker: &defaultDNSReachableChecker{},
|
||||
apiClientFunc: api.NewAPIClient,
|
||||
})
|
||||
}
|
||||
|
||||
// See network.Network
|
||||
func (a *networkImpl) GetNodeNames() ([]string, error) {
|
||||
a.nodesLock.RLock()
|
||||
defer a.nodesLock.RUnlock()
|
||||
|
||||
if a.isStopped() {
|
||||
return nil, network.ErrStopped
|
||||
}
|
||||
|
||||
nodes := make([]string, len(a.nodes))
|
||||
i := 0
|
||||
for _, n := range a.nodes {
|
||||
nodes[i] = n.name
|
||||
i++
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
// See network.Network
|
||||
func (a *networkImpl) Healthy(ctx context.Context) chan error {
|
||||
a.nodesLock.RLock()
|
||||
defer a.nodesLock.RUnlock()
|
||||
|
||||
errCh := make(chan error, 1)
|
||||
if a.isStopped() {
|
||||
errCh <- network.ErrStopped
|
||||
return errCh
|
||||
}
|
||||
nodes := make([]*Node, 0, len(a.nodes))
|
||||
for _, node := range a.nodes {
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
go func() {
|
||||
errGr, ctx := errgroup.WithContext(ctx)
|
||||
for _, node := range nodes {
|
||||
node := node
|
||||
errGr.Go(func() error {
|
||||
// Every constants.HealthCheckInterval, query node for health status.
|
||||
// Do this until ctx timeout
|
||||
for {
|
||||
select {
|
||||
case <-a.closedOnStopCh:
|
||||
return network.ErrStopped
|
||||
case <-ctx.Done():
|
||||
return fmt.Errorf("node %q failed to become healthy within timeout", node.GetName())
|
||||
case <-time.After(healthCheckFreq):
|
||||
}
|
||||
health, err := node.apiClient.HealthAPI().Health(ctx)
|
||||
if err == nil && health.Healthy {
|
||||
a.log.Info("node %q became healthy", node.GetName())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// Wait until all nodes are ready or timeout
|
||||
if err := errGr.Wait(); err != nil {
|
||||
errCh <- err
|
||||
}
|
||||
close(errCh)
|
||||
}()
|
||||
return errCh
|
||||
}
|
||||
|
||||
// See network.Network
|
||||
func (a *networkImpl) Stop(ctx context.Context) error {
|
||||
a.nodesLock.Lock()
|
||||
defer a.nodesLock.Unlock()
|
||||
|
||||
if a.isStopped() {
|
||||
return network.ErrStopped
|
||||
}
|
||||
|
||||
failCount := 0
|
||||
for nodeName, node := range a.nodes {
|
||||
a.log.Debug("Shutting down node %q...", nodeName)
|
||||
if err := a.k8scli.Delete(ctx, node.k8sObjSpec); err != nil {
|
||||
a.log.Error("error while stopping node %s: %s", node.name, err)
|
||||
failCount++
|
||||
}
|
||||
delete(a.nodes, nodeName)
|
||||
}
|
||||
close(a.closedOnStopCh)
|
||||
if failCount > 0 {
|
||||
return fmt.Errorf("%d nodes failed shutting down", failCount)
|
||||
}
|
||||
a.log.Info("Network stopped")
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddNode starts a new node with the given config and blocks
|
||||
// until it is reachable.
|
||||
// Assumes [a.nodesLock] isn't held.
|
||||
func (a *networkImpl) AddNode(cfg node.Config) (node.Node, error) {
|
||||
a.nodesLock.RLock()
|
||||
isStopped := a.isStopped()
|
||||
a.nodesLock.RUnlock()
|
||||
|
||||
// TODO fix this is race condition:
|
||||
// Stop() can be called after the lock is released above.
|
||||
// If that happens, we'll create the pod inside launchNodes
|
||||
// and then never destroy it.
|
||||
// launchNodes assumes [a.nodesLock] isn't held so we can't just
|
||||
// hold the lock inside this method to fix this race condition.
|
||||
if isStopped {
|
||||
return nil, network.ErrStopped
|
||||
}
|
||||
|
||||
nodeSpec, err := buildK8sObjSpec(a.log, []byte(a.config.Genesis), cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
a.log.Debug("Launching new node %s to network...", cfg.Name)
|
||||
if err := a.launchNodes([]*k8sapi.Avalanchego{nodeSpec}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
a.nodesLock.RLock()
|
||||
defer a.nodesLock.RUnlock()
|
||||
return a.nodes[nodeSpec.Name], nil
|
||||
}
|
||||
|
||||
// See network.Network
|
||||
func (a *networkImpl) RemoveNode(name string) error {
|
||||
a.nodesLock.Lock()
|
||||
defer a.nodesLock.Unlock()
|
||||
|
||||
if a.isStopped() {
|
||||
return network.ErrStopped
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), removeTimeout)
|
||||
defer cancel()
|
||||
|
||||
if node, ok := a.nodes[name]; ok {
|
||||
if err := a.k8scli.Delete(ctx, node.k8sObjSpec); err != nil {
|
||||
return err
|
||||
}
|
||||
a.log.Info("Removed node %q", name)
|
||||
delete(a.nodes, name)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("node %q not found", name)
|
||||
}
|
||||
|
||||
// GetAllNodes returns all nodes
|
||||
func (a *networkImpl) GetAllNodes() (map[string]node.Node, error) {
|
||||
a.nodesLock.RLock()
|
||||
defer a.nodesLock.RUnlock()
|
||||
|
||||
if a.isStopped() {
|
||||
return nil, network.ErrStopped
|
||||
}
|
||||
|
||||
nodesCopy := make(map[string]node.Node, len(a.nodes))
|
||||
for nodeName, node := range a.nodes {
|
||||
nodesCopy[nodeName] = node
|
||||
}
|
||||
return nodesCopy, nil
|
||||
}
|
||||
|
||||
// See network.Network
|
||||
func (a *networkImpl) GetNode(name string) (node.Node, error) {
|
||||
a.nodesLock.RLock()
|
||||
defer a.nodesLock.RUnlock()
|
||||
|
||||
if a.isStopped() {
|
||||
return nil, network.ErrStopped
|
||||
}
|
||||
if n, ok := a.nodes[name]; ok {
|
||||
return n, nil
|
||||
}
|
||||
return nil, fmt.Errorf("node %q not found", name)
|
||||
}
|
||||
|
||||
// Assumes [a.nodesLock] is held
|
||||
func (net *networkImpl) isStopped() bool {
|
||||
select {
|
||||
case <-net.closedOnStopCh:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Creates the given nodes and blocks until they're all reachable.
|
||||
// Assumes [a.nodesLock] isn't held.
|
||||
func (a *networkImpl) launchNodes(nodeSpecs []*k8sapi.Avalanchego) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
errGr, ctx := errgroup.WithContext(ctx)
|
||||
for _, nodeSpec := range nodeSpecs {
|
||||
nodeSpec := nodeSpec
|
||||
errGr.Go(func() error {
|
||||
if err := a.launchNode(ctx, nodeSpec); err != nil {
|
||||
return fmt.Errorf("error launching node %q: %w", nodeSpec.Spec.DeploymentName, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return errGr.Wait()
|
||||
}
|
||||
|
||||
// Create the given node in k8s and block until it's reachable.
|
||||
// Assumes [a.nodesLock] isn't held.
|
||||
func (a *networkImpl) launchNode(ctx context.Context, nodeSpec *k8sapi.Avalanchego) error {
|
||||
ctx, cancel := context.WithTimeout(ctx, nodeReachableTimeout)
|
||||
defer cancel()
|
||||
|
||||
a.nodesLock.Lock()
|
||||
if a.beaconURL != "" {
|
||||
nodeSpec.Spec.BootstrapperURL = a.beaconURL
|
||||
}
|
||||
// Update [a.nodes] so that we'll delete this node on stop
|
||||
a.nodes[nodeSpec.Spec.DeploymentName] = &Node{
|
||||
name: nodeSpec.Spec.DeploymentName,
|
||||
k8sObjSpec: nodeSpec,
|
||||
}
|
||||
// Create a Kubernetes pod for this node
|
||||
err := a.k8scli.Create(ctx, nodeSpec)
|
||||
a.nodesLock.Unlock()
|
||||
if err != nil {
|
||||
return fmt.Errorf("k8scli.Create failed: %w", err)
|
||||
}
|
||||
|
||||
a.log.Debug("Waiting for pod to be created for node %q...", nodeSpec.Spec.DeploymentName)
|
||||
for len(nodeSpec.Status.NetworkMembersURI) != 1 {
|
||||
if err := a.k8scli.Get(ctx, types.NamespacedName{
|
||||
Name: nodeSpec.Name,
|
||||
Namespace: nodeSpec.Namespace,
|
||||
}, nodeSpec); err != nil {
|
||||
return fmt.Errorf("k8scli.Get failed: %w", err)
|
||||
}
|
||||
select {
|
||||
case <-time.After(nodeReachableCheckFreq):
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
a.log.Debug("pod created. Waiting to be reachable...")
|
||||
// Try connecting to nodes until the DNS resolves,
|
||||
// otherwise we have to sleep indiscriminately, we can't just use the API right away:
|
||||
// the kubernetes cluster has already created the pod(s) but not the DNS names,
|
||||
// so using the API Client too early results in an error.
|
||||
url := nodeSpec.Status.NetworkMembersURI[0]
|
||||
apiURL := fmt.Sprintf("http://%s:%d", url, defaultAPIPort)
|
||||
reachableLoop:
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
a.log.Debug("checking if %q is reachable at %s...", nodeSpec.Spec.DeploymentName, apiURL)
|
||||
if reachable := a.dnsChecker.Reachable(ctx, apiURL); reachable {
|
||||
a.log.Debug("%q has become reachable", nodeSpec.Spec.DeploymentName)
|
||||
break reachableLoop
|
||||
}
|
||||
// Wait before checking again
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-time.After(nodeReachableRetryFreq):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create an API client
|
||||
a.log.Debug("creating network node and client for %s", url)
|
||||
apiClient := a.apiClientFunc(url, defaultAPIPort)
|
||||
// Get this node's ID
|
||||
// TODO should we get this by parsing the key/cert?
|
||||
nodeIDStr, err := apiClient.InfoAPI().GetNodeID(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't get node ID: %w", err)
|
||||
}
|
||||
nodeID, err := ids.ShortFromPrefixedString(nodeIDStr, constants.NodeIDPrefix)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse node ID %q from string: %s", nodeIDStr, err)
|
||||
}
|
||||
// Update node info
|
||||
a.nodesLock.Lock()
|
||||
a.nodes[nodeSpec.Spec.DeploymentName].uri = url
|
||||
a.nodes[nodeSpec.Spec.DeploymentName].apiClient = apiClient
|
||||
a.nodes[nodeSpec.Spec.DeploymentName].nodeID = nodeID
|
||||
a.nodesLock.Unlock()
|
||||
a.log.Debug("Name: %s, NodeID: %s, URI: %s", nodeSpec.Spec.DeploymentName, nodeID, url)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns a string representing the network nodes
|
||||
func (a *networkImpl) String() string {
|
||||
a.nodesLock.RLock()
|
||||
defer a.nodesLock.RUnlock()
|
||||
|
||||
s := strings.Builder{}
|
||||
_, _ = s.WriteString("\n****************************************************************************************************\n")
|
||||
_, _ = s.WriteString(" List of nodes in the network: \n")
|
||||
_, _ = s.WriteString(" +------------------------------------------------------------------------------------------------+\n")
|
||||
_, _ = s.WriteString(" + NodeID | Label | Cluster URI +\n")
|
||||
_, _ = s.WriteString(" +------------------------------------------------------------------------------------------------+\n")
|
||||
for _, n := range a.nodes {
|
||||
s.WriteString(fmt.Sprintf(" %s %s %s\n", n.nodeID, n.name, n.uri))
|
||||
}
|
||||
s.WriteString("****************************************************************************************************\n")
|
||||
return s.String()
|
||||
}
|
||||
@@ -1,507 +0,0 @@
|
||||
package k8s
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ava-labs/avalanche-network-runner/api"
|
||||
apimocks "github.com/ava-labs/avalanche-network-runner/api/mocks"
|
||||
"github.com/ava-labs/avalanche-network-runner/k8s/mocks"
|
||||
"github.com/ava-labs/avalanche-network-runner/local"
|
||||
"github.com/ava-labs/avalanche-network-runner/network"
|
||||
"github.com/ava-labs/avalanche-network-runner/network/node"
|
||||
"github.com/ava-labs/avalanche-network-runner/utils"
|
||||
"github.com/ava-labs/avalanchego/api/health"
|
||||
healthmocks "github.com/ava-labs/avalanchego/api/health/mocks"
|
||||
infomocks "github.com/ava-labs/avalanchego/api/info/mocks"
|
||||
"github.com/ava-labs/avalanchego/ids"
|
||||
"github.com/ava-labs/avalanchego/staking"
|
||||
"github.com/ava-labs/avalanchego/utils/constants"
|
||||
"github.com/ava-labs/avalanchego/utils/logging"
|
||||
|
||||
k8sapi "github.com/ava-labs/avalanchego-operator/api/v1alpha1"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
k8scli "sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTestNetworkID = uint32(1337)
|
||||
defaultTestNetworkSize = 5
|
||||
)
|
||||
|
||||
var (
|
||||
_ api.NewAPIClientF = newMockAPISuccessful
|
||||
_ api.NewAPIClientF = newMockAPIUnhealthy
|
||||
defaultTestGenesis []byte = []byte(
|
||||
`{
|
||||
"networkID": 1337,
|
||||
"allocations": [
|
||||
{
|
||||
"ethAddr": "0xb3d82b1367d362de99ab59a658165aff520cbd4d",
|
||||
"avaxAddr": "X-local1g65uqn6t77p656w64023nh8nd9updzmxyymev2",
|
||||
"initialAmount": 0,
|
||||
"unlockSchedule": [
|
||||
{
|
||||
"amount": 10000000000000000,
|
||||
"locktime": 1633824000
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ethAddr": "0xb3d82b1367d362de99ab59a658165aff520cbd4d",
|
||||
"avaxAddr": "X-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p",
|
||||
"initialAmount": 300000000000000000,
|
||||
"unlockSchedule": [
|
||||
{
|
||||
"amount": 20000000000000000
|
||||
},
|
||||
{
|
||||
"amount": 10000000000000000,
|
||||
"locktime": 1633824000
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ethAddr": "0xb3d82b1367d362de99ab59a658165aff520cbd4d",
|
||||
"avaxAddr": "X-custom1ur873jhz9qnaqv5qthk5sn3e8nj3e0kmzpjrhp",
|
||||
"initialAmount": 10000000000000000,
|
||||
"unlockSchedule": [
|
||||
{
|
||||
"amount": 10000000000000000,
|
||||
"locktime": 1633824000
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"startTime": 1630987200,
|
||||
"initialStakeDuration": 31536000,
|
||||
"initialStakeDurationOffset": 5400,
|
||||
"initialStakedFunds": [
|
||||
"X-custom1g65uqn6t77p656w64023nh8nd9updzmxwd59gh"
|
||||
],
|
||||
"initialStakers": [
|
||||
{
|
||||
"nodeID": "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg",
|
||||
"rewardAddress": "X-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p",
|
||||
"delegationFee": 1000000
|
||||
},
|
||||
{
|
||||
"nodeID": "NodeID-MFrZFVCXPv5iCn6M9K6XduxGTYp891xXZ",
|
||||
"rewardAddress": "X-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p",
|
||||
"delegationFee": 500000
|
||||
},
|
||||
{
|
||||
"nodeID": "NodeID-NFBbbJ4qCmNaCzeW7sxErhvWqvEQMnYcN",
|
||||
"rewardAddress": "X-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p",
|
||||
"delegationFee": 250000
|
||||
},
|
||||
{
|
||||
"nodeID": "NodeID-GWPcbFJZFfZreETSoWjPimr846mXEKCtu",
|
||||
"rewardAddress": "X-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p",
|
||||
"delegationFee": 125000
|
||||
},
|
||||
{
|
||||
"nodeID": "NodeID-P7oB2McjBGgW2NXXWVYjV8JEDFoW9xDE5",
|
||||
"rewardAddress": "X-custom18jma8ppw3nhx5r4ap8clazz0dps7rv5u9xde7p",
|
||||
"delegationFee": 62500
|
||||
}
|
||||
],
|
||||
"cChainGenesis": "{\"config\":{\"chainId\":43112,\"homesteadBlock\":0,\"daoForkBlock\":0,\"daoForkSupport\":true,\"eip150Block\":0,\"eip150Hash\":\"0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0,\"apricotPhase1BlockTimestamp\":0,\"apricotPhase2BlockTimestamp\":0},\"nonce\":\"0x0\",\"timestamp\":\"0x0\",\"extraData\":\"0x00\",\"gasLimit\":\"0x5f5e100\",\"difficulty\":\"0x0\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"coinbase\":\"0x0000000000000000000000000000000000000000\",\"alloc\":{\"8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC\":{\"balance\":\"0x295BE96E64066972000000\"}},\"number\":\"0x0\",\"gasUsed\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}",
|
||||
"message": "{{ fun_quote }}"
|
||||
}
|
||||
`,
|
||||
)
|
||||
)
|
||||
|
||||
// newMockK8sClient creates a new mock client
|
||||
func newMockK8sClient() k8scli.Client {
|
||||
client := &mocks.Client{}
|
||||
client.On("Get", mock.Anything, mock.Anything, mock.Anything).Run(
|
||||
func(args mock.Arguments) {
|
||||
arg := args.Get(2).(*k8sapi.Avalanchego)
|
||||
arg.Status.NetworkMembersURI = []string{"localhost"}
|
||||
}).Return(nil)
|
||||
client.On("Delete", mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
||||
client.On("DeleteAllOf", mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
||||
client.On("Create", mock.Anything, mock.Anything).Return(nil)
|
||||
client.On("Status").Return(nil)
|
||||
client.On("Scheme").Return(nil)
|
||||
client.On("RESTMapper").Return(nil)
|
||||
return client
|
||||
}
|
||||
|
||||
// newDNSChecker creates a mock for checking the DNS (really just a http.Get mock)
|
||||
func newDNSChecker() *mocks.DnsReachableChecker {
|
||||
dnsChecker := &mocks.DnsReachableChecker{}
|
||||
dnsChecker.On("Reachable", mock.Anything, mock.AnythingOfType("string")).Return(true)
|
||||
return dnsChecker
|
||||
}
|
||||
|
||||
// Returns an API client where:
|
||||
// * The Health API's Health method always returns healthy
|
||||
// * The CChainEthAPI's Close method may be called
|
||||
// * Only the above 2 methods may be called
|
||||
// TODO have this method return an API Client that has all
|
||||
// APIs and methods implemented
|
||||
func newMockAPISuccessful(ipAddr string, port uint16) api.Client {
|
||||
healthReply := &health.APIHealthReply{Healthy: true}
|
||||
healthClient := &healthmocks.Client{}
|
||||
healthClient.On("Health", mock.Anything).Return(healthReply, nil)
|
||||
|
||||
id := ids.GenerateTestShortID().String()
|
||||
infoReply := fmt.Sprintf("%s%s", constants.NodeIDPrefix, id)
|
||||
infoClient := &infomocks.Client{}
|
||||
infoClient.On("GetNodeID", mock.Anything).Return(infoReply, nil)
|
||||
|
||||
client := &apimocks.Client{}
|
||||
client.On("HealthAPI").Return(healthClient)
|
||||
client.On("InfoAPI").Return(infoClient)
|
||||
return client
|
||||
}
|
||||
|
||||
// Returns an API client where the Health API's Health method always returns unhealthy
|
||||
func newMockAPIUnhealthy(ipAddr string, port uint16) api.Client {
|
||||
healthReply := &health.APIHealthReply{Healthy: false}
|
||||
healthClient := &healthmocks.Client{}
|
||||
healthClient.On("Health", mock.Anything).Return(healthReply, nil)
|
||||
client := &apimocks.Client{}
|
||||
client.On("HealthAPI").Return(healthClient)
|
||||
return client
|
||||
}
|
||||
|
||||
func newDefaultTestNetwork(t *testing.T) (network.Network, error) {
|
||||
conf := defaultTestNetworkConfig(t)
|
||||
return newTestNetworkWithConfig(conf)
|
||||
}
|
||||
|
||||
func newTestNetworkWithConfig(conf network.Config) (network.Network, error) {
|
||||
return newNetwork(networkParams{
|
||||
conf: conf,
|
||||
log: logging.NoLog{},
|
||||
k8sClient: newMockK8sClient(),
|
||||
dnsChecker: newDNSChecker(),
|
||||
apiClientFunc: newMockAPISuccessful,
|
||||
})
|
||||
}
|
||||
|
||||
// cleanup closes the channel to shutdown the HTTP server
|
||||
func cleanup(n network.Network) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), stopTimeout)
|
||||
defer cancel()
|
||||
if err := n.Stop(ctx); err != nil {
|
||||
fmt.Printf("Error stopping network: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestNewNetworkEmpty tests that an empty config results in an error
|
||||
func TestNewNetworkEmpty(t *testing.T) {
|
||||
t.Parallel()
|
||||
conf := network.Config{}
|
||||
_, err := newTestNetworkWithConfig(conf)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
// TestHealthy tests that a default network can be created and becomes healthy
|
||||
func TestHealthy(t *testing.T) {
|
||||
t.Parallel()
|
||||
n, err := newDefaultTestNetwork(t)
|
||||
assert.NoError(t, err)
|
||||
defer cleanup(n)
|
||||
err = awaitNetworkHealthy(n, 30*time.Second)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
// TestNetworkDefault tests the default operations on a network:
|
||||
// * it creates a network and waits until it's healthy
|
||||
// * it adds a new node
|
||||
// * it gets a single node
|
||||
// * it gets all nodes
|
||||
// * it removes a node
|
||||
// * it stops the network
|
||||
func TestNetworkDefault(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := assert.New(t)
|
||||
conf := defaultTestNetworkConfig(t)
|
||||
n, err := newTestNetworkWithConfig(conf)
|
||||
assert.NoError(err)
|
||||
defer cleanup(n)
|
||||
err = awaitNetworkHealthy(n, 30*time.Second)
|
||||
assert.NoError(err)
|
||||
|
||||
net, ok := n.(*networkImpl)
|
||||
assert.True(ok)
|
||||
assert.Len(net.nodes, len(conf.NodeConfigs))
|
||||
for _, node := range net.nodes {
|
||||
assert.NotNil(node.apiClient)
|
||||
assert.NotNil(node.k8sObjSpec)
|
||||
assert.True(len(node.name) > 0)
|
||||
assert.True(len(node.uri) > 0)
|
||||
assert.NotEqualValues(ids.ShortEmpty, node.nodeID)
|
||||
}
|
||||
|
||||
names, err := n.GetNodeNames()
|
||||
assert.NoError(err)
|
||||
netSize := len(names)
|
||||
assert.EqualValues(defaultTestNetworkSize, netSize)
|
||||
for _, name := range names {
|
||||
assert.Greater(len(name), 0)
|
||||
}
|
||||
stakingCert, stakingKey, err := staking.NewCertAndKeyBytes()
|
||||
assert.NoError(err)
|
||||
|
||||
newNodeConfig := node.Config{
|
||||
Name: "new-node",
|
||||
IsBeacon: false,
|
||||
StakingKey: string(stakingKey),
|
||||
StakingCert: string(stakingCert),
|
||||
ImplSpecificConfig: utils.NewK8sNodeConfigJsonRaw(
|
||||
"chain.avax.network/v1alpha1",
|
||||
"new-node",
|
||||
"avaplatform/avalanchego",
|
||||
"Avalanchego",
|
||||
"ci-network-runner",
|
||||
"9.99.9999",
|
||||
),
|
||||
}
|
||||
newNode, err := n.AddNode(newNodeConfig)
|
||||
assert.NoError(err)
|
||||
names, err = n.GetNodeNames()
|
||||
assert.NoError(err)
|
||||
assert.Len(names, netSize+1)
|
||||
|
||||
nn, err := n.GetNode(newNodeConfig.Name)
|
||||
assert.NoError(err)
|
||||
assert.Equal(newNodeConfig.Name, nn.GetName())
|
||||
|
||||
_, err = n.GetNode("this does not exist")
|
||||
assert.Error(err)
|
||||
|
||||
err = n.RemoveNode(newNode.GetName())
|
||||
assert.NoError(err)
|
||||
names, err = n.GetNodeNames()
|
||||
assert.NoError(err)
|
||||
assert.Len(names, netSize)
|
||||
}
|
||||
|
||||
// TestWrongNetworkConfigs checks configs that are expected to be invalid at network creation time
|
||||
// This is adapted from the local test suite
|
||||
func TestWrongNetworkConfigs(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := map[string]struct {
|
||||
config network.Config
|
||||
}{
|
||||
"no ImplSpecificConfig": {
|
||||
config: network.Config{
|
||||
Genesis: "nonempty",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
IsBeacon: true,
|
||||
StakingKey: "nonempty",
|
||||
StakingCert: "nonempty",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"empty name": {
|
||||
config: network.Config{
|
||||
Genesis: "nonempty",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewK8sNodeConfigJsonRaw("0.00.0000", "testnode", "somerepo/someimage", "anykind", "noname", "testingversion"),
|
||||
IsBeacon: true,
|
||||
StakingKey: "nonempty",
|
||||
StakingCert: "nonempty",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"StakingKey but no StakingCert": {
|
||||
config: network.Config{
|
||||
Genesis: "nonempty",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewK8sNodeConfigJsonRaw("0.00.0000", "testnode", "somerepo/someimage", "anykind", "noname", "testingversion"),
|
||||
IsBeacon: true,
|
||||
StakingKey: "nonempty",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"StakingCert but no StakingKey": {
|
||||
config: network.Config{
|
||||
Genesis: "nonempty",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewK8sNodeConfigJsonRaw("0.00.0000", "testnode", "somerepo/someimage", "anykind", "noname", "testingversion"),
|
||||
IsBeacon: true,
|
||||
StakingCert: "nonempty",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"no beacon node": {
|
||||
config: network.Config{
|
||||
Genesis: "nonempty",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewK8sNodeConfigJsonRaw("0.00.0000", "testnode", "somerepo/someimage", "anykind", "noname", "testingversion"),
|
||||
StakingKey: "nonempty",
|
||||
StakingCert: "nonempty",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"repeated name": {
|
||||
config: network.Config{
|
||||
Genesis: "nonempty",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewK8sNodeConfigJsonRaw("0.00.0000", "testnode", "somerepo/someimage", "anykind", "noname", "testingversion"),
|
||||
Name: "node0",
|
||||
IsBeacon: true,
|
||||
StakingKey: "nonempty",
|
||||
StakingCert: "nonempty",
|
||||
},
|
||||
{
|
||||
ImplSpecificConfig: utils.NewK8sNodeConfigJsonRaw("0.00.0000", "testnode", "somerepo/someimage", "anykind", "noname", "testingversion"),
|
||||
Name: "node0",
|
||||
IsBeacon: false,
|
||||
StakingKey: "nonempty",
|
||||
StakingCert: "nonempty",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
assert := assert.New(t)
|
||||
for name, tt := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
_, err := newTestNetworkWithConfig(tt.config)
|
||||
assert.Error(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestFlags tests that we can pass flags through the network.Config
|
||||
// but also via node.Config and that the latter overrides the former
|
||||
// if same keys exist.
|
||||
func TestFlags(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := assert.New(t)
|
||||
networkConfig := defaultTestNetworkConfig(t)
|
||||
|
||||
networkConfig.Flags = map[string]interface{}{
|
||||
"test-network-config-flag": "something",
|
||||
"common-config-flag": "should not be added",
|
||||
}
|
||||
for i := range networkConfig.NodeConfigs {
|
||||
v := &networkConfig.NodeConfigs[i]
|
||||
v.Flags = map[string]interface{}{
|
||||
"test-node-config-flag": "node",
|
||||
"test2-node-config-flag": "config",
|
||||
"common-config-flag": "this should be added",
|
||||
}
|
||||
}
|
||||
nw, err := newTestNetworkWithConfig(networkConfig)
|
||||
assert.NoError(err)
|
||||
// after creating the network, one flag should have been overridden by the node configs
|
||||
for _, n := range networkConfig.NodeConfigs {
|
||||
assert.Len(n.Flags, 4)
|
||||
assert.Contains(n.Flags, "test-network-config-flag")
|
||||
assert.Equal(n.Flags["test-network-config-flag"], "something")
|
||||
assert.Contains(n.Flags, "common-config-flag")
|
||||
assert.Equal(n.Flags["common-config-flag"], "this should be added")
|
||||
assert.Contains(n.Flags, "test-node-config-flag")
|
||||
assert.Equal(n.Flags["test-node-config-flag"], "node")
|
||||
assert.Contains(n.Flags, "test2-node-config-flag")
|
||||
assert.Equal(n.Flags["test2-node-config-flag"], "config")
|
||||
}
|
||||
err = nw.Stop(context.Background())
|
||||
assert.NoError(err)
|
||||
|
||||
// submit only node.Config flags
|
||||
networkConfig.Flags = nil
|
||||
for i := range networkConfig.NodeConfigs {
|
||||
v := &networkConfig.NodeConfigs[i]
|
||||
v.Flags = map[string]interface{}{
|
||||
"test-node-config-flag": "node",
|
||||
"test2-node-config-flag": "config",
|
||||
"common-config-flag": "this should be added",
|
||||
}
|
||||
}
|
||||
nw, err = newTestNetworkWithConfig(networkConfig)
|
||||
assert.NoError(err)
|
||||
// after creating the network, only node configs should exist
|
||||
for _, n := range networkConfig.NodeConfigs {
|
||||
assert.Len(n.Flags, 3)
|
||||
assert.NotContains(n.Flags, "test-network-config-flag")
|
||||
assert.Contains(n.Flags, "common-config-flag")
|
||||
assert.Equal(n.Flags["common-config-flag"], "this should be added")
|
||||
assert.Contains(n.Flags, "test-node-config-flag")
|
||||
assert.Equal(n.Flags["test-node-config-flag"], "node")
|
||||
assert.Contains(n.Flags, "test2-node-config-flag")
|
||||
assert.Equal(n.Flags["test2-node-config-flag"], "config")
|
||||
}
|
||||
err = nw.Stop(context.Background())
|
||||
assert.NoError(err)
|
||||
|
||||
// submit only network.Config flags
|
||||
networkConfig.Flags = map[string]interface{}{
|
||||
"test-network-config-flag": "something",
|
||||
"common-config-flag": "else",
|
||||
}
|
||||
for i := range networkConfig.NodeConfigs {
|
||||
v := &networkConfig.NodeConfigs[i]
|
||||
v.Flags = nil
|
||||
}
|
||||
nw, err = newTestNetworkWithConfig(networkConfig)
|
||||
assert.NoError(err)
|
||||
// after creating the network, only flags from the network config should exist
|
||||
for _, n := range networkConfig.NodeConfigs {
|
||||
assert.True(len(n.Flags) == 2)
|
||||
assert.Contains(n.Flags, "test-network-config-flag")
|
||||
assert.Equal(n.Flags["test-network-config-flag"], "something")
|
||||
assert.Contains(n.Flags, "common-config-flag")
|
||||
assert.Equal(n.Flags["common-config-flag"], "else")
|
||||
}
|
||||
err = nw.Stop(context.Background())
|
||||
assert.NoError(err)
|
||||
}
|
||||
|
||||
// TestImplSpecificConfigInterface checks incorrect type to interface{} ImplSpecificConfig
|
||||
// This is adapted from the local test suite
|
||||
func TestImplSpecificConfigInterface(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := assert.New(t)
|
||||
networkConfig := defaultTestNetworkConfig(t)
|
||||
networkConfig.NodeConfigs[0].ImplSpecificConfig = json.RawMessage("should be a JSON")
|
||||
_, err := newTestNetworkWithConfig(networkConfig)
|
||||
assert.Error(err)
|
||||
}
|
||||
|
||||
// defaultTestNetworkConfig creates a default size network for testing
|
||||
func defaultTestNetworkConfig(t *testing.T) network.Config {
|
||||
assert := assert.New(t)
|
||||
networkConfig, err := local.NewDefaultConfigNNodes("pepito", defaultTestNetworkSize)
|
||||
assert.NoError(err)
|
||||
for i := 0; i < defaultTestNetworkSize; i++ {
|
||||
networkConfig.NodeConfigs[i].Name = fmt.Sprintf("node%d", i)
|
||||
networkConfig.NodeConfigs[i].ImplSpecificConfig = utils.NewK8sNodeConfigJsonRaw("0.00.0000", fmt.Sprintf("testnode-%d", i), "somerepo/someimage", "Avalanchego", "ci-networkrunner", "testingversion")
|
||||
}
|
||||
return networkConfig
|
||||
}
|
||||
|
||||
// Returns nil when all the nodes in [net] are healthy,
|
||||
// or an error if one doesn't become healthy within
|
||||
// the timeout.
|
||||
func awaitNetworkHealthy(net network.Network, timeout time.Duration) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
healthyCh := net.Healthy(ctx)
|
||||
return <-healthyCh
|
||||
}
|
||||
-83
@@ -1,83 +0,0 @@
|
||||
package k8s
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/ava-labs/avalanche-network-runner/api"
|
||||
"github.com/ava-labs/avalanche-network-runner/network/node"
|
||||
k8sapi "github.com/ava-labs/avalanchego-operator/api/v1alpha1"
|
||||
"github.com/ava-labs/avalanchego/ids"
|
||||
"github.com/ava-labs/avalanchego/network/peer"
|
||||
"github.com/ava-labs/avalanchego/snow/networking/router"
|
||||
)
|
||||
|
||||
var _ node.Node = &Node{}
|
||||
|
||||
// ObjectSpec is the K8s-specifc object config. This is the "implementation-specic config"
|
||||
// for the K8s-based network runner. See struct Config in network/node/node.go.
|
||||
type ObjectSpec struct {
|
||||
Namespace string `json:"namespace"` // The kubernetes Namespace
|
||||
Identifier string `json:"identifier"` // Identifies this network in the cluster
|
||||
Kind string `json:"kind"` // Identifies the object Kind for the operator
|
||||
APIVersion string `json:"apiVersion"` // The APIVersion of the kubernetes object
|
||||
Image string `json:"image"` // The docker image to use
|
||||
Tag string `json:"tag"` // The docker tag to use
|
||||
}
|
||||
|
||||
// Node is a Avalanchego representation on k8s
|
||||
type Node struct {
|
||||
// This node's AvalancheGo node ID
|
||||
nodeID ids.ShortID
|
||||
// Unique name of this node
|
||||
name string
|
||||
// URI of this node from Kubernetes
|
||||
uri string
|
||||
// Use to send API calls to this node
|
||||
apiClient api.Client
|
||||
// K8s description of this node
|
||||
k8sObjSpec *k8sapi.Avalanchego
|
||||
}
|
||||
|
||||
// AttachPeer see Network
|
||||
// TODO: Not yet implemented
|
||||
func (n *Node) AttachPeer(ctx context.Context, handler router.InboundHandler) (peer.Peer, error) {
|
||||
return nil, errors.New("AttachPeer is not implemented")
|
||||
}
|
||||
|
||||
// See node.Node
|
||||
func (n *Node) GetAPIClient() api.Client {
|
||||
return n.apiClient
|
||||
}
|
||||
|
||||
// See node.Node
|
||||
func (n *Node) GetName() string {
|
||||
return n.name
|
||||
}
|
||||
|
||||
// See node.Node
|
||||
func (n *Node) GetNodeID() ids.ShortID {
|
||||
return n.nodeID
|
||||
}
|
||||
|
||||
// See node.Node
|
||||
func (n *Node) GetURL() string {
|
||||
return n.uri
|
||||
}
|
||||
|
||||
// See node.Node
|
||||
func (n *Node) GetP2PPort() uint16 {
|
||||
// TODO don't hard-code this
|
||||
return defaultP2PPort
|
||||
}
|
||||
|
||||
func (n *Node) GetAPIPort() uint16 {
|
||||
// TODO don't hard-code this
|
||||
return defaultAPIPort
|
||||
}
|
||||
|
||||
// GetK8sObjSpec returns the kubernetes object spec
|
||||
// representation of this node
|
||||
func (n *Node) GetK8sObjSpec() *k8sapi.Avalanchego {
|
||||
return n.k8sObjSpec
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package k8s
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
consecutiveReachableSuccess = 5
|
||||
reachableCheckFreq = time.Second
|
||||
)
|
||||
|
||||
var _ dnsReachableChecker = &defaultDNSReachableChecker{}
|
||||
|
||||
// dnsReachableChecker checks if a URL is reachable.
|
||||
// We use this to check whether a K8s pod is reachable.
|
||||
// We need this as long as we use plain HTTP Get calls
|
||||
// to check for DNS working (there is a TODO to change this).
|
||||
type dnsReachableChecker interface {
|
||||
// Returns true if we can successfully
|
||||
// make an HTTP call to [url]
|
||||
Reachable(ctx context.Context, url string) bool
|
||||
}
|
||||
|
||||
// defaultDNSReachableChecker is the default implementation of the DNS check.
|
||||
// It just uses http.Get.
|
||||
type defaultDNSReachableChecker struct{}
|
||||
|
||||
// It seems that sometimes, we are able to send a GET request to [url]
|
||||
// but then an immediately subsequent HTTP request to [url] fails.
|
||||
// This method only returns true if [consecutiveReachableSuccess]
|
||||
// consecutive GET requests to [url], with [reachableCheckFreq]
|
||||
// between each check, succeed, in order to ensure that [url] is stably reachable.
|
||||
func (d *defaultDNSReachableChecker) Reachable(ctx context.Context, url string) bool {
|
||||
for i := 0; i < consecutiveReachableSuccess; i++ {
|
||||
if resp, err := http.Get(url); err != nil {
|
||||
return false
|
||||
} else {
|
||||
_ = resp.Body.Close()
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return false
|
||||
case <-time.After(reachableCheckFreq): // Wait
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
-206
@@ -1,206 +0,0 @@
|
||||
package k8s
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/ava-labs/avalanche-network-runner/network/node"
|
||||
"github.com/ava-labs/avalanche-network-runner/utils"
|
||||
k8sapi "github.com/ava-labs/avalanchego-operator/api/v1alpha1"
|
||||
"github.com/ava-labs/avalanchego/config"
|
||||
"github.com/ava-labs/avalanchego/utils/logging"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// Convert a config flag to the format AvalancheGo expects
|
||||
// environment variable config flags in.
|
||||
// e.g. bootstrap-ips --> AVAGO_BOOTSTRAP_IPS
|
||||
// e.g. log-level --> AVAGO_LOG_LEVEL
|
||||
func convertKey(key string) string {
|
||||
key = strings.Replace(key, "-", "_", -1)
|
||||
key = strings.ToUpper(key)
|
||||
newKey := fmt.Sprintf("%s%s", envVarPrefix, key)
|
||||
return newKey
|
||||
}
|
||||
|
||||
// Given a node's config and genesis, returns the environment
|
||||
// variables (i.e. config flags) to give to the node
|
||||
func buildNodeEnv(log logging.Logger, genesis []byte, c node.Config) ([]corev1.EnvVar, error) {
|
||||
conf := map[string]interface{}{}
|
||||
|
||||
// Parse config from file if one given
|
||||
if c.ConfigFile != "" {
|
||||
if err := json.Unmarshal([]byte(c.ConfigFile), &conf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// If a key is in the config file and flags, the flag takes precedence.
|
||||
for key, val := range c.Flags {
|
||||
if _, ok := conf[key]; ok {
|
||||
log.Info("overwriting key %s in config file with value given in flag", key)
|
||||
}
|
||||
conf[key] = val
|
||||
}
|
||||
|
||||
// Parse network ID from genesis
|
||||
networkID, err := utils.NetworkIDFromGenesis(genesis)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Make sure network ID in config file / flag, if given,
|
||||
// matches genesis network ID
|
||||
if gotNetworkID, ok := conf[config.NetworkNameKey]; ok {
|
||||
if gotNetworkID, ok := gotNetworkID.(float64); ok && uint32(gotNetworkID) != networkID {
|
||||
return nil, fmt.Errorf(
|
||||
"network ID in config file / flag (%d) != network ID in genesis (%d)",
|
||||
uint32(gotNetworkID), networkID,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// AvalancheGo expects environment variable config keys in.
|
||||
// e.g. bootstrap-ips --> AVAGO_BOOTSTRAP_IPS
|
||||
// e.g. log-level --> AVAGO_LOG_LEVEL
|
||||
env := []corev1.EnvVar{
|
||||
{
|
||||
// Provide environment variable giving the network ID
|
||||
Name: convertKey(config.NetworkNameKey),
|
||||
Value: fmt.Sprint(networkID),
|
||||
},
|
||||
}
|
||||
for key, val := range conf {
|
||||
// For each config key, convert it to the right format
|
||||
env = append(env, corev1.EnvVar{
|
||||
Name: convertKey(key),
|
||||
Value: fmt.Sprintf("%v", val),
|
||||
})
|
||||
}
|
||||
return env, nil
|
||||
}
|
||||
|
||||
// Takes a node's config and genesis and returns the node as a k8s object spec
|
||||
func buildK8sObjSpec(log logging.Logger, genesis []byte, c node.Config) (*k8sapi.Avalanchego, error) {
|
||||
env, err := buildNodeEnv(log, genesis, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
certs := []k8sapi.Certificate{
|
||||
{
|
||||
Cert: base64.StdEncoding.EncodeToString([]byte(c.StakingCert)),
|
||||
Key: base64.StdEncoding.EncodeToString([]byte(c.StakingKey)),
|
||||
},
|
||||
}
|
||||
var k8sConf ObjectSpec
|
||||
if err := json.Unmarshal(c.ImplSpecificConfig, &k8sConf); err != nil {
|
||||
return nil, fmt.Errorf("Unmarshalling an expected k8s.ObjectSpec failed: %w", err)
|
||||
}
|
||||
|
||||
if err := validateObjectSpec(k8sConf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &k8sapi.Avalanchego{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: k8sConf.Kind,
|
||||
APIVersion: k8sConf.APIVersion,
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: k8sConf.Identifier,
|
||||
Namespace: k8sConf.Namespace,
|
||||
},
|
||||
Spec: k8sapi.AvalanchegoSpec{
|
||||
BootstrapperURL: "",
|
||||
DeploymentName: k8sConf.Identifier,
|
||||
Image: k8sConf.Image,
|
||||
Tag: k8sConf.Tag,
|
||||
Env: env,
|
||||
NodeCount: 1,
|
||||
Certificates: certs,
|
||||
Genesis: string(genesis),
|
||||
Resources: corev1.ResourceRequirements{
|
||||
Limits: corev1.ResourceList{
|
||||
corev1.ResourceCPU: resource.MustParse(resourceLimitsCPU), // TODO: Should these be supplied by Opts rather than const?
|
||||
corev1.ResourceMemory: resource.MustParse(resourceLimitsMemory),
|
||||
},
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceCPU: resource.MustParse(resourceRequestCPU),
|
||||
corev1.ResourceMemory: resource.MustParse(resourceRequestMemory),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Validates an ObjectSpec.
|
||||
// The tag value can be empty so not checked.
|
||||
func validateObjectSpec(k8sobj ObjectSpec) error {
|
||||
switch {
|
||||
case k8sobj.Identifier == "":
|
||||
return errors.New("name should not be empty")
|
||||
case k8sobj.APIVersion == "":
|
||||
return errors.New("APIVersion should not be empty")
|
||||
case k8sobj.Kind != "Avalanchego":
|
||||
// only "AvalancheGo" currently supported -- mandated by avalanchego-operator
|
||||
return fmt.Errorf("expected \"Avalanchego\" but got %q", k8sobj.Kind)
|
||||
case k8sobj.Namespace == "":
|
||||
return errors.New("namespace should be defined to avoid unintended consequences")
|
||||
case k8sobj.Image == "" || strings.Index(k8sobj.Image, "/") == 1:
|
||||
return fmt.Errorf("image string %q is invalid, it can't be empty and must contain a %q to describe a valid image repo", k8sobj.Image, "/")
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Takes the genesis of a network and node configs and returns:
|
||||
// 1) The beacon nodes
|
||||
// 2) The non-beacon nodes
|
||||
// as avalanchego-operator compatible descriptions.
|
||||
// May return nil slices.
|
||||
func createDeploymentFromConfig(params networkParams) ([]*k8sapi.Avalanchego, []*k8sapi.Avalanchego, error) {
|
||||
// Give each flag in the network config to each node's config.
|
||||
// If a flag is defined in both the network config and the node config,
|
||||
// the value given in the node config takes precedence.
|
||||
for flagName, flagVal := range params.conf.Flags {
|
||||
for i := range params.conf.NodeConfigs {
|
||||
nodeConfig := ¶ms.conf.NodeConfigs[i]
|
||||
if len(nodeConfig.Flags) == 0 {
|
||||
nodeConfig.Flags = make(map[string]interface{})
|
||||
}
|
||||
// Do not overwrite flags described in the nodeConfig
|
||||
if val, ok := nodeConfig.Flags[flagName]; !ok {
|
||||
nodeConfig.Flags[flagName] = flagVal
|
||||
} else {
|
||||
params.log.Info(
|
||||
"not overwriting node config flag %s (value %v) with network config flag (value %v)",
|
||||
flagName, val, flagVal,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var beacons, nonBeacons []*k8sapi.Avalanchego
|
||||
names := make(map[string]struct{})
|
||||
for _, nodeConfig := range params.conf.NodeConfigs {
|
||||
spec, err := buildK8sObjSpec(params.log, []byte(params.conf.Genesis), nodeConfig)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if _, exists := names[spec.Name]; exists {
|
||||
return nil, nil, fmt.Errorf("node with name name %q already exists", spec.Name)
|
||||
}
|
||||
names[spec.Name] = struct{}{}
|
||||
if nodeConfig.IsBeacon {
|
||||
beacons = append(beacons, spec)
|
||||
} else {
|
||||
nonBeacons = append(nonBeacons, spec)
|
||||
}
|
||||
}
|
||||
return beacons, nonBeacons, nil
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
package k8s
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/ava-labs/avalanche-network-runner/network"
|
||||
"github.com/ava-labs/avalanche-network-runner/network/node"
|
||||
"github.com/ava-labs/avalanche-network-runner/utils"
|
||||
"github.com/ava-labs/avalanchego/utils/logging"
|
||||
"github.com/stretchr/testify/assert"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// TestBuildNodeEnv tests the internal buildNodeEnv method which creates the env vars for the avalanche nodes
|
||||
func TestBuildNodeEnv(t *testing.T) {
|
||||
t.Parallel()
|
||||
genesis := defaultTestGenesis
|
||||
testConfig := `
|
||||
{
|
||||
"network-peer-list-gossip-frequency": "250ms",
|
||||
"network-max-reconnect-delay": "1s",
|
||||
"health-check-frequency": "2s"
|
||||
}`
|
||||
c := node.Config{
|
||||
ConfigFile: testConfig,
|
||||
}
|
||||
|
||||
envVars, err := buildNodeEnv(logging.NoLog{}, genesis, c)
|
||||
assert.NoError(t, err)
|
||||
controlVars := []v1.EnvVar{
|
||||
{
|
||||
Name: "AVAGO_NETWORK_PEER_LIST_GOSSIP_FREQUENCY",
|
||||
Value: "250ms",
|
||||
},
|
||||
{
|
||||
Name: "AVAGO_NETWORK_MAX_RECONNECT_DELAY",
|
||||
Value: "1s",
|
||||
},
|
||||
{
|
||||
Name: "AVAGO_HEALTH_CHECK_FREQUENCY",
|
||||
Value: "2s",
|
||||
},
|
||||
{
|
||||
Name: "AVAGO_NETWORK_ID",
|
||||
Value: fmt.Sprint(defaultTestNetworkID),
|
||||
},
|
||||
}
|
||||
|
||||
assert.ElementsMatch(t, envVars, controlVars)
|
||||
}
|
||||
|
||||
// TestConvertKey tests the internal convertKey method which is used
|
||||
// to convert from the avalanchego config file format to env vars
|
||||
func TestConvertKey(t *testing.T) {
|
||||
t.Parallel()
|
||||
testKey := "network-peer-list-gossip-frequency"
|
||||
controlKey := "AVAGO_NETWORK_PEER_LIST_GOSSIP_FREQUENCY"
|
||||
convertedKey := convertKey(testKey)
|
||||
assert.Equal(t, convertedKey, controlKey)
|
||||
}
|
||||
|
||||
// TestCreateDeploymentConfig tests the internal createDeploymentFromConfig method which creates the k8s objects
|
||||
func TestCreateDeploymentConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := assert.New(t)
|
||||
genesis := defaultTestGenesis
|
||||
|
||||
nodeConfigs := []node.Config{
|
||||
{
|
||||
Name: "test1",
|
||||
IsBeacon: true,
|
||||
StakingKey: "fooKey",
|
||||
StakingCert: "fooCert",
|
||||
ConfigFile: "{}",
|
||||
ImplSpecificConfig: utils.NewK8sNodeConfigJsonRaw(
|
||||
"v1",
|
||||
"test11",
|
||||
"img1",
|
||||
"Avalanchego",
|
||||
"test01",
|
||||
"t1",
|
||||
),
|
||||
},
|
||||
{
|
||||
Name: "test2",
|
||||
IsBeacon: false,
|
||||
StakingKey: "barKey",
|
||||
StakingCert: "barCert",
|
||||
ConfigFile: "{}",
|
||||
ImplSpecificConfig: utils.NewK8sNodeConfigJsonRaw(
|
||||
"v2",
|
||||
"test22",
|
||||
"img2",
|
||||
"Avalanchego",
|
||||
"test02",
|
||||
"t2",
|
||||
),
|
||||
},
|
||||
}
|
||||
params := networkParams{
|
||||
conf: network.Config{
|
||||
Genesis: string(genesis),
|
||||
NodeConfigs: nodeConfigs,
|
||||
},
|
||||
}
|
||||
|
||||
beacons, nonBeacons, err := createDeploymentFromConfig(params)
|
||||
assert.NoError(err)
|
||||
assert.Len(beacons, 1)
|
||||
assert.Len(nonBeacons, 1)
|
||||
|
||||
b := beacons[0]
|
||||
n := nonBeacons[0]
|
||||
|
||||
assert.Equal(b.Name, "test11")
|
||||
assert.Equal(n.Name, "test22")
|
||||
assert.Equal(b.Kind, "Avalanchego")
|
||||
assert.Equal(n.Kind, "Avalanchego")
|
||||
assert.Equal(b.APIVersion, "v1")
|
||||
assert.Equal(n.APIVersion, "v2")
|
||||
assert.Equal(b.Namespace, "test01")
|
||||
assert.Equal(n.Namespace, "test02")
|
||||
assert.Equal(b.Spec.DeploymentName, "test11")
|
||||
assert.Equal(n.Spec.DeploymentName, "test22")
|
||||
assert.Equal(b.Spec.Image, "img1")
|
||||
assert.Equal(n.Spec.Image, "img2")
|
||||
assert.Equal(b.Spec.Tag, "t1")
|
||||
assert.Equal(n.Spec.Tag, "t2")
|
||||
assert.Equal(b.Spec.BootstrapperURL, "")
|
||||
assert.Equal(n.Spec.BootstrapperURL, "")
|
||||
assert.Equal(b.Spec.Env[0].Name, "AVAGO_NETWORK_ID")
|
||||
assert.Equal(n.Spec.Env[0].Name, "AVAGO_NETWORK_ID")
|
||||
assert.Equal(b.Spec.Env[0].Value, fmt.Sprint(defaultTestNetworkID))
|
||||
assert.Equal(n.Spec.Env[0].Value, fmt.Sprint(defaultTestNetworkID))
|
||||
assert.Equal(b.Spec.NodeCount, 1)
|
||||
assert.Equal(n.Spec.NodeCount, 1)
|
||||
assert.Equal(b.Spec.Certificates[0].Cert, base64.StdEncoding.EncodeToString([]byte("fooCert")))
|
||||
assert.Equal(b.Spec.Certificates[0].Key, base64.StdEncoding.EncodeToString([]byte("fooKey")))
|
||||
assert.Equal(n.Spec.Certificates[0].Cert, base64.StdEncoding.EncodeToString([]byte("barCert")))
|
||||
assert.Equal(n.Spec.Certificates[0].Key, base64.StdEncoding.EncodeToString([]byte("barKey")))
|
||||
assert.Equal(n.Spec.NodeCount, 1)
|
||||
assert.Equal(b.Spec.Genesis, string(genesis))
|
||||
assert.Equal(n.Spec.Genesis, string(genesis))
|
||||
}
|
||||
+7
-16
@@ -158,16 +158,12 @@ type nodeProcessCreator struct {
|
||||
// If the config has redirection set to `true` for either StdErr or StdOut,
|
||||
// the output will be redirected and colored
|
||||
func (npc *nodeProcessCreator) NewNodeProcess(config node.Config, args ...string) (NodeProcess, error) {
|
||||
var localNodeConfig NodeConfig
|
||||
if err := json.Unmarshal(config.ImplSpecificConfig, &localNodeConfig); err != nil {
|
||||
return nil, fmt.Errorf("couldn't unmarshal local.NodeConfig: %w", err)
|
||||
}
|
||||
// Start the AvalancheGo node and pass it the flags defined above
|
||||
cmd := exec.Command(localNodeConfig.BinaryPath, args...)
|
||||
// assign a new color to this process (might not be used if the localNodeConfig isn't set for it)
|
||||
cmd := exec.Command(config.BinaryPath, args...)
|
||||
// assign a new color to this process (might not be used if the config isn't set for it)
|
||||
color := npc.colorPicker.NextColor()
|
||||
// Optionally redirect stdout and stderr
|
||||
if localNodeConfig.RedirectStdout {
|
||||
if config.RedirectStdout {
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Could not create stdout pipe: %s", err)
|
||||
@@ -175,7 +171,7 @@ func (npc *nodeProcessCreator) NewNodeProcess(config node.Config, args ...string
|
||||
// redirect stdout and assign a color to the text
|
||||
utils.ColorAndPrepend(stdout, npc.stdout, config.Name, color)
|
||||
}
|
||||
if localNodeConfig.RedirectStderr {
|
||||
if config.RedirectStderr {
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Could not create stderr pipe: %s", err)
|
||||
@@ -322,7 +318,7 @@ func NewDefaultConfig(binaryPath string) network.Config {
|
||||
config.NodeConfigs = make([]node.Config, len(defaultNetworkConfig.NodeConfigs))
|
||||
copy(config.NodeConfigs, defaultNetworkConfig.NodeConfigs)
|
||||
for i := 0; i < len(config.NodeConfigs); i++ {
|
||||
config.NodeConfigs[i].ImplSpecificConfig = utils.NewLocalNodeConfigJsonRaw(binaryPath)
|
||||
config.NodeConfigs[i].BinaryPath = binaryPath
|
||||
}
|
||||
return config
|
||||
}
|
||||
@@ -404,19 +400,14 @@ func (ln *localNetwork) addNode(nodeConfig node.Config) (node.Node, error) {
|
||||
return nil, fmt.Errorf("couldn't get node ID: %w", err)
|
||||
}
|
||||
|
||||
var localNodeConfig NodeConfig
|
||||
if err := json.Unmarshal(nodeConfig.ImplSpecificConfig, &localNodeConfig); err != nil {
|
||||
return nil, fmt.Errorf("Unmarshalling an expected local.NodeConfig object failed: %w", err)
|
||||
}
|
||||
|
||||
// Start the AvalancheGo node and pass it the flags defined above
|
||||
nodeProcess, err := ln.nodeProcessCreator.NewNodeProcess(nodeConfig, flags...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't create new node process: %s", err)
|
||||
}
|
||||
ln.log.Debug("starting node %q with \"%s %s\"", nodeConfig.Name, localNodeConfig.BinaryPath, flags)
|
||||
ln.log.Debug("starting node %q with \"%s %s\"", nodeConfig.Name, nodeConfig.BinaryPath, flags)
|
||||
if err := nodeProcess.Start(); err != nil {
|
||||
return nil, fmt.Errorf("could not execute cmd \"%s %s\": %w", localNodeConfig.BinaryPath, flags, err)
|
||||
return nil, fmt.Errorf("could not execute cmd \"%s %s\": %w", nodeConfig.BinaryPath, flags, err)
|
||||
}
|
||||
|
||||
// Create a wrapper for this node so we can reference it later
|
||||
|
||||
+79
-100
@@ -3,7 +3,6 @@ package local
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -164,7 +163,7 @@ func (lt *localTestOneNodeCreator) NewNodeProcess(config node.Config, flags ...s
|
||||
expectedConfig := lt.networkConfig.NodeConfigs[0]
|
||||
lt.assert.EqualValues(expectedConfig.CChainConfigFile, config.CChainConfigFile)
|
||||
lt.assert.EqualValues(expectedConfig.ConfigFile, config.ConfigFile)
|
||||
lt.assert.EqualValues(expectedConfig.ImplSpecificConfig, config.ImplSpecificConfig)
|
||||
lt.assert.EqualValues(expectedConfig.BinaryPath, config.BinaryPath)
|
||||
lt.assert.EqualValues(expectedConfig.IsBeacon, config.IsBeacon)
|
||||
lt.assert.EqualValues(expectedConfig.Name, config.Name)
|
||||
lt.assert.EqualValues(expectedConfig.StakingCert, config.StakingCert)
|
||||
@@ -227,28 +226,16 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
config network.Config
|
||||
}{
|
||||
"no ImplSpecificConfig": {
|
||||
config: network.Config{
|
||||
Genesis: "{\"networkID\": 0}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"config file unmarshal": {
|
||||
config: network.Config{
|
||||
Genesis: "{\"networkID\": 0}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "nonempty",
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "nonempty",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -258,11 +245,11 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "{\"networkID\": 0}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "{\"network-id\": \"0\"}",
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "{\"network-id\": \"0\"}",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -272,11 +259,11 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "{\"networkID\": 0}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "{\"db-dir\": 0}",
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "{\"db-dir\": 0}",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -286,11 +273,11 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "{\"networkID\": 0}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "{\"log-dir\": 0}",
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "{\"log-dir\": 0}",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -300,11 +287,11 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "{\"networkID\": 0}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "{\"http-port\": \"0\"}",
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "{\"http-port\": \"0\"}",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -314,11 +301,11 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "{\"networkID\": 0}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "{\"staking-port\": \"0\"}",
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "{\"staking-port\": \"0\"}",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -328,11 +315,11 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "{\"networkID\": 0}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "{\"network-id\": 1}",
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
ConfigFile: "{\"network-id\": 1}",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -342,10 +329,10 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "nonempty",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -355,10 +342,10 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "{}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -368,10 +355,10 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "{\"networkID\": \"0\"}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -380,10 +367,10 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
config: network.Config{
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -393,9 +380,9 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "{\"networkID\": 0}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -405,9 +392,9 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "{\"networkID\": 0}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -417,10 +404,10 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "{\"networkID\": 0}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: "nonempty",
|
||||
StakingCert: "nonempty",
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: "nonempty",
|
||||
StakingCert: "nonempty",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -430,9 +417,9 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "{\"networkID\": 0}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
BinaryPath: "pepe",
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -442,18 +429,18 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
Genesis: "{\"networkID\": 0}",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
Name: "node0",
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
Name: "node0",
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[0].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[0].StakingCert,
|
||||
},
|
||||
{
|
||||
Name: "node0",
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("pepe"),
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[1].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[1].StakingCert,
|
||||
Name: "node0",
|
||||
BinaryPath: "pepe",
|
||||
IsBeacon: true,
|
||||
StakingKey: refNetworkConfig.NodeConfigs[1].StakingKey,
|
||||
StakingCert: refNetworkConfig.NodeConfigs[1].StakingCert,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -468,16 +455,6 @@ func TestWrongNetworkConfigs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Give incorrect type to interface{} ImplSpecificConfig
|
||||
func TestInvalidImplSpecificConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := assert.New(t)
|
||||
networkConfig := testNetworkConfig(t)
|
||||
networkConfig.NodeConfigs[0].ImplSpecificConfig = json.RawMessage("just a string")
|
||||
_, err := newNetwork(logging.NoLog{}, networkConfig, newMockAPISuccessful, &localTestSuccessfulNodeProcessCreator{}, "")
|
||||
assert.Error(err)
|
||||
}
|
||||
|
||||
// Assert that the network's Healthy() method returns an
|
||||
// error when all nodes' Health API return unhealthy
|
||||
func TestUnhealthyNetwork(t *testing.T) {
|
||||
@@ -825,8 +802,10 @@ func TestChildCmdRedirection(t *testing.T) {
|
||||
|
||||
// now create the node process and check it will be prepended and colored
|
||||
testConfig := node.Config{
|
||||
ImplSpecificConfig: json.RawMessage(`{"binaryPath":"echo","redirectStdout":true,"redirectStderr":true}`),
|
||||
Name: mockNodeName,
|
||||
BinaryPath: "echo",
|
||||
RedirectStdout: true,
|
||||
RedirectStderr: true,
|
||||
Name: mockNodeName,
|
||||
}
|
||||
proc, err := npc.NewNodeProcess(testConfig, testOutput)
|
||||
if err != nil {
|
||||
|
||||
@@ -34,17 +34,6 @@ var (
|
||||
|
||||
type getConnFunc func(context.Context, node.Node) (net.Conn, error)
|
||||
|
||||
// NodeConfig configurations which are specific to the
|
||||
// local implementation of a network / node.
|
||||
type NodeConfig struct {
|
||||
// What type of node this is
|
||||
BinaryPath string `json:"binaryPath"`
|
||||
// If non-nil, direct this node's Stdout to os.Stdout
|
||||
RedirectStdout bool `json:"redirectStdout"`
|
||||
// If non-nil, direct this node's Stderr to os.Stderr
|
||||
RedirectStderr bool `json:"redirectStderr"`
|
||||
}
|
||||
|
||||
// NodeProcess as an interface so we can mock running
|
||||
// AvalancheGo binaries in tests
|
||||
type NodeProcess interface {
|
||||
|
||||
@@ -35,40 +35,6 @@ type AddrAndBalance struct {
|
||||
Balance uint64
|
||||
}
|
||||
|
||||
// Backend is the type of network runner to use
|
||||
type Backend byte
|
||||
|
||||
const (
|
||||
// Local network runner
|
||||
Local Backend = iota + 1
|
||||
// Kubernetes network runner
|
||||
Kubernetes
|
||||
)
|
||||
|
||||
func (b Backend) MarshalJSON() ([]byte, error) {
|
||||
switch b {
|
||||
case Local:
|
||||
return []byte("\"local\""), nil
|
||||
case Kubernetes:
|
||||
return []byte("\"k8s\""), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("got unexpected backend %v", b)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Backend) UnmarshalJSON(bytes []byte) error {
|
||||
switch string(bytes) {
|
||||
case "\"local\"":
|
||||
*b = Local
|
||||
return nil
|
||||
case "\"k8s\"":
|
||||
*b = Kubernetes
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("got unexpected backend %s", string(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
// Config that defines a network when it is created.
|
||||
type Config struct {
|
||||
// Must not be empty
|
||||
@@ -80,8 +46,6 @@ type Config struct {
|
||||
LogLevel string `json:"logLevel"`
|
||||
// Name for the network
|
||||
Name string `json:"name"`
|
||||
// Backend specifies the backend for the network
|
||||
Backend Backend `json:"backend"`
|
||||
// Flags that will be passed to each node in this network.
|
||||
// It can be empty.
|
||||
// Config flags may also be passed in a node's config struct
|
||||
|
||||
+15
-93
@@ -4,90 +4,46 @@ import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/ava-labs/avalanche-network-runner/k8s"
|
||||
"github.com/ava-labs/avalanche-network-runner/local"
|
||||
"github.com/ava-labs/avalanche-network-runner/network"
|
||||
"github.com/ava-labs/avalanche-network-runner/network/node"
|
||||
"github.com/ava-labs/avalanche-network-runner/utils"
|
||||
"github.com/ava-labs/avalanchego/utils/logging"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBackendMarshalJSON(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
backend := network.Local
|
||||
backendJSON, err := json.Marshal(backend)
|
||||
assert.NoError(err)
|
||||
assert.Equal("\"local\"", string(backendJSON))
|
||||
err = json.Unmarshal(backendJSON, &backend)
|
||||
assert.NoError(err)
|
||||
assert.EqualValues(network.Local, backend)
|
||||
|
||||
backend = network.Kubernetes
|
||||
backendJSON, err = json.Marshal(backend)
|
||||
assert.NoError(err)
|
||||
assert.Equal("\"k8s\"", string(backendJSON))
|
||||
err = json.Unmarshal(backendJSON, &backend)
|
||||
assert.NoError(err)
|
||||
assert.EqualValues(network.Kubernetes, backend)
|
||||
|
||||
backend = network.Backend(200) // non-existent backend
|
||||
_, err = json.Marshal(backend)
|
||||
assert.Error(err)
|
||||
err = json.Unmarshal([]byte("invalid"), &backend)
|
||||
assert.Error(err)
|
||||
}
|
||||
|
||||
func TestConfigMarshalJSON(t *testing.T) {
|
||||
jsonNetcfg := "{\"implSpecificConfig\":\"\",\"genesis\":\"in the beginning there was a token\",\"nodeConfigs\":[{\"implSpecificConfig\":{\"binaryPath\":\"/tmp/some/file/path\"},\"name\":\"node0\",\"isBeacon\":true,\"stakingKey\":\"key123\",\"stakingCert\":\"cert123\",\"configFile\":\"config-file-blablabla1\",\"cchainConfigFile\":\"cchain-config-file-blablabla1\",\"flags\":{\"flag-one\":\"val-one\",\"flag-two\":2}},{\"implSpecificConfig\":{\"apiVersion\":\"0.99.999\",\"identifier\":\"k8s-node-1\",\"image\":\"therepo/theimage\",\"kind\":\"imaginary\",\"namespace\":\"outer-space\",\"tag\":\"omega\"},\"name\":\"node1\",\"isBeacon\":false,\"stakingKey\":\"key456\",\"stakingCert\":\"cert456\",\"configFile\":\"config-file-blablabla2\",\"cchainConfigFile\":\"cchain-config-file-blablabla2\",\"flags\":{\"flag-one\":\"val-one\",\"flag-two\":2}},{\"implSpecificConfig\":{\"binaryPath\":\"/tmp/some/other/path\"},\"name\":\"node2\",\"isBeacon\":false,\"stakingKey\":\"key789\",\"stakingCert\":\"cert789\",\"configFile\":\"config-file-blablabla3\",\"cchainConfigFile\":\"cchain-config-file-blablabla3\",\"flags\":{\"flag-one\":\"val-one\",\"flag-two\":2}}],\"logLevel\":\"DEBUG\",\"name\":\"abcxyz\",\"backend\":\"k8s\",\"flags\":{\"flag-three\":\"val-three\"}}"
|
||||
jsonNetcfg := "{\"genesis\":\"in the beginning there was a token\",\"nodeConfigs\":[{\"binaryPath\":\"/tmp/some/file/path\",\"name\":\"node0\",\"isBeacon\":true,\"stakingKey\":\"key123\",\"stakingCert\":\"cert123\",\"configFile\":\"config-file-blablabla1\",\"cchainConfigFile\":\"cchain-config-file-blablabla1\",\"flags\":{\"flag-one\":\"val-one\",\"flag-two\":2}},{\"binaryPath\":\"/tmp/some/other/path\",\"name\":\"node2\",\"isBeacon\":false,\"stakingKey\":\"key789\",\"stakingCert\":\"cert789\",\"configFile\":\"config-file-blablabla3\",\"cchainConfigFile\":\"cchain-config-file-blablabla3\",\"flags\":{\"flag-one\":\"val-one\",\"flag-two\":2}}],\"logLevel\":\"DEBUG\",\"name\":\"abcxyz\",\"flags\":{\"flag-three\":\"val-three\"}}"
|
||||
|
||||
control := network.Config{
|
||||
Genesis: "in the beginning there was a token",
|
||||
NodeConfigs: []node.Config{
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("/tmp/some/file/path"),
|
||||
Name: "node0",
|
||||
IsBeacon: true,
|
||||
StakingKey: "key123",
|
||||
StakingCert: "cert123",
|
||||
ConfigFile: "config-file-blablabla1",
|
||||
CChainConfigFile: "cchain-config-file-blablabla1",
|
||||
Name: "node0",
|
||||
IsBeacon: true,
|
||||
StakingKey: "key123",
|
||||
StakingCert: "cert123",
|
||||
ConfigFile: "config-file-blablabla1",
|
||||
CChainConfigFile: "cchain-config-file-blablabla1",
|
||||
Flags: map[string]interface{}{
|
||||
"flag-one": "val-one",
|
||||
"flag-two": float64(2),
|
||||
},
|
||||
BinaryPath: "/tmp/some/file/path",
|
||||
},
|
||||
{
|
||||
ImplSpecificConfig: newTestK8sNodeConfigJSONRaw(),
|
||||
Name: "node1",
|
||||
IsBeacon: false,
|
||||
StakingKey: "key456",
|
||||
StakingCert: "cert456",
|
||||
ConfigFile: "config-file-blablabla2",
|
||||
CChainConfigFile: "cchain-config-file-blablabla2",
|
||||
Flags: map[string]interface{}{
|
||||
"flag-one": "val-one",
|
||||
"flag-two": float64(2),
|
||||
},
|
||||
},
|
||||
{
|
||||
ImplSpecificConfig: utils.NewLocalNodeConfigJsonRaw("/tmp/some/other/path"),
|
||||
Name: "node2",
|
||||
IsBeacon: false,
|
||||
StakingKey: "key789",
|
||||
StakingCert: "cert789",
|
||||
ConfigFile: "config-file-blablabla3",
|
||||
CChainConfigFile: "cchain-config-file-blablabla3",
|
||||
Name: "node2",
|
||||
IsBeacon: false,
|
||||
StakingKey: "key789",
|
||||
StakingCert: "cert789",
|
||||
ConfigFile: "config-file-blablabla3",
|
||||
CChainConfigFile: "cchain-config-file-blablabla3",
|
||||
Flags: map[string]interface{}{
|
||||
"flag-one": "val-one",
|
||||
"flag-two": float64(2),
|
||||
},
|
||||
BinaryPath: "/tmp/some/other/path",
|
||||
},
|
||||
},
|
||||
LogLevel: "DEBUG",
|
||||
Name: "abcxyz",
|
||||
Backend: network.Kubernetes,
|
||||
Flags: map[string]interface{}{
|
||||
"flag-three": "val-three",
|
||||
},
|
||||
@@ -100,38 +56,4 @@ func TestConfigMarshalJSON(t *testing.T) {
|
||||
|
||||
assert := assert.New(t)
|
||||
assert.EqualValues(control, netcfg)
|
||||
|
||||
// At this point unmarshalling should succeed because *the json.RawMessages are ignored*.
|
||||
// Let's try creating a local network first: it should fail as the second node is for k8s
|
||||
_, err := local.NewNetwork(logging.NoLog{}, netcfg, "")
|
||||
assert.Error(err)
|
||||
|
||||
var localcfg local.NodeConfig
|
||||
err = json.Unmarshal([]byte(control.NodeConfigs[0].ImplSpecificConfig), &localcfg)
|
||||
assert.NoError(err)
|
||||
assert.NotEmpty(localcfg.BinaryPath)
|
||||
localcfg.BinaryPath = ""
|
||||
err = json.Unmarshal([]byte(control.NodeConfigs[2].ImplSpecificConfig), &localcfg)
|
||||
assert.NoError(err)
|
||||
assert.NotEmpty(localcfg.BinaryPath)
|
||||
localcfg.BinaryPath = ""
|
||||
err = json.Unmarshal([]byte(control.NodeConfigs[1].ImplSpecificConfig), &localcfg)
|
||||
assert.NoError(err)
|
||||
assert.Empty(localcfg.BinaryPath)
|
||||
|
||||
var k8scfg k8s.ObjectSpec
|
||||
assert.Empty(k8scfg.APIVersion)
|
||||
err = json.Unmarshal([]byte(control.NodeConfigs[0].ImplSpecificConfig), &k8scfg)
|
||||
assert.NoError(err)
|
||||
assert.Empty(k8scfg.APIVersion)
|
||||
err = json.Unmarshal([]byte(control.NodeConfigs[2].ImplSpecificConfig), &k8scfg)
|
||||
assert.NoError(err)
|
||||
assert.Empty(k8scfg.APIVersion)
|
||||
err = json.Unmarshal([]byte(control.NodeConfigs[1].ImplSpecificConfig), &k8scfg)
|
||||
assert.NoError(err)
|
||||
assert.NotEmpty(k8scfg.APIVersion)
|
||||
}
|
||||
|
||||
func newTestK8sNodeConfigJSONRaw() json.RawMessage {
|
||||
return utils.NewK8sNodeConfigJsonRaw("0.99.999", "k8s-node-1", "therepo/theimage", "imaginary", "outer-space", "omega")
|
||||
}
|
||||
|
||||
@@ -22,9 +22,7 @@ type Node interface {
|
||||
GetNodeID() ids.ShortID
|
||||
// Return a client that can be used to make API calls.
|
||||
GetAPIClient() api.Client
|
||||
// Return this node's URL.
|
||||
// For a local network, this is the node's IP (e.g. 127.0.0.1).
|
||||
// For a k8s network, this is the DNS name of the pod hosting the node.
|
||||
// Return this node's IP (e.g. 127.0.0.1).
|
||||
GetURL() string
|
||||
// Return this node's P2P (staking) port.
|
||||
GetP2PPort() uint16
|
||||
@@ -40,8 +38,6 @@ type Node interface {
|
||||
|
||||
// Config encapsulates an avalanchego configuration
|
||||
type Config struct {
|
||||
// Configuration specific to a particular implementation of a node.
|
||||
ImplSpecificConfig json.RawMessage `json:"implSpecificConfig"`
|
||||
// A node's name must be unique from all other nodes
|
||||
// in a network. If Name is the empty string, a
|
||||
// unique name is assigned on node creation.
|
||||
@@ -64,13 +60,17 @@ type Config struct {
|
||||
// 2. Flags defined in network.Config override
|
||||
// 3. Flags defined in the json config file
|
||||
Flags map[string]interface{} `json:"flags"`
|
||||
// What type of node this is
|
||||
BinaryPath string `json:"binaryPath"`
|
||||
// If non-nil, direct this node's Stdout to os.Stdout
|
||||
RedirectStdout bool `json:"redirectStdout"`
|
||||
// If non-nil, direct this node's Stderr to os.Stderr
|
||||
RedirectStderr bool `json:"redirectStderr"`
|
||||
}
|
||||
|
||||
// Validate returns an error if this config is invalid
|
||||
func (c *Config) Validate(expectedNetworkID uint32) error {
|
||||
switch {
|
||||
case c.ImplSpecificConfig == nil:
|
||||
return errors.New("implementation-specific node config not given")
|
||||
case c.StakingKey == "":
|
||||
return errors.New("staking key not given")
|
||||
case c.StakingCert == "":
|
||||
|
||||
+3
-3
@@ -5,7 +5,6 @@ package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -107,8 +106,9 @@ func newLocalNetwork(opts localNetworkOptions) (*localNetwork, error) {
|
||||
nodeNames[i] = nodeName
|
||||
cfg.NodeConfigs[i].Name = nodeName
|
||||
cfg.NodeConfigs[i].ConfigFile = createConfigFileString(logLevel, logDir, dbDir, opts.pluginDir, opts.whitelistedSubnets)
|
||||
cfg.NodeConfigs[i].ImplSpecificConfig = json.RawMessage(fmt.Sprintf(`{"binaryPath":"%s","redirectStdout":true,"redirectStderr":true}`, opts.execPath))
|
||||
|
||||
cfg.NodeConfigs[i].BinaryPath = opts.execPath
|
||||
cfg.NodeConfigs[i].RedirectStdout = true
|
||||
cfg.NodeConfigs[i].RedirectStderr = true
|
||||
nodeInfos[nodeName] = &rpcpb.NodeInfo{
|
||||
Name: nodeName,
|
||||
ExecPath: opts.execPath,
|
||||
|
||||
+10
-7
@@ -6,7 +6,6 @@ package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -566,11 +565,13 @@ func (s *server) AddNode(ctx context.Context, req *rpcpb.AddNodeRequest) (*rpcpb
|
||||
}
|
||||
|
||||
nodeConfig := node.Config{
|
||||
Name: req.Name,
|
||||
ConfigFile: configFile,
|
||||
ImplSpecificConfig: json.RawMessage(fmt.Sprintf(`{"binaryPath":"%s","redirectStdout":true,"redirectStderr":true}`, execPath)),
|
||||
StakingKey: string(stakingKey),
|
||||
StakingCert: string(stakingCert),
|
||||
Name: req.Name,
|
||||
ConfigFile: configFile,
|
||||
StakingKey: string(stakingKey),
|
||||
StakingCert: string(stakingCert),
|
||||
BinaryPath: execPath,
|
||||
RedirectStdout: true,
|
||||
RedirectStderr: true,
|
||||
}
|
||||
_, err = s.network.nw.AddNode(nodeConfig)
|
||||
if err != nil {
|
||||
@@ -692,7 +693,9 @@ func (s *server) RestartNode(ctx context.Context, req *rpcpb.RestartNodeRequest)
|
||||
nodeInfo.PluginDir,
|
||||
nodeInfo.WhitelistedSubnets,
|
||||
)
|
||||
nodeConfig.ImplSpecificConfig = json.RawMessage(fmt.Sprintf(`{"binaryPath":"%s","redirectStdout":true,"redirectStderr":true}`, nodeInfo.ExecPath))
|
||||
nodeConfig.BinaryPath = nodeInfo.ExecPath
|
||||
nodeConfig.RedirectStdout = true
|
||||
nodeConfig.RedirectStderr = true
|
||||
|
||||
// now remove the node before restart
|
||||
zap.L().Info("removing the node")
|
||||
|
||||
@@ -40,29 +40,6 @@ func NetworkIDFromGenesis(genesis []byte) (uint32, error) {
|
||||
return uint32(networkID), nil
|
||||
}
|
||||
|
||||
// NewLocalNodeConfigJsonRaw returns a JSON formatted string as json.RawMessage for a
|
||||
// local node config object (ImplSpecificConfig)
|
||||
func NewLocalNodeConfigJsonRaw(binaryPath string) json.RawMessage {
|
||||
return json.RawMessage(fmt.Sprintf(`{"binaryPath":"%s"}`, binaryPath))
|
||||
}
|
||||
|
||||
// NewK8sNodeConfigJsonRaw returns a JSON formatted string as json.RawMessage for a
|
||||
// kubernetes node config object (ImplSpecificConfig)
|
||||
func NewK8sNodeConfigJsonRaw(
|
||||
api,
|
||||
id,
|
||||
image,
|
||||
kind,
|
||||
namespace,
|
||||
tag string,
|
||||
) json.RawMessage {
|
||||
return json.RawMessage(
|
||||
fmt.Sprintf(`{"apiVersion":"%s","identifier":"%s","image":"%s","kind":"%s","namespace":"%s","tag":"%s"}`,
|
||||
api, id, image, kind, namespace, tag,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidExecPath = errors.New("avalanche exec is invalid")
|
||||
ErrNotExists = errors.New("avalanche exec not exists")
|
||||
|
||||
Reference in New Issue
Block a user