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:
felipemadero
2022-04-26 09:26:52 -04:00
committed by GitHub
co-authored by Dan Laine
parent d83115e00d
commit 6e90fb27d1
45 changed files with 166 additions and 3042 deletions
-1
View File
@@ -4,7 +4,6 @@ run:
tests: false
skip-dirs:
- api/mocks
- k8s/mocks
- local/mocks
- rpcpb
go: "1.17"
+41 -27
View File
@@ -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
-36
View File
@@ -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"]
-71
View File
@@ -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`.
-48
View File
@@ -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"
}
]
}
-76
View File
@@ -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 }}"
}
-6
View File
@@ -1,6 +0,0 @@
{
"network-peer-list-gossip-frequency": "250ms",
"network-max-reconnect-delay": "1s",
"health-check-frequency": "2s",
"log-level":"debug"
}
-30
View File
@@ -1,30 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFNzCCAx8CCQC687XFxtDRSjANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJV
UzELMAkGA1UECAwCTlkxDzANBgNVBAcMBkl0aGFjYTEQMA4GA1UECgwHQXZhbGFi
czEOMAwGA1UECwwFR2Vja28xDDAKBgNVBAMMA2F2YTEiMCAGCSqGSIb3DQEJARYT
c3RlcGhlbkBhdmFsYWJzLm9yZzAgFw0xOTA3MDIxNjEyMTVaGA8zMDE5MDcxMDE2
MTIxNVowOjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRAwDgYDVQQKDAdBdmFs
YWJzMQwwCgYDVQQDDANhdmEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
AQDKYSRw/W0YpYH/MTQhiFrR0m89l6yTuzLpDtjudr/5RnhIPvtqk7YIGm/m9l29
xwR4J5r7SZGs+70yBetkbS+h7PwJ2rmWDwbrdyJKvVBhqf8kSn+VU2LePSIcJj19
3LDyWhV1H4lqNkUkcAR76Fh9qjMvA2p0vJ66+eDLXlph/RYapQx9HgOj/0BmAKMr
YCyo5BhRih+Ougg8aK4G9PQTIA5G2wTWW2QkHxM/QppFjZd/XwQeJ2H6ubWMFc5f
ttf6AzpJvFIDBu/JDCKWiCu5m8t4GL8w2OrIx8Js19lF4YYE2eojCreqgPi64S3o
cqwKsDoySTw6/5iKQ5BUYwUXX3z7EXOqD8SMHefUKeczj4WvAaZLzR27qXm55EgR
YQAIX4fhmY7NfSop3Wh0Eo62+JHoM/1g+UgOXlbnWpY95Mgd7/fwDSWLu4IxE0/u
q8VufIbfC4yrY8qlTVfAffI1ldRdvJjPJBPiQ0CNrOl60LVptpkGc9shH7wZ2bP0
bEnYKTgLAfOzD8Ut71O2AOIa80A1GNFl4Yle/MSNJOcQOSpgtWdREzIUoenAjfuz
M4OeTr4cRg4+VYTAo9KHKriN1DuewNzGd8WjKAVHmcIMjqISLTlzMhdsdm+OmfQ6
OvyX7v0GTOBbhP09NGcww5A0gCzXN18FS5oxnxe6OG9D0wIDAQABMA0GCSqGSIb3
DQEBCwUAA4ICAQAqL1TWI1PTMm3JaXkhdTBe8tsk7+FsHAFzTcBVBsB8dkJNGhxb
dlu7XIm+AyGUn0j8siz8qojKbO+rEPV/ImTH5W7Q36rXSdgvNUWpKrKIC5S8PUF5
T4pH+lpYIlQHnTaKMuqH3nO3I40IhEhPaa2wAwy2kDlz46fJcr6aMzj6Zg43J5UK
Zid+BQsiWAUau5V7CpC7GMCx4YdOZWWsT3dAsug9hvwTe81kK1JoTH0juwPTBH0t
xUgUVIWyuweM1UwYF3n8Hmwq6B46YmujhMDKT+3lgqZt7eZ1XvieLdBRlVQWzOa/
6QYTkrqwPZioKIStrxVGYjk40qECNodCSCIwRDgbnQubRWrdslxiIyc5blJNuOV+
jgv5d2EeUpwUjvpZuEV7FqPKGRgiG0jfl6Psms9gYUXd+y3ytG9HeoDNmLTSTBE4
nCQXX935P2/xOuok6CpiGpP89DX7t8yiwk8LFNnY3rvv50nVy8kerVdnfHTmoMZ9
/IBgojSIKov4lmPKdgzFfimzhbssVCa4DO/LIhTF7bQbH1ut/Oq7npdOpMjLYIBE
9lagvRVTVFwT/uwrCcXHCb21b/puwV94SNXVwt7BheFTFBdtxJrR4jjr2T5odLkX
6nQcY8V2OT7KOxn0KVc6pl3saJTLmL+H/3CtAao9NtmuUDapKINRSVNyvg==
-----END CERTIFICATE-----
-51
View File
@@ -1,51 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIJKAIBAAKCAgEAymEkcP1tGKWB/zE0IYha0dJvPZesk7sy6Q7Y7na/+UZ4SD77
apO2CBpv5vZdvccEeCea+0mRrPu9MgXrZG0voez8Cdq5lg8G63ciSr1QYan/JEp/
lVNi3j0iHCY9fdyw8loVdR+JajZFJHAEe+hYfaozLwNqdLyeuvngy15aYf0WGqUM
fR4Do/9AZgCjK2AsqOQYUYofjroIPGiuBvT0EyAORtsE1ltkJB8TP0KaRY2Xf18E
Hidh+rm1jBXOX7bX+gM6SbxSAwbvyQwilogruZvLeBi/MNjqyMfCbNfZReGGBNnq
Iwq3qoD4uuEt6HKsCrA6Mkk8Ov+YikOQVGMFF198+xFzqg/EjB3n1CnnM4+FrwGm
S80du6l5ueRIEWEACF+H4ZmOzX0qKd1odBKOtviR6DP9YPlIDl5W51qWPeTIHe/3
8A0li7uCMRNP7qvFbnyG3wuMq2PKpU1XwH3yNZXUXbyYzyQT4kNAjazpetC1abaZ
BnPbIR+8Gdmz9GxJ2Ck4CwHzsw/FLe9TtgDiGvNANRjRZeGJXvzEjSTnEDkqYLVn
URMyFKHpwI37szODnk6+HEYOPlWEwKPShyq4jdQ7nsDcxnfFoygFR5nCDI6iEi05
czIXbHZvjpn0Ojr8l+79BkzgW4T9PTRnMMOQNIAs1zdfBUuaMZ8XujhvQ9MCAwEA
AQKCAgEAuUM4Mt8r8bYBTPVj/ZZvXUjAYKfqacqijkrzN0kp8C4cijZtvWC+8KgS
7GF36vS3GK9Y5tSwMKS6y4IzvFlfk2H4T6UU41OaSA9lKvonDWCrmjNAnBgbl8pq
4U34WLGgohrpLbDTAJHxtat9z1ghOdiGxnDgEUFiJVP9/u2+25jtlTKmPhstxgEy
mK3YsSp3d5xmzq4cuXF/fJ1vQhsXHDLqHt78jKZZA+AWpIB57VXy67y1bk0rGnTK
xxRnOaOODubJgxqMEQ1WkLs1Jow9Sspd9vDghPzt4SNMzorB8YDESMib17xF6iXq
jFj6x6HB8H7mp4X3RyMYJuo2w6lpzBsEncUYpKhqMabF0I/giI5VdpSDvkCCOFen
nWZLV9Ai/x7tTq/0F+cVM69Mgfe8iYymqlfd6WRZITKfViNHALlG/Pq9yHJsz7Ng
S8BKODt/sj4Q0xLtFDT/DmpP50iq7SiS14obcKcQr8FAjM/sOY/Ulg4M8MA7EugS
pDJwLl6XDoIMMCNwZ1HGsDstzmx5Mf50bS4tbK4iZzcpPX5RBTlVdo9MTSgnFizp
Ii1NjHLuVVCSLb1OjoTgu0cQFiWEBCkC1XuoR8RCY6iWVrUH4Gezni7ckt2mJaNA
pd6/87dFKE3jh5T6jZeJMJg5skTZHSozJDuaj9pMK/JONSD06sECggEBAPq2lEmd
g1hpMIqa7ey1uoLd1zFFzlWrxTJLlu38N69mYDOHrV/zqRGOpZB+1nH7tQJIT/L1
xLN33mFVqCrN8yUmZ+iUWioaI5JZ1jzCgemVGeBgodwP9MOZfxxrDp17oTdabaEq
7ZaBYnY8xK/4bCxu/B4mFiF3Za8ZTd/+2yev7JM+E3MorWc7rrKm1ApflfxytdhO
JLBiqOcqobI3dgHyzesVb8cT4XCpoRhdrFwort0JI7ryfddd49vMJ3ElRbnN/h4F
f24cWY/sQPq/nfDmec28Z7nVza1D4rszNylYDvzdjF0Q1mL5dFVntWbZA1CNurVw
nTfwuyQ8RF9YnYMCggEBAM6lpNeqaiG9ixKSr65pYOKtByUI3/eTT4vBnrDtYF+8
ohiKgIymG/vJsSdrynKfwJObEy2dBYhCGF3h9z2nc9KJQD/su7wxCsdmBs7YoDiM
uzNPlRAmI0QAFILPCk48z/lUQk3r/Mzu0YzRv7fI4WSpIGAefVPDqy1uXsATDoDJ
arcEkND5Lib89Lx7r02EevJJTdhTJM8mBdRl6wpNV3xBdwis67uSyunFZYpSiMw7
WWjIRhzhLIvpgD78UvNvuJi0UGVEjTqnxvuW3Y6sLfIk80KSR24USinT27t//x7z
yzNko75avF2hm1f8Y/EpcHHAax8NAQF5uuV9xBNvv3ECggEAdS/sRjCK2UNpvg/G
0FLtWAgrcsuHM4IzjVvJs3ml6aV3p/5uKqBw0VUUzGKNCAA4TlXQkOcRxzVrS6HH
FiLn2OCHxy24q19Gazz0p7ffE3hu/PMOFRecN+VChd0AmtnTtFTfU2sGXMgjZtLm
uL3siiRiUhFJXOE7NUolnWK5u2Y+tWBZpQVJcCx0busNx7+AEtznZLC583xaKJtD
s1K7JRQB7jU55xrC0G9pbkMysm0NtyFzgwmfipBHVlCpyvg6DCxd8FhvhN9Zea1b
fhkc0SJZorHC5hkqpydJDmlVCk0vzEAeQM4C94ZUOytbnjQnmXp14CNASYqLXteQ
ueRo0wKCAQAG0F10IxFm1WotjZqvZJgmQVBX/0frUPcxg4vpB5rC7WRm7MI6YQvR
LKBjzWEakHv4Igfq3B+fk5ZcGiRd6xSdn5r3wKWcGf3h/1JAJdJ6quFNWtVud+N3
zYzfl1YeqFCvRwD8ssheNY3BV/U7aStNd2oy4S5+wZf2YopLSRWUV4/mQwdHbMAB
1xt2z5lDNBgdvx8LAArZrcZJb6blaxF0bnAvYAxR3hBEzxZ/DiOmoFpdYyU0tJQU
dPmemhFeJ5PtrRxtimohwgCEsT/TAYhuUJuY2VvznEWpxWucbicKbT2JD0t67mEB
sV9+8jqVbCliBtdBadtbohjwkkoR3gBxAoIBAG3cZuNkIWpELEbeICKouSOKN06r
Fs/UXU8roNThPR7vPtjeD1NDMmUHJr1FG4SJrSigdD8qNBg8w/G3nI0Iw7eFskk5
8mNm21CpDzON36ZO7IDMj5uyBlj2t+Ixl/uJYhYSpuNXyUTMm+rkFJ0vdSV4fjLd
J2m30juYnMiBBJf7dz5M95+T0xicGWyV24zVYYBbSo0NHEGxqeRhikNqZNPkod6f
kfOJZGalh2KaK5RMpZpFFhZ/kW9xRWNJZyCWgkIoYkdilMuISBu3lCrk8rdMpAL0
wHEcq8xwcgYCS2qk8HwjtmVd3gpB1y9UshMr3qnuH1wMpU5C+nM2oy3vSko=
-----END RSA PRIVATE KEY-----
-6
View File
@@ -1,6 +0,0 @@
{
"network-peer-list-gossip-frequency": "250ms",
"network-max-reconnect-delay": "1s",
"health-check-frequency": "2s",
"log-level":"debug"
}
-30
View File
@@ -1,30 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFNzCCAx8CCQC687XFxtDRSjANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJV
UzELMAkGA1UECAwCTlkxDzANBgNVBAcMBkl0aGFjYTEQMA4GA1UECgwHQXZhbGFi
czEOMAwGA1UECwwFR2Vja28xDDAKBgNVBAMMA2F2YTEiMCAGCSqGSIb3DQEJARYT
c3RlcGhlbkBhdmFsYWJzLm9yZzAgFw0xOTA3MDIxNjEyMTlaGA8zMDE5MDcxMDE2
MTIxOVowOjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRAwDgYDVQQKDAdBdmFs
YWJzMQwwCgYDVQQDDANhdmEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
AQDdToR60na6NuR9iSAUMyzPXJNMWVQbLyT5/iZCiJ3BB4YWMBhfxpJWJiWXcM+z
nDgpJuyCEeh5Dp6ZY3Fe7k6Hht6FmFpDjwnjpQmdkEKUg00G+ElPTp/UsmsPL+JA
swPqBZWpMBS3dsXQNunMMtMGlrf5S0l6XX4y7kc/GTxYgveWZ9JtR/m2KNer+wjg
BHqJ4rPqnHB30sDYPZg91Cz1Ak8Bb2w2I108zQVgKK6eIqNKXJJ/4pizSZdU4920
wMxYBpnfDAchnxei9U/v3QbT7eKUI2fGr+hOWTIWU80+VeOBt8a6P4sS9AQh5/6G
8qwmAqO3YQ9dxN82iu/H3+N+GGa/M0r5rEWrzwIuFhwKvyQcpPRBm2yQnBnhL9G5
kN6n4OBM0KsgZ3CYlHZSg4eWcNgBt1WCFsQc7vfUFaJnr8QP3pF4V/4Bok7wTO5H
N0A1EYEVYuX53NGnrKVe+Fg9+xMOgXPWkUNqdvpI9ZbV3Z0S5866qF3/vBZrhgCr
Kc5E/vMexBRe8Ki4wKqONVhi9WGUcRHvFEikc+7VrPj0YaG6zVLd+uOAJN81fKOP
Yo4X4sZrMyPYl3OjGtMhfV4KvCaLEr1duOklqO6cCvGQ8iAlLVy3VJyW5GJ0D0Ky
iAir4VNdAJKo1ZgiGivJLWulTfjUifCN9o115AiqJxiqwwIDAQABMA0GCSqGSIb3
DQEBCwUAA4ICAQCQOdwD7eRIxBvbQHUc+m0TRzEa17BCfck1Y2WwN3TZXDGSkPVE
0uujA8SL3qi8/CTLGRqI9U3gRZJf+tJPBF/P021PEmyaFTS4htxcDxTxuZv2jCo9
+XhUEyvRWitTmoy1esq3mkotVQHeTmQvwCsQJAhctVA/hRdJwmMPs1B8QxOUI6Bq
SOBHa9CsXIzVOFv8FqE91PZA2ns30sKQYrrnbH99apfF5WglLUoyPwxf2e3AACh7
beEdk45ivvKwi5Jk8nr85KDHYPlqkr0bd9Ehl8xplaNBdMPeRufqBDlztjcLJ3wo
mnrt95gQMeSoLHY3UNsIRjbj43zImu7q9v/DD9ppQpu26aRDRmBNgLZA9GM5XnbZ
RFi3VxLyqasGcSzaHwz5c7vOBOkOdlqcQzISRvWDxiN1HkAL+hkiQCuMchgORAgM
wzPooa8rfWtLIpOXMpwuVGb/8rGNLEPovoCK9z6c+WZ+zkRo4+3TQkOMY66Xht7r
Ahly3ler+Tyg6a5jXT92WKC/MXBYAy2ZQNoy204kNKevcH7R2cSkxITd3n5EacNy
5MAtCNIk7JweLCh9rLrLUBt+i4n44sP+LVhfWHemngA8CoF4n6eQ0pp0ixZTen0j
4uN0G2Nf+JeGMlqoObLWdIOdH/pbDppXGoZaKKDd7+bA74Fle5Uh7+1e3A==
-----END CERTIFICATE-----
-51
View File
@@ -1,51 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
-6
View File
@@ -1,6 +0,0 @@
{
"network-peer-list-gossip-frequency": "250ms",
"network-max-reconnect-delay": "1s",
"health-check-frequency": "2s",
"log-level":"debug"
}
-30
View File
@@ -1,30 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFNzCCAx8CCQC687XFxtDRSjANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJV
UzELMAkGA1UECAwCTlkxDzANBgNVBAcMBkl0aGFjYTEQMA4GA1UECgwHQXZhbGFi
czEOMAwGA1UECwwFR2Vja28xDDAKBgNVBAMMA2F2YTEiMCAGCSqGSIb3DQEJARYT
c3RlcGhlbkBhdmFsYWJzLm9yZzAgFw0xOTA3MDIxNjEyMjJaGA8zMDE5MDcxMDE2
MTIyMlowOjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRAwDgYDVQQKDAdBdmFs
YWJzMQwwCgYDVQQDDANhdmEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
AQC8mVDToHbkUF2gRdVfpydZLNKeQ38d6HZFkUM3U1dWLZFSZNvagN8hlQvY/tQu
3A40p19WgKbzWZre3tg1Akw8Jztdz9gl4RMn142IIO3CiwIptkE0JopbZhmG5fAC
2n/MXQtfieI3hzeR04LW4JgLKzf3Nn8xZdlBgJfBmL5qUUnE7O7IbJGGma6gSD3e
wetE6KQZtNtf0xRIv08doZKYwTl6ItkdGK76ufqq098GVwWvA1wSune4+MFgs9N4
eFJj6Jyt85fiK/cwPx7KRdgYgBzrZQ4EPshRnwWrBTieOOaJvAA2RMxMEYzKRrJA
AsYI1zxtNyqIUaBTcxmaz+NXUGW+wHwITic0Gp/XQm2Lwr/lxIV6OnAlL3CgbSXi
rSnoG+eHQ+vDzBAcRDkTAgv/GUIzlfqT2StTK02uIBgJYzvFTG4plHitccRfy8wx
sh5Z8xG99lmPQQtLsnlQAV+Li06Cb8CH4hUVoiWiVs5QAahqWmv5fpoX0Es26RyU
HXGbjE202pyMMA7jUerUVKMijOoGZtcH6zB4p/dJ0TtToRwOgrA7NCI9AYVtqVXr
XG/udj8ur2r1bTVwIbHsOeTEP3gY0mHRWm2E/bLjt9vbYIRUxR8xWnLkbeBziNTw
g+36jdDF+6gu3cUz/nbSn8YY+Y1jjXuM3lqF8iMaAobhuwIDAQABMA0GCSqGSIb3
DQEBCwUAA4ICAQAe2kC0HjKZU+dlnU2RlfBpB4QgzzrFE5N9A8F1MlE4vV3AzCg1
RVdHPvniXzdNhDiiflK0l/cnrFv2X1TzYMrrA677/usHf2Bw0xjm/ipHOt5V+4TN
mZAIA4IPl09gP28IZLc9xSuq4FoHeM8OTxhttOlINhqpG9P5d6bPezW6ZzI3CdPP
CF69xK4GFlj/NQnAoFogid4ojYYNTj/cM4PYQU2KbrlzLyPuUk/CgwefXLMH87/H
e3kPDev80Tjv2Pm5nD937fZfgrEoyolKxiRVcfZVMxR7qhPhizjueD0DAkfQIs7L
YVSyx/qjEv2bBYaim5RQakUeHR1Xu5Xj/k5zr33t979ede50byQrcWm4H5JxnEpD
JxJnFfDOU6o14SKGHSrao5Z4C3dI55DM84WLASnlMI5BK4XtS3notLNzG8dfWWhT
9m0Hcry+wPNDcGr8Mtj1los/0bMDqMHC4jcFW1hrXCUUs9RYzE+N/xoqwCQSgN1P
E73uXTySWj5ovMR5TPF6PhcftLB/OziqO7FverEBpvGGHUAnUT61JtjodjXPbEdj
0VgyMOBY2y53HTXnx3dxeFZkUdRX/VZYy8tMK3MTY+7UIU5cWYnCZAo5LNcc0ukR
S6WS9+6eaQ6XRjhfNUjx9a7FzqapWdtTedpipmBP1Njap3g29iUuVnLQeg==
-----END CERTIFICATE-----
-51
View File
@@ -1,51 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
-6
View File
@@ -1,6 +0,0 @@
{
"network-peer-list-gossip-frequency":"250ms",
"network-max-reconnect-delay":"1s",
"health-check-frequency":"2s",
"log-level":"debug"
}
-30
View File
@@ -1,30 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFNzCCAx8CCQC687XFxtDRSjANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJV
UzELMAkGA1UECAwCTlkxDzANBgNVBAcMBkl0aGFjYTEQMA4GA1UECgwHQXZhbGFi
czEOMAwGA1UECwwFR2Vja28xDDAKBgNVBAMMA2F2YTEiMCAGCSqGSIb3DQEJARYT
c3RlcGhlbkBhdmFsYWJzLm9yZzAgFw0xOTA3MDIxNjEyMjVaGA8zMDE5MDcxMDE2
MTIyNVowOjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRAwDgYDVQQKDAdBdmFs
YWJzMQwwCgYDVQQDDANhdmEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
AQDZnDoDHE2nj82xDjH0Tb7OXMqQDHz+zbLidt6MSI1XB3vOAIEiPqrtenGnqRbV
Fcm5GZxvxh4YQD8CjKSk1qgZJczs0DPSiGQ8Efl4PGO4xnEbllgL3PURPWp7mEV3
oh6fxICgQKTBlT671EnFzB5lyJWpumRzvA1vyhBMsY8aO+xdq5LUFltYzBdvpgLX
VaDwHZQ2PQEWtF0d0JO2N0WFFDGNmx6n8pKSeIAVDsTwZCZK+FCeeEyoGfXsINsc
0yCMQslawkfOMqA9yBV3Ji6QmFYKyGYt65MWGNqPA4XrIyliKwCCXwz9mjaWyN7r
Ayw9cWlLMODNmDORWzGRZ5290MEAEIZsqjYHVitRTM/RnNIadToZGO0y5uAkM14c
mTvnsK1CP92qtfSisq75W/I91drThoEtTK78UGOl/5Q1YBR08F+tSUWZWyHeI6UO
BUCGC2bCtmzKMl7vU25lG6mbCR1JuQi6RYpnfMjXH36lV4S7fTvSwwuR03h2F3H1
eFkWNG2lbFrW0dzDCPg3lXwmFQ65hUcQhctznoBz5C1lF2eW03wuVgxinnuVlJHj
y/GrqmWsASn1PDuVs4k7k6DJfwyHAiA0uxXrGfxYvp7H8j4+2YOmWiWl5xYgrEDj
ur5n8Zx46PHQer2Avq3sbEGEe1MCtXJlj3drd5Him3m+NQIDAQABMA0GCSqGSIb3
DQEBCwUAA4ICAQA40ax0dAMrbWikaJ5s6kjaGkPkYuxHNJbw047Do0hjw+ncXsxc
QDHmWcoHHpgMQCx0+vp8y+oKZ4pnqNfGSuOTo7/l05oQW/NbWw9mHwTiLMeI18/x
Ay+5LpOasw+omqWLbdbbWqL0o/RvtBdK2rkcHzTVzECgGSoxUFfZD+ck2odpH+aR
sQVu86AZVfclN2mjMyFSqMItqRcVw7rqr3Xy6FcgRQPykUnpguCEgcc9c54c1lQ9
Zpddt4ezY7cTdk86oh7yA8QFchvtE9Zb5dJ5Vu9bdy9ig1kyscPTm+SeyhXRchUo
ql4H/czGBVMHUY41wY2VFz7HitECcTAIpS6QvcxxgYevGNjZZxyZvEA8SYpLMZyb
omk4enDTLd/xK1yF7VFodTDEyq63IAm0NTQZUVvIDfJeuzuNz55uxgdUq2RLpaJe
0bvrt9Obz+f5j2jonb2e0BuucwSdTyFXkUCxMW+piIUGkyrguAhlcHohDLEo2uB/
iQ4fosGqqsl47b+TezT5pSSblkgUjiwz6eDpM4lQpx22MxsHVlxFHrcBNm0Td92v
FixrmllamAZbEz1tB//0bipKaOOZuhANJfrgN8BC6v2ahl4/SBuut09a0Azyxqpp
uCsyTnfNEd1W6c6noaq24s+7W7KKLIekuNn1NunnHqKqriEuH1xlxxPjYA==
-----END CERTIFICATE-----
-51
View File
@@ -1,51 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
-6
View File
@@ -1,6 +0,0 @@
{
"network-peer-list-gossip-frequency":"250ms",
"network-max-reconnect-delay":"1s",
"health-check-frequency":"2s",
"log-level":"debug"
}
-30
View File
@@ -1,30 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFNzCCAx8CCQC687XFxtDRSjANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJV
UzELMAkGA1UECAwCTlkxDzANBgNVBAcMBkl0aGFjYTEQMA4GA1UECgwHQXZhbGFi
czEOMAwGA1UECwwFR2Vja28xDDAKBgNVBAMMA2F2YTEiMCAGCSqGSIb3DQEJARYT
c3RlcGhlbkBhdmFsYWJzLm9yZzAgFw0xOTA3MDIxNjEyMjlaGA8zMDE5MDcxMDE2
MTIyOVowOjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRAwDgYDVQQKDAdBdmFs
YWJzMQwwCgYDVQQDDANhdmEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
AQDgK5r5vdHtJFEgw7hGE/lzKaHcvwzr32armq0k9tYchJXfT3k1j1lXtBAdcUN3
gSRKjgzH/vjbn0ea3AiDCUd2Mck/n0KcJZ43S5I7ZjP7rbav296bKCZ1Hr7r5gXY
Fhk+3aUsVfDUqAPBwyP8KeV31ARVA/s+WPeWqs69QXTdyJuBYE5pr40v1Sf+ebUI
nZ37uGY3kiO0Ex/JgcoQsGJzrWD/ztbRCFIvrdNJZd0pGvMlmTKp7XsMR3cpvqk7
70//MLCdyGW/1IArTSuD1vd7mBX1JyVXKycYN0vIOtbgxPOFutUyqDOeP7o51q4i
PS3dCRgfmn/hWLwy+CtJe0BGKsb4tk0tKxo0se8v9JA8mUtnmzmMt4Y9jijOrCOB
7XwWKmJYEm8N5Ubcy6cp2oL8vQVtzz3PXrkFt+3cFt1jrjdpQYgH4jykkWDeOjEf
y1FCwzsNRudLTvLhfLn86/ZT4cLZ9JI7/WW0IPC8Fc7lhznJ+bIQUeEndaGdgVkx
uEg0MxdrMr0jU0IFoXySRXNRzcDWZShEjBTv7tnFxLmoNU+uJb/KpMH6sRYi3zs8
5ecaMKNyG+LDmBahUlHx5hKAH49O8855+AMhsg91ONZJldjQX0oZrIKzK5BpsqeT
l4c2Yt/fALiZaeFk1pBEsvVeMOBCIuWE+b4UIEaLAOhxfwIDAQABMA0GCSqGSIb3
DQEBCwUAA4ICAQB+2VXnqRqfG7H2/K0lgzxT+X9r1u+YDn0EaUGAG71s70Qnqbpn
X7tBmCKLN6XgPL0HrN933nwiYrmfb8S33zZ7kw8GJDvaTamLNyem4/8qTBQmnRwe
6rQ7SY2l73Ig87mR0WTi+rTnTTtc66+/jLtFeaj0Ycl9hBZXHKiULSGhsbUbwtkz
iuNlANhoNKXNIABRImUq6OwYhEQN0DwHXj79wkpyDYjKZwHuEZUknc8Pl2oQPBke
mil3tsrvGRkwhisnXX7tqh6rWKVZNJkO68hy7XO9aTXjbcB/7Y1K83ISNEyGPsH/
pwFyd/j8O4modwh7Ulww1/hwcqnqiEFE3KzxX2pMh7VxeAmX2t5eXFZOlRx1lecM
XRkVu19lYDKQHGSrGxng+BFlSOB96e5kXIbuIXKpPAACoBQ/JZYbtHks9H8OtNYO
P2joqmnQ9wGkE5co1Ii//j2tuoCRCpK86mmbTlyNYvK+1/kkKcsaiiWXNrQsrIDZ
BFs0FwX5g24OP5+brxTlRZE01R6St8lQj4IUwAcIzG8fFmMCWaYavrCZTeYaEiyF
A0X2VA/vZ7x9D5P9Z5OakMhrMW+hJTYrpH1rm6KR7B26iU2kJRxTX7xQ9lrksqfB
7lX+q0iheeYA4cHbGJNWwWgd+FQsK/PTeiyr4rfqututdWA0IxoLRc3XFw==
-----END CERTIFICATE-----
-51
View File
@@ -1,51 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
-153
View File
@@ -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
}
-13
View File
@@ -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
-116
View File
@@ -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
---
+4 -5
View File
@@ -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{}{
-28
View File
@@ -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
)
-27
View File
@@ -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=
-20
View File
@@ -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)
)
-28
View File
@@ -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
}
-210
View File
@@ -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
View File
@@ -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()
}
-507
View File
@@ -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
View File
@@ -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
}
-49
View File
@@ -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
View File
@@ -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 := &params.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
}
-146
View File
@@ -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
View File
@@ -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
View File
@@ -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 {
-11
View File
@@ -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 {
-36
View File
@@ -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
View File
@@ -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")
}
+7 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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")
-23
View File
@@ -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")