diff --git a/.github/workflows/go.yaml b/.github/workflows/go.yaml index 8e7b3d5c..1776a067 100644 --- a/.github/workflows/go.yaml +++ b/.github/workflows/go.yaml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 with: - go-version: '>=1.20.2' + go-version: '>=1.22' - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: @@ -29,6 +29,6 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 with: - go-version: '>=1.20.2' + go-version: '>=1.22' - name: unit tests run: make test diff --git a/.github/workflows/manifests.yaml b/.github/workflows/manifests.yaml index fd96a968..c263ee16 100644 --- a/.github/workflows/manifests.yaml +++ b/.github/workflows/manifests.yaml @@ -14,9 +14,8 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 with: - go-version: '>=1.20.2' + go-version: '>=1.22' - run: make generate manifests - - uses: CatChen/check-git-status-action@v1 - with: - fail-if-not-clean: true + - name: Ensure no changes + run: git diff --exit-code diff --git a/.github/workflows/strangelove-project-management.yaml b/.github/workflows/strangelove-project-management.yaml deleted file mode 100644 index 4e037aca..00000000 --- a/.github/workflows/strangelove-project-management.yaml +++ /dev/null @@ -1,25 +0,0 @@ -name: Strangelove Project Management -on: - issues: - types: - - opened - - reopened - - closed - -jobs: - issue_opened_or_reopened: - name: issue_opened_or_reopened - runs-on: ubuntu-latest - if: | - startsWith(github.repository,'strangelove-ventures/') && - github.event_name == 'issues' && (github.event.action == 'opened' || github.event.action == 'reopened') - steps: - - name: Add Issue to "Motherboard" Project Board - uses: leonsteinhaeuser/project-beta-automations@v2.0.1 - with: - gh_app_secret_key: ${{ secrets.MB_SECRET_KEY }} - gh_app_ID: ${{ secrets.MB_APP_ID }} - gh_app_installation_ID: ${{ secrets.MB_INSTALLATION_ID }} - organization: strangelove-ventures - project_id: 4 - resource_node_id: ${{ github.event.issue.node_id }} diff --git a/.gitignore b/.gitignore index 5577a8a5..cf7e0ec3 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,5 @@ testbin/* *~ # Local temporary files -/tmp \ No newline at end of file +/tmp +.vscode/settings.json \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 75919d0c..9eb84c6e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # See rocksdb/README.md for instructions to update rocksdb version FROM ghcr.io/strangelove-ventures/rocksdb:v7.10.2 AS rocksdb -FROM --platform=$BUILDPLATFORM golang:1.20-alpine AS builder +FROM --platform=$BUILDPLATFORM golang:1.23-alpine AS builder RUN apk add --update --no-cache\ gcc\ diff --git a/README.md b/README.md index d62427b7..d5545a3b 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,88 @@ -# Cosmos Operator - +[![Conforms to README.lint](https://img.shields.io/badge/README.lint-conforming-brightgreen)](https://github.com/strangelove-ventures/readme-dot-lint) [![Project Status: Initial Release](https://img.shields.io/badge/repo%20status-active-green.svg?style=flat-square)](https://www.repostatus.org/#active) [![GoDoc](https://img.shields.io/badge/godoc-reference-blue?style=flat-square&logo=go)](https://pkg.go.dev/github.com/strangelove-ventures/cosmos-operator) [![Go Report Card](https://goreportcard.com/badge/github.com/strangelove-ventures/cosmos-operator)](https://goreportcard.com/report/github.com/strangelove-ventures/cosmos-operator) [![License: Apache-2.0](https://img.shields.io/github/license/strangelove-ventures/cosmos-operator.svg?style=flat-square)](https://github.com/strangelove-ventures/cosmos-operator/blob/main/LICENSE) [![Version](https://img.shields.io/github/tag/strangelove-ventures/cosmos-operator.svg?style=flat-square)](https://github.com/cosmos/strangelove-ventures/cosmos-operator) -Cosmos Operator is a [Kubernetes Operator](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) for blockchains built with the [Cosmos SDK](https://github.com/cosmos/cosmos-sdk). +Cosmos Operator is a [Kubernetes Operator](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) primarily for blockchains built with the [Cosmos SDK](https://github.com/cosmos/cosmos-sdk). It also supports [Penumbra](https://github.com/penumbra-zone/penumbra) and other chains which use [CometBFT](https://github.com/cometbft/cometbft) for consensus. -The long-term vision of this operator is to allow you to "configure it and forget it". +🌌 Why use Cosmos Operator? +============================= -## Motivation +Kubernetes ("K8") makes DevOps easier. Cosmos Operator makes Kubernetes easier for use in the Cosmos Ecosystem. -Kubernetes provides a foundation for creating highly-available, scalable, fault-tolerant applications. -Additionally, Kubernetes provides well-known DevOps patterns and abstractions vs. -traditional DevOps which often requires "re-inventing the wheel". +K8 provides a foundation for creating highly-available, scalable, fault-tolerant applications. It provides well-known DevOps patterns and abstractions (as opposed to traditional DevOps which often requires "re-inventing the wheel"). -Furthermore, the Operator Pattern allows us to mix infrastructure with business logic, +Furthermore, the [Operator Pattern][] allows us to mix infrastructure with business logic, thus minimizing human intervention and human error. -# Disclaimers -* Tested on Google's GKE and Bare-metal with Kubeadm. Although kubernetes is portable, we cannot guarantee or provide support for AWS, Azure, or other kubernetes providers. -* Requires a recent version of kubernetes: v1.23+. -* CosmosFullNode: The chain must be built from the [Cosmos SDK](https://github.com/cosmos/cosmos-sdk). -* CosmosFullNode: Validator sentries require a remote signer such as [horcrux](https://github.com/strangelove-ventures/horcrux). -* CosmosFullNode: The controller requires [heighliner](https://github.com/strangelove-ventures/heighliner) images. If you build your own image, you will need a shell `sh` and set the uid:gid to 1025:1025. If running as a validator sentry, you need `sleep` as well. -* CosmosFullNode: May not work for all Cosmos chains. (Some chains diverge from common conventions.) Strangelove has yet to encounter a Cosmos chain that does not work with this operator. +🌌🌌 Who benefits from Cosmos Operator? +============================= + +People who'd like to use the [Operator Pattern][] to "configure it and forget it". + +> The [operator pattern][] aims to capture the key aim of a human operator who is managing a service or set of services. Human operators who look after specific applications and services have deep knowledge of how the system ought to behave, how to deploy it, and how to react if there are problems. + +> People who run workloads on Kubernetes often like to use automation to take care of repeatable tasks. The [operator pattern][] captures how you can write code to automate a task beyond what Kubernetes itself provides. + -# CosmosFullNode CRD +🌌🌌🌌 What does Cosmos Operator do? +============================= + +Cosmos Operator is a [Kubernetes Operator](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) for blockchains built with the [Cosmos SDK](https://github.com/cosmos/cosmos-sdk). Write your own Custom Resource Definition ("CRD") as a `yaml` file and deploy with ease! + + +🌌🌌🌌🌌 How do I use Cosmos Operator? +============================= + +## Quick Start + +See the [quick start guide](./docs/quick_start.md). -Status: v1, stable +## CosmosFullNode CRD -CosmosFullNode is the flagship CRD. Its purpose is to deploy highly-available, fault-tolerant blockchain nodes. +CosmosFullNode is the flagship CRD. Its purpose is to deploy highly-available, fault-tolerant blockchain nodes. The CosmosFullNode controller is like a StatefulSet for running Cosmos SDK blockchains. -A CosmosFullNode can be configured to run as an RPC node, a validator sentry, or a seed node. All configurations can -be used as persistent peers. +A CosmosFullNode can be configured to run as an RPC node, a validator sentry, or a seed node. All configurations can be used as persistent peers. -As of this writing, Strangelove has been running CosmosFullNode in production for many months. +As of this writing, Strangelove has been running CosmosFullNode in production for over a year. -[Minimal example yaml](./config/samples/cosmos_v1_cosmosfullnode.yaml) +## Samples -[Full example yaml](./config/samples/cosmos_v1_cosmosfullnode_full.yaml) +- [Minimal example yaml](./config/samples/cosmos_v1_cosmosfullnode.yaml) +- [Full example yaml](./config/samples/cosmos_v1_cosmosfullnode_full.yaml) +- [Penumbra example yaml](./config/samples/cosmos_v1_cosmosfullnode_penumbra.yaml) + +## Support CRDs + +These CRDs are part of the operator and serve to support CosmosFullNodes. + +- [ScheduledVolumeSnapshot](./docs/scheduled_volume_snapshot.md) +- [StatefulJob](./docs/stateful_job.md) ### Why not a StatefulSet? + Each pod requires different config, such as peer settings in config.toml and mounted node keys. Therefore, a blanket template as found in StatefulSet did not suffice. -Additionally, CosmosFullNode gives you more control over individual pod and pvc pairs vs. a StatefulSet to help -the human operator debug and recover from situations such as a corrupted PVCs. +Additionally, CosmosFullNode gives you more control over individual pod and pvc pairs vs. a StatefulSet to help the human operator debug and recover from situations such as a corrupted PVCs. -# Support CRDs -These CRDs are part of the operator and serve to support CosmosFullNodes. +🌌🌌🌌🌌🌌 Extras +============================= -* [ScheduledVolumeSnapshot](./docs/scheduled_volume_snapshot.md) -* [StatefulJob](./docs/stateful_job.md) - -# Quick Start +# Disclaimers -See the [quick start guide](./docs/quick_start.md). +- Tested on Google's GKE and Bare-metal with `Kubeadm`. Although kubernetes is portable, we cannot guarantee or provide support for AWS, Azure, or other kubernetes providers. +- Requires a recent version of kubernetes: v1.23+. +- CosmosFullNode: The chain must be built from the [Cosmos SDK](https://github.com/cosmos/cosmos-sdk). +- CosmosFullNode: Validator sentries require a remote signer such as [horcrux](https://github.com/strangelove-ventures/horcrux). +- CosmosFullNode: The controller requires [heighliner](https://github.com/strangelove-ventures/heighliner) images. If you build your own image, you will need a shell `sh` and set the uid:gid to 1025:1025. If running as a validator sentry, you need `sleep` as well. +- CosmosFullNode: May not work for all Cosmos chains. (Some chains diverge from common conventions.) Strangelove has yet to encounter a Cosmos chain that does not work with this operator. # Contributing @@ -75,7 +96,7 @@ See the [best practices guide for CosmosFullNode](./docs/fullnode_best_practices Disclaimer: Strangelove has not committed to these enhancements and cannot estimate when they will be completed. -- [ ] Scheduled upgrades. Set a halt height and image version. The controller performs a rolling update with the new image version after the committed halt height. +- [x] Scheduled upgrades. Set the upgrade height and image version, optionally setting halt height. The controller performs a rolling update with the new image version after the committed height. - [x] Support configuration suitable for validator sentries. - [x] Reliable, persistent peer support. - [x] Quicker p2p discovery using private peers. @@ -104,3 +125,7 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +--- + +[Operator Pattern]: https://kubernetes.io/docs/concepts/extend-kubernetes/operator/#operators-in-kubernetes \ No newline at end of file diff --git a/api/v1/cosmosfullnode_types.go b/api/v1/cosmosfullnode_types.go index a4c3f11d..68a5b7e3 100644 --- a/api/v1/cosmosfullnode_types.go +++ b/api/v1/cosmosfullnode_types.go @@ -303,14 +303,16 @@ type PodSpec struct { type FullNodeProbeStrategy string const ( - FullNodeProbeStrategyNone FullNodeProbeStrategy = "None" + FullNodeProbeStrategyNone FullNodeProbeStrategy = "None" + FullNodeProbeStrategyReachable FullNodeProbeStrategy = "Reachable" + FullNodeProbeStrategyInSync FullNodeProbeStrategy = "InSync" ) // FullNodeProbesSpec configures probes for created pods type FullNodeProbesSpec struct { // Strategy controls the default probes added by the controller. // None = Do not add any probes. May be necessary for Sentries using a remote signer. - // +kubebuilder:validation:Enum:=None + // +kubebuilder:validation:Enum:=None;Reachable;InSync // +optional Strategy FullNodeProbeStrategy `json:"strategy"` } @@ -436,6 +438,8 @@ type ChainSpec struct { Comet CometConfig `json:"config"` // App configuration applied to app.toml. + // Although optional, it's highly recommended you configure this field. + // +optional App SDKAppConfig `json:"app"` // One of trace|debug|info|warn|error|fatal|panic. @@ -559,6 +563,14 @@ type ChainVersion struct { // The docker image for this version in "repository:tag" format. E.g. busybox:latest. Image string `json:"image"` + // Version overrides for initContainers of the fullnode/sentry pods. + // +optional + InitContainers map[string]string `json:"initContainers"` + + // Version overrides for containers of the fullnode/sentry pods. + // +optional + Containers map[string]string `json:"containers"` + // Determines if the node should forcefully halt at the upgrade height. // +optional SetHaltHeight bool `json:"setHaltHeight,omitempty"` @@ -720,6 +732,10 @@ type ServiceSpec struct { // Overrides for the single RPC service. // +optional RPCTemplate ServiceOverridesSpec `json:"rpcTemplate"` + + // Overrides for default cluster domain name. + // +optional + ClusterDomain *string `json:"clusterDomain"` } // ServiceOverridesSpec allows some overrides for the created, single RPC service. @@ -733,6 +749,11 @@ type ServiceOverridesSpec struct { // +optional Type *corev1.ServiceType `json:"type"` + // Setting this to "None" makes a "headless service" (no virtual IP), which is useful when direct endpoint connections are preferred and proxying is not required. + // If not set, defaults to "". + // +optional + ClusterIP *string `json:"clusterIP"` + // Sets endpoint and routing behavior. // See: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#caveats-and-limitations-when-preserving-source-ips // If not set, defaults to "Cluster". diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index e52a60d9..fdffcbe1 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -106,7 +106,9 @@ func (in *ChainSpec) DeepCopyInto(out *ChainSpec) { if in.Versions != nil { in, out := &in.Versions, &out.Versions *out = make([]ChainVersion, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } if in.AdditionalInitArgs != nil { in, out := &in.AdditionalInitArgs, &out.AdditionalInitArgs @@ -133,6 +135,20 @@ func (in *ChainSpec) DeepCopy() *ChainSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ChainVersion) DeepCopyInto(out *ChainVersion) { *out = *in + if in.InitContainers != nil { + in, out := &in.InitContainers, &out.InitContainers + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Containers != nil { + in, out := &in.Containers, &out.Containers + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ChainVersion. @@ -734,6 +750,11 @@ func (in *ServiceOverridesSpec) DeepCopyInto(out *ServiceOverridesSpec) { *out = new(corev1.ServiceType) **out = **in } + if in.ClusterIP != nil { + in, out := &in.ClusterIP, &out.ClusterIP + *out = new(string) + **out = **in + } if in.ExternalTrafficPolicy != nil { in, out := &in.ExternalTrafficPolicy, &out.ExternalTrafficPolicy *out = new(corev1.ServiceExternalTrafficPolicyType) @@ -761,6 +782,11 @@ func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) { } in.P2PTemplate.DeepCopyInto(&out.P2PTemplate) in.RPCTemplate.DeepCopyInto(&out.RPCTemplate) + if in.ClusterDomain != nil { + in, out := &in.ClusterDomain, &out.ClusterDomain + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceSpec. diff --git a/cmd/versioncheck.go b/cmd/versioncheck.go index b642b84d..0cb23bd9 100644 --- a/cmd/versioncheck.go +++ b/cmd/versioncheck.go @@ -174,7 +174,12 @@ func checkVersion( image = v.Image } - thisPodImage := thisPod.Spec.Containers[0].Image + var thisPodImage string + for _, c := range thisPod.Spec.Containers { + if c.Name == "node" { + thisPodImage = c.Image + } + } if thisPodImage != image { return fmt.Errorf("image mismatch for height %d: %s != %s", height, thisPodImage, image) } diff --git a/config/crd/bases/cosmos.strange.love_cosmosfullnodes.yaml b/config/crd/bases/cosmos.strange.love_cosmosfullnodes.yaml index 38d1ca14..aed78565 100644 --- a/config/crd/bases/cosmos.strange.love_cosmosfullnodes.yaml +++ b/config/crd/bases/cosmos.strange.love_cosmosfullnodes.yaml @@ -81,7 +81,9 @@ spec: Use AddrbookScript if the chain has an unconventional file format or address book location. type: string app: - description: App configuration applied to app.toml. + description: |- + App configuration applied to app.toml. + Although optional, it's highly recommended you configure this field. properties: apiEnableUnsafeCORS: description: Defines if CORS should be enabled for the API @@ -352,6 +354,12 @@ spec: If not provided, the operator will not upgrade the chain, and will use the image specified in the pod spec. items: properties: + containers: + additionalProperties: + type: string + description: Version overrides for containers of the fullnode/sentry + pods. + type: object height: description: The block height when this version should be applied. @@ -361,6 +369,12 @@ spec: description: The docker image for this version in "repository:tag" format. E.g. busybox:latest. type: string + initContainers: + additionalProperties: + type: string + description: Version overrides for initContainers of the + fullnode/sentry pods. + type: object setHaltHeight: description: Determines if the node should forcefully halt at the upgrade height. @@ -371,7 +385,6 @@ spec: type: object type: array required: - - app - binary - chainID - network @@ -3918,6 +3931,8 @@ spec: None = Do not add any probes. May be necessary for Sentries using a remote signer. enum: - None + - Reachable + - InSync type: string type: object resources: @@ -5672,6 +5687,9 @@ spec: This allows a k8s admin to use the service in an Ingress, for example. Additionally, multiple p2p services are created for CometBFT peer exchange. properties: + clusterDomain: + description: Overrides for default cluster domain name. + type: string maxP2PExternalAddresses: description: |- Max number of external p2p services to create for CometBFT peer exchange. @@ -5686,6 +5704,11 @@ spec: description: Overrides for all P2P services that need external addresses. properties: + clusterIP: + description: |- + Setting this to "None" makes a "headless service" (no virtual IP), which is useful when direct endpoint connections are preferred and proxying is not required. + If not set, defaults to "". + type: string externalTrafficPolicy: description: |- Sets endpoint and routing behavior. @@ -5727,6 +5750,11 @@ spec: rpcTemplate: description: Overrides for the single RPC service. properties: + clusterIP: + description: |- + Setting this to "None" makes a "headless service" (no virtual IP), which is useful when direct endpoint connections are preferred and proxying is not required. + If not set, defaults to "". + type: string externalTrafficPolicy: description: |- Sets endpoint and routing behavior. diff --git a/config/samples/cosmos_v1_cosmosfullnode_penumbra.yaml b/config/samples/cosmos_v1_cosmosfullnode_penumbra.yaml new file mode 100644 index 00000000..e1d3f536 --- /dev/null +++ b/config/samples/cosmos_v1_cosmosfullnode_penumbra.yaml @@ -0,0 +1,143 @@ +# Example Penumbra Sentry configuration +# 3 sentries, 1 per worker node +apiVersion: cosmos.strange.love/v1 +kind: CosmosFullNode +metadata: + name: penumbra-mainnet-sentry +spec: + #type: Sentry + type: FullNode + replicas: 3 + chain: + chainID: penumbra-1 + network: mainnet + versions: + - height: 0 + image: ghcr.io/strangelove-ventures/heighliner/cometbft:v0.37.9 # TODO UPDATE ME FOR STAGED UPGRADES + containers: + pd: ghcr.io/strangelove-ventures/heighliner/penumbra:v0.80.0 # TODO UPDATE ME FOR STAGED UPGRADES + - height: 2 + image: ghcr.io/strangelove-ventures/heighliner/cometbft:v0.37.9 + containers: + pd: ghcr.io/strangelove-ventures/heighliner/penumbra:v0.79.1 + - height: 501975 + image: ghcr.io/strangelove-ventures/heighliner/cometbft:v0.37.9 + containers: + pd: ghcr.io/strangelove-ventures/heighliner/penumbra:v0.80.0 + # Also apply latest image for height 0 for upgrades since they reset the Comet DB. (L16-L19) + config: + maxInboundPeers: 20 + maxOutboundPeers: 20 + overrides: |- + moniker = "strangelove" + fast_sync = true + + [consensus] + timeout_commit = "5000ms" + + [fastsync] + version = "v0" + + [mempool] + max_tx_bytes = 30720 + max_txs_bytes = 10485760 + seeds: c28827cb96c14c905b127b92065a3fb4cd77d7f6@seeds.whispernode.com:21956,20e1000e88125698264454a884812746c2eb4807@seeds.lavenderfive.com:21956 + peers: 7ae6236905eb6a06d9f27e22204d4c49d4e36d4f@108.21.128.181:26656,76a0f3a7dbc735bd799a8630dfe21ef932816ba3@159.89.254.147:26656,262ef06f71446d6fac6461ea421852c9d9f50006@159.203.52.181:26656,06516a3ef6ca69085c174298864f6abad076e01d@15.204.65.192:26656,9546d20499be3cf7849621faebb3f1e4b0ab0392@164.92.120.11:26656,f90a0a85b976b9bdaf05a871083e702402621fea@160.202.131.247:26656,d4a31f4c0267d668e8cb0d9b6dfa15c860d82376@160.202.131.221:26656,d236fb98aa91f9a3dca8db6403a03923bb510048@65.21.192.115:21956 + genesisScript: echo "No need for genesis" + addrbookScript: echo "No need for address book" + skipInvariants: false + binary: cometbft + + podTemplate: + affinity: + podAntiAffinity: + # One sentry per node + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/name: penumbra-mainnet-sentry + topologyKey: kubernetes.io/hostname + initContainers: + - name: chain-init + command: + - sh + - -c + - | + set -eu + if [ ! -d "$CHAIN_HOME/data" ]; then + echo "Initializing chain..." + cometbft init --home "$CHAIN_HOME" + else + echo "Skipping chain init; already initialized." + fi + + echo "Initializing into tmp dir for downstream processing..." + cometbft init --home "$HOME/.tmp" + volumeMounts: + - mountPath: /home/operator/.tmp + name: vol-tmp + - name: pd-move + image: ghcr.io/strangelove-ventures/infra-toolkit:v0.1.7 + command: + - sh + - -c + - | + export HOME=/home/operator/cosmos + NODE0=$HOME/.penumbra/network_data/node0 + mkdir $HOME/pd || echo "Already created pd dir" + + rsync -Iar --remove-source-files $NODE0/cometbft/* $HOME && rm -rf $NODE0/cometbft || echo "Already moved cometbft data" + rsync -Iar --remove-source-files $NODE0/pd $HOME && rm -rf $NODE0/pd || echo "Already moved pd data" + rsync -Iar --remove-source-files $HOME/cometbft/* $HOME && rm -rf $HOME/cometbft || echo "Already moved polkachu snapshot data" + volumeMounts: + - mountPath: /home/operator/cosmos + name: vol-chain-home + containers: + - name: pd + command: + - sh + - -c + - | + export HOME=/home/operator/cosmos + pd migrate --home $HOME/pd --comet-home $HOME + + pd start --home $HOME/pd + volumeMounts: + - mountPath: /home/operator/cosmos + name: vol-chain-home + ports: + - name: abci + containerPort: 26658 + protocol: TCP + - name: grpc + containerPort: 8080 + protocol: TCP + + probes: + # Disable liveness and readiness probes for sentries + strategy: None + resources: + requests: + cpu: 4000m + memory: 10Gi + limits: + memory: 64Gi + selfHeal: + heightDriftMitigation: + threshold: 10 + pvcAutoScale: + increaseQuantity: 10% + maxSize: 5Ti + usedSpacePercentage: 75 + service: + # Create a kubernetes NodePort service for the P2P port on each sentry + maxP2PExternalAddresses: 3 + p2pTemplate: + type: NodePort + volumeClaimTemplate: + resources: + requests: + # Initial storage size for the PVC, needs to be enough for snapshot restore + storage: 30Gi + # Storage class for the PVC, will use default storage class if not specified + storageClassName: topolvm-provisioner-thin-striped diff --git a/go.mod b/go.mod index 2b7060fb..91f2e873 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/strangelove-ventures/cosmos-operator -go 1.20 +go 1.23.2 require ( cosmossdk.io/log v1.2.1 @@ -14,7 +14,7 @@ require ( github.com/pkg/profile v1.7.0 github.com/robfig/cron/v3 v3.0.1 github.com/samber/lo v1.38.1 - github.com/spf13/cobra v1.7.0 + github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.16.0 github.com/stretchr/testify v1.8.4 go.uber.org/goleak v1.2.1 @@ -114,18 +114,18 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tidwall/btree v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878 // indirect google.golang.org/grpc v1.57.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index fc3eb68f..9c10f55a 100644 --- a/go.sum +++ b/go.sum @@ -85,7 +85,9 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= +github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -103,6 +105,7 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/cockroachdb/errors v1.10.0 h1:lfxS8zZz1+OjtV4MtNWgboi/W5tyLEB6VQZBXN+0VUU= github.com/cockroachdb/errors v1.10.0/go.mod h1:lknhIsEVQ9Ss/qKDBQS/UqFSvPQjOwNq2qyKAxtHRqE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= @@ -122,12 +125,13 @@ github.com/cosmos/iavl v1.0.0-rc.1 h1:5+73BEWW1gZOIUJKlk/1fpD4lOqqeFBA8KuV+NpkCp github.com/cosmos/iavl v1.0.0-rc.1/go.mod h1:CmTGqMnRnucjxbjduneZXT+0vPgNElYvdefjX2q9tYc= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= @@ -144,12 +148,14 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= @@ -159,6 +165,7 @@ github.com/getsentry/sentry-go v0.21.0 h1:c9l5F1nPF30JIppulk4veau90PK6Smu3abgVtV github.com/getsentry/sentry-go v0.21.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -203,6 +210,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -278,6 +286,7 @@ github.com/hashicorp/go-metrics v0.5.1/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAO github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= @@ -361,11 +370,13 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= +github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= +github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= @@ -376,6 +387,7 @@ github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCr github.com/petermattis/goid v0.0.0-20221215004737-a150e88a970d h1:htwtWgtQo8YS6JFWWi2DNgY0RwSGJ1ruMoxY6CUUclk= github.com/petermattis/goid v0.0.0-20221215004737-a150e88a970d/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -429,8 +441,8 @@ github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -495,8 +507,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -574,8 +586,8 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -654,12 +666,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -669,8 +681,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -835,13 +847,14 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= @@ -866,6 +879,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= +gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/fullnode/build_pods.go b/internal/fullnode/build_pods.go index f86371c9..8b63aec3 100644 --- a/internal/fullnode/build_pods.go +++ b/internal/fullnode/build_pods.go @@ -38,6 +38,28 @@ func BuildPods(crd *cosmosv1.CosmosFullNode, cksums ConfigChecksums) ([]diff.Res return pods, nil } +func setChainContainerImages(pod *corev1.Pod, v *cosmosv1.ChainVersion) { + setChainContainerImage(pod, v.Image) + + for name, image := range v.InitContainers { + for i := range pod.Spec.InitContainers { + if pod.Spec.InitContainers[i].Name == name { + pod.Spec.InitContainers[i].Image = image + break + } + } + } + + for name, image := range v.Containers { + for i := range pod.Spec.Containers { + if pod.Spec.Containers[i].Name == name { + pod.Spec.Containers[i].Image = image + break + } + } + } +} + func setChainContainerImage(pod *corev1.Pod, image string) { for i := range pod.Spec.Containers { if pod.Spec.Containers[i].Name == mainContainer { @@ -45,6 +67,7 @@ func setChainContainerImage(pod *corev1.Pod, image string) { break } } + for i := range pod.Spec.InitContainers { if pod.Spec.InitContainers[i].Name == chainInitContainer { pod.Spec.InitContainers[i].Image = image diff --git a/internal/fullnode/peer_collector.go b/internal/fullnode/peer_collector.go index 75426d50..37c27c3a 100644 --- a/internal/fullnode/peer_collector.go +++ b/internal/fullnode/peer_collector.go @@ -105,6 +105,11 @@ func NewPeerCollector(client Getter) *PeerCollector { // Collect peer information given the crd. func (c PeerCollector) Collect(ctx context.Context, crd *cosmosv1.CosmosFullNode) (Peers, kube.ReconcileError) { peers := make(Peers) + + clusterDomain := "cluster.local" + if crd.Spec.Service.ClusterDomain != nil { + clusterDomain = *crd.Spec.Service.ClusterDomain + } for i := int32(0); i < crd.Spec.Replicas; i++ { secretName := nodeKeySecretName(crd, i) var secret corev1.Secret @@ -121,7 +126,7 @@ func (c PeerCollector) Collect(ctx context.Context, crd *cosmosv1.CosmosFullNode svcName := p2pServiceName(crd, i) peers[c.objectKey(crd, i)] = Peer{ NodeID: nodeKey.ID(), - PrivateAddress: fmt.Sprintf("%s.%s.svc.cluster.local:%d", svcName, secret.Namespace, p2pPort), + PrivateAddress: fmt.Sprintf("%s.%s.svc.%s:%d", svcName, secret.Namespace, clusterDomain, p2pPort), } if err := c.addExternalAddress(ctx, peers, crd, i); err != nil { return nil, kube.TransientError(err) diff --git a/internal/fullnode/pod_builder.go b/internal/fullnode/pod_builder.go index 6776e55b..92ba5c2a 100644 --- a/internal/fullnode/pod_builder.go +++ b/internal/fullnode/pod_builder.go @@ -159,6 +159,10 @@ func podReadinessProbes(crd *cosmosv1.CosmosFullNode) []*corev1.Probe { FailureThreshold: 5, } + if crd.Spec.PodTemplate.Probes.Strategy == cosmosv1.FullNodeProbeStrategyReachable { + return []*corev1.Probe{mainProbe, nil} + } + sidecarProbe := &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{ @@ -181,22 +185,28 @@ func podReadinessProbes(crd *cosmosv1.CosmosFullNode) []*corev1.Probe { func (b PodBuilder) Build() (*corev1.Pod, error) { pod := b.pod.DeepCopy() + if err := kube.ApplyStrategicMergePatch(pod, podPatch(b.crd)); err != nil { + return nil, err + } + if len(b.crd.Spec.ChainSpec.Versions) > 0 { instanceHeight := uint64(0) if height, ok := b.crd.Status.Height[pod.Name]; ok { instanceHeight = height } - var image string - for _, version := range b.crd.Spec.ChainSpec.Versions { - if instanceHeight < version.UpgradeHeight { + var vrs *cosmosv1.ChainVersion + for _, v := range b.crd.Spec.ChainSpec.Versions { + v := v + if instanceHeight < v.UpgradeHeight { break } - image = version.Image + vrs = &v } - if image != "" { - setChainContainerImage(pod, image) + if vrs != nil { + setChainContainerImages(pod, vrs) } } + if o, ok := b.crd.Spec.InstanceOverrides[pod.Name]; ok { if o.DisableStrategy != nil { return nil, nil @@ -206,10 +216,6 @@ func (b PodBuilder) Build() (*corev1.Pod, error) { } } - if err := kube.ApplyStrategicMergePatch(pod, podPatch(b.crd)); err != nil { - return nil, err - } - kube.NormalizeMetadata(&pod.ObjectMeta) return pod, nil } @@ -310,10 +316,11 @@ func (b PodBuilder) WithOrdinal(ordinal int32) PodBuilder { } const ( - workDir = "/home/operator" - tmpDir = workDir + "/.tmp" - tmpConfigDir = workDir + "/.config" - infraToolImage = "ghcr.io/strangelove-ventures/infra-toolkit:v0.0.1" + workDir = "/home/operator" + tmpDir = workDir + "/.tmp" + tmpConfigDir = workDir + "/.config" + infraToolImage = "ghcr.io/strangelove-ventures/infra-toolkit" + infraToolVersion = "v0.1.6" // Necessary for statesync systemTmpDir = "/tmp" @@ -339,6 +346,10 @@ func envVars(crd *cosmosv1.CosmosFullNode) []corev1.EnvVar { } } +func resolveInfraToolImage() string { + return fmt.Sprintf("%s:%s", infraToolImage, infraToolVersion) +} + func initContainers(crd *cosmosv1.CosmosFullNode, moniker string) []corev1.Container { tpl := crd.Spec.PodTemplate binary := crd.Spec.ChainSpec.Binary @@ -353,7 +364,7 @@ func initContainers(crd *cosmosv1.CosmosFullNode, moniker string) []corev1.Conta required := []corev1.Container{ { Name: "clean-init", - Image: infraToolImage, + Image: resolveInfraToolImage(), Command: []string{"sh"}, Args: []string{"-c", `rm -rf "$HOME/.tmp/*"`}, Env: env, @@ -385,7 +396,7 @@ echo "Initializing into tmp dir for downstream processing..." { Name: "genesis-init", - Image: infraToolImage, + Image: resolveInfraToolImage(), Command: []string{genesisCmd}, Args: genesisArgs, Env: env, @@ -394,7 +405,7 @@ echo "Initializing into tmp dir for downstream processing..." }, { Name: "addrbook-init", - Image: infraToolImage, + Image: resolveInfraToolImage(), Command: []string{addrbookCmd}, Args: addrbookArgs, Env: env, @@ -403,7 +414,7 @@ echo "Initializing into tmp dir for downstream processing..." }, { Name: "config-merge", - Image: infraToolImage, + Image: resolveInfraToolImage(), Command: []string{"sh"}, Args: []string{"-c", ` @@ -420,8 +431,13 @@ rm -rf "$CONFIG_DIR/node_key.json" echo "Merging config..." set -x -config-merge -f toml "$TMP_DIR/config.toml" "$OVERLAY_DIR/config-overlay.toml" > "$CONFIG_DIR/config.toml" -config-merge -f toml "$TMP_DIR/app.toml" "$OVERLAY_DIR/app-overlay.toml" > "$CONFIG_DIR/app.toml" + +if [ -f "$TMP_DIR/config.toml" ]; then + config-merge -f toml "$TMP_DIR/config.toml" "$OVERLAY_DIR/config-overlay.toml" > "$CONFIG_DIR/config.toml" +fi +if [ -f "$TMP_DIR/app.toml" ]; then + config-merge -f toml "$TMP_DIR/app.toml" "$OVERLAY_DIR/app-overlay.toml" > "$CONFIG_DIR/app.toml" +fi `, }, Env: env, @@ -434,7 +450,7 @@ config-merge -f toml "$TMP_DIR/app.toml" "$OVERLAY_DIR/app-overlay.toml" > "$CON cmd, args := DownloadSnapshotCommand(crd.Spec.ChainSpec) required = append(required, corev1.Container{ Name: "snapshot-restore", - Image: infraToolImage, + Image: resolveInfraToolImage(), Command: []string{cmd}, Args: args, Env: env, diff --git a/internal/fullnode/pod_builder_test.go b/internal/fullnode/pod_builder_test.go index bf9285ed..bea97424 100644 --- a/internal/fullnode/pod_builder_test.go +++ b/internal/fullnode/pod_builder_test.go @@ -266,12 +266,12 @@ func TestPodBuilder(t *testing.T) { require.Len(t, lo.Map(pod.Spec.InitContainers, func(c corev1.Container, _ int) string { return c.Name }), 7) wantInitImages := []string{ - "ghcr.io/strangelove-ventures/infra-toolkit:v0.0.1", + "ghcr.io/strangelove-ventures/infra-toolkit:v0.1.6", "main-image:v1.2.3", - "ghcr.io/strangelove-ventures/infra-toolkit:v0.0.1", - "ghcr.io/strangelove-ventures/infra-toolkit:v0.0.1", - "ghcr.io/strangelove-ventures/infra-toolkit:v0.0.1", - "ghcr.io/strangelove-ventures/infra-toolkit:v0.0.1", + "ghcr.io/strangelove-ventures/infra-toolkit:v0.1.6", + "ghcr.io/strangelove-ventures/infra-toolkit:v0.1.6", + "ghcr.io/strangelove-ventures/infra-toolkit:v0.1.6", + "ghcr.io/strangelove-ventures/infra-toolkit:v0.1.6", "ghcr.io/strangelove-ventures/cosmos-operator:latest", } require.Equal(t, wantInitImages, lo.Map(pod.Spec.InitContainers, func(c corev1.Container, _ int) string { @@ -548,6 +548,24 @@ gaiad start --home /home/operator/cosmos` sidecar := pod.Spec.Containers[1] require.Equal(t, "healthcheck", sidecar.Name) require.Nil(t, sidecar.ReadinessProbe) + + crd.Spec.PodTemplate.Probes = cosmosv1.FullNodeProbesSpec{Strategy: cosmosv1.FullNodeProbeStrategyReachable} + + builder = NewPodBuilder(&crd) + pod, err = builder.WithOrdinal(1).Build() + require.NoError(t, err) + + require.NotNilf(t, pod.Spec.Containers[0].ReadinessProbe, "container 0") + require.Nilf(t, pod.Spec.Containers[1].ReadinessProbe, "container 1") + + crd.Spec.PodTemplate.Probes = cosmosv1.FullNodeProbesSpec{Strategy: cosmosv1.FullNodeProbeStrategyInSync} + + builder = NewPodBuilder(&crd) + pod, err = builder.WithOrdinal(1).Build() + require.NoError(t, err) + + require.NotNilf(t, pod.Spec.Containers[0].ReadinessProbe, "container 0") + require.NotNilf(t, pod.Spec.Containers[1].ReadinessProbe, "container 1") }) t.Run("strategic merge fields", func(t *testing.T) { @@ -606,27 +624,100 @@ gaiad start --home /home/operator/cosmos` } crd.Spec.ChainSpec.Versions = []cosmosv1.ChainVersion{ { - UpgradeHeight: 1, + UpgradeHeight: 0, Image: "image:v1.0.0", }, { UpgradeHeight: 100, Image: "image:v2.0.0", }, + { + UpgradeHeight: 300, + Image: "image:v3.0.0", + InitContainers: map[string]string{ + "chain-init": "chain-init:v3.0.0", + "new-init": "new-init:v3.0.0", + }, + Containers: map[string]string{ + "new-sidecar": "new-sidecar:v3.0.0", + }, + }, + { + UpgradeHeight: 400, + Image: "image:v4.0.0", + }, + } + + crd.Status.Height = map[string]uint64{ + "osmosis-0": 1, + "osmosis-1": 150, + "osmosis-2": 300, } builder := NewPodBuilder(&crd) - pod, err := builder.WithOrdinal(0).Build() + + pod0, err := builder.WithOrdinal(0).Build() require.NoError(t, err) - containers := lo.SliceToMap(pod.Spec.Containers, func(c corev1.Container) (string, corev1.Container) { return c.Name, c }) + containers := lo.SliceToMap(pod0.Spec.Containers, func(c corev1.Container) (string, corev1.Container) { return c.Name, c }) require.ElementsMatch(t, []string{"node", "new-sidecar", "healthcheck", "version-check-interval"}, lo.Keys(containers)) - }) - test.HasTypeLabel(t, func(crd cosmosv1.CosmosFullNode) []map[string]string { - builder := NewPodBuilder(&crd) - pod, _ := builder.WithOrdinal(5).Build() - return []map[string]string{pod.Labels} + initContainers := lo.SliceToMap(pod0.Spec.InitContainers, func(c corev1.Container) (string, corev1.Container) { return c.Name, c }) + require.ElementsMatch(t, []string{"chain-init", "new-init", "genesis-init", "addrbook-init", "config-merge", "version-check", "clean-init"}, lo.Keys(initContainers)) + + require.Equal(t, "osmosis-0", pod0.Name) + + require.Equal(t, "node", pod0.Spec.Containers[0].Name) + require.Equal(t, "image:v1.0.0", pod0.Spec.Containers[0].Image) + + require.Equal(t, "chain-init", pod0.Spec.InitContainers[1].Name) + require.Equal(t, "image:v1.0.0", pod0.Spec.InitContainers[1].Image) + + pod1, err := builder.WithOrdinal(1).Build() + require.NoError(t, err) + + require.Equal(t, "osmosis-1", pod1.Name) + + require.Equal(t, "node", pod1.Spec.Containers[0].Name) + require.Equal(t, "image:v2.0.0", pod1.Spec.Containers[0].Image) + + require.Equal(t, "chain-init", pod1.Spec.InitContainers[1].Name) + require.Equal(t, "image:v2.0.0", pod1.Spec.InitContainers[1].Image) + + pod2, err := builder.WithOrdinal(2).Build() + require.NoError(t, err) + + require.Equal(t, "osmosis-2", pod2.Name) + + require.Equal(t, "node", pod2.Spec.Containers[0].Name) + require.Equal(t, "image:v3.0.0", pod2.Spec.Containers[0].Image) + + require.Equal(t, "new-sidecar", pod2.Spec.Containers[1].Name) + require.Equal(t, "new-sidecar:v3.0.0", pod2.Spec.Containers[1].Image) + + require.Equal(t, "chain-init", pod2.Spec.InitContainers[1].Name) + require.Equal(t, "chain-init:v3.0.0", pod2.Spec.InitContainers[1].Image) + + require.Equal(t, "new-init", pod2.Spec.InitContainers[2].Name) + require.Equal(t, "new-init:v3.0.0", pod2.Spec.InitContainers[2].Image) + + crd.Status.Height["osmosis-2"] = 400 + pod2, err = builder.WithOrdinal(2).Build() + require.NoError(t, err) + + require.Equal(t, "osmosis-2", pod2.Name) + + require.Equal(t, "node", pod2.Spec.Containers[0].Name) + require.Equal(t, "image:v4.0.0", pod2.Spec.Containers[0].Image) + + require.Equal(t, "new-sidecar", pod2.Spec.Containers[1].Name) + require.Equal(t, "new-sidecar:latest", pod2.Spec.Containers[1].Image) + + require.Equal(t, "chain-init", pod2.Spec.InitContainers[1].Name) + require.Equal(t, "image:v4.0.0", pod2.Spec.InitContainers[1].Image) + + require.Equal(t, "new-init", pod2.Spec.InitContainers[2].Name) + require.Equal(t, "new-init:latest", pod2.Spec.InitContainers[2].Image) }) } diff --git a/internal/fullnode/script/download-snapshot.sh b/internal/fullnode/script/download-snapshot.sh index 04ada94c..6ffe13cc 100755 --- a/internal/fullnode/script/download-snapshot.sh +++ b/internal/fullnode/script/download-snapshot.sh @@ -21,8 +21,14 @@ download_lz4() { wget -c -O - "$SNAPSHOT_URL" | lz4 -c -d | tar -x -C "$CHAIN_HOME" } +download_zst() { + echo "Downloading and extracting zst..." + wget -c -O - "$SNAPSHOT_URL" | zstd -d --stdout | tar -x -C "$CHAIN_HOME" +} + case "$SNAPSHOT_URL" in *.tar.lz4) download_lz4 ;; +*.tar.zst) download_zst ;; *.tar.gzip) download_targz ;; *.tar.gz) download_targz ;; *.tar) download_tar ;; diff --git a/internal/fullnode/service_builder.go b/internal/fullnode/service_builder.go index 6f880a0a..2831a12a 100644 --- a/internal/fullnode/service_builder.go +++ b/internal/fullnode/service_builder.go @@ -63,6 +63,7 @@ func BuildServices(crd *cosmosv1.CosmosFullNode) []diff.Resource[*corev1.Service svc.Spec.ExternalTrafficPolicy = *valOrDefault(crd.Spec.Service.P2PTemplate.ExternalTrafficPolicy, ptr(corev1.ServiceExternalTrafficPolicyTypeLocal)) } else { svc.Spec.Type = corev1.ServiceTypeClusterIP + svc.Spec.ClusterIP = *valOrDefault(crd.Spec.Service.P2PTemplate.ClusterIP, ptr("")) } p2ps[i] = diff.Adapt(&svc, i) @@ -131,6 +132,9 @@ func rpcService(crd *cosmosv1.CosmosFullNode) *corev1.Service { if v := rpcSpec.Type; v != nil { svc.Spec.Type = *v } + if v := rpcSpec.ClusterIP; v != nil { + svc.Spec.ClusterIP = *v + } return &svc } diff --git a/internal/kube/labels.go b/internal/kube/labels.go index 30b419b4..006d540f 100644 --- a/internal/kube/labels.go +++ b/internal/kube/labels.go @@ -59,7 +59,7 @@ func NormalizeMetadata(obj *metav1.ObjectMeta) { annots := make(map[string]string) for k, v := range obj.Annotations { - annots[ToLabelKey(k)] = trimMiddle(v, 63) + annots[ToLabelKey(k)] = v } obj.Annotations = annots diff --git a/internal/kube/labels_test.go b/internal/kube/labels_test.go index f06752b1..2b83836a 100644 --- a/internal/kube/labels_test.go +++ b/internal/kube/labels_test.go @@ -86,7 +86,7 @@ func TestNormalizeMetadata(t *testing.T) { obj := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: strings.Repeat(" name ", 500), - Annotations: map[string]string{strings.Repeat("annot-key", 500): strings.Repeat("value", 500), "cloud.google.com/neg": `{"ingress": true}`}, + Annotations: map[string]string{strings.Repeat("annot-key", 500): strings.Repeat("value", 500), "cloud.google.com/neg": `{"ingress": true}`, "long-value": strings.Repeat("value", 500)}, Labels: map[string]string{strings.Repeat("label-key", 500): strings.Repeat("value", 500)}, }, } @@ -95,4 +95,5 @@ func TestNormalizeMetadata(t *testing.T) { test.RequireValidMetadata(t, obj) require.Equal(t, `{"ingress": true}`, obj.Annotations["cloud.google.com/neg"]) + require.Equal(t, strings.Repeat("value", 500), obj.Annotations["long-value"]) } diff --git a/internal/test/metadata.go b/internal/test/metadata.go index b00750ca..6bd0157f 100644 --- a/internal/test/metadata.go +++ b/internal/test/metadata.go @@ -16,8 +16,7 @@ func RequireValidMetadata(t *testing.T, obj client.Object) { require.LessOrEqual(t, len(k), 63) require.LessOrEqual(t, len(v), 63, k) } - for k, v := range obj.GetAnnotations() { + for k := range obj.GetAnnotations() { require.LessOrEqual(t, len(k), 63) - require.LessOrEqual(t, len(v), 63, k) } } diff --git a/local.Dockerfile b/local.Dockerfile index fcb0fd3a..805cff9b 100644 --- a/local.Dockerfile +++ b/local.Dockerfile @@ -1,7 +1,7 @@ # See rocksdb/README.md for instructions to update rocksdb version FROM ghcr.io/strangelove-ventures/rocksdb:v7.10.2 AS rocksdb -FROM golang:1.20-alpine AS builder +FROM golang:1.23-alpine AS builder RUN apk add --update --no-cache\ gcc\ diff --git a/rocksdb/Dockerfile b/rocksdb/Dockerfile index a60a5c45..5bbc4605 100644 --- a/rocksdb/Dockerfile +++ b/rocksdb/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=$BUILDPLATFORM golang:1.20-alpine AS builder +FROM --platform=$BUILDPLATFORM golang:1.23-alpine AS builder RUN apk add --update --no-cache\ gcc\