From 1f482c98b54a14e365c940d0cd8126f82120b56f Mon Sep 17 00:00:00 2001 From: Starttoaster Date: Fri, 13 Sep 2024 22:42:19 -0700 Subject: [PATCH 1/9] Add ChiaNetwork custom resource, API, and controller --- PROJECT | 9 ++ api/v1/chianetwork_types.go | 124 +++++++++++++++ api/v1/chianetwork_types_test.go | 96 ++++++++++++ api/v1/zz_generated.deepcopy.go | 135 +++++++++++++++++ cmd/main.go | 12 +- .../crd/bases/k8s.chia.net_chianetworks.yaml | 142 ++++++++++++++++++ config/crd/kustomization.yaml | 2 + config/rbac/chianetwork_editor_role.yaml | 27 ++++ config/rbac/chianetwork_viewer_role.yaml | 23 +++ config/rbac/kustomization.yaml | 2 + config/rbac/role.yaml | 13 ++ config/samples/chianetwork.yaml | 20 +++ config/samples/kustomization.yaml | 1 + go.mod | 3 +- go.sum | 6 +- internal/controller/chianetwork/assemblers.go | 75 +++++++++ .../controller/chianetwork/assemblers_test.go | 72 +++++++++ internal/controller/chianetwork/controller.go | 112 ++++++++++++++ internal/controller/chianetwork/helpers.go | 20 +++ .../controller/chianetwork/helpers_test.go | 41 +++++ internal/controller/chianetwork_test.go | 85 +++++++++++ .../controller/common/kube/reconcilers.go | 37 +++++ internal/controller/suite_test.go | 8 + internal/metrics/metrics.go | 9 ++ 24 files changed, 1069 insertions(+), 5 deletions(-) create mode 100644 api/v1/chianetwork_types.go create mode 100644 api/v1/chianetwork_types_test.go create mode 100644 config/crd/bases/k8s.chia.net_chianetworks.yaml create mode 100644 config/rbac/chianetwork_editor_role.yaml create mode 100644 config/rbac/chianetwork_viewer_role.yaml create mode 100644 config/samples/chianetwork.yaml create mode 100644 internal/controller/chianetwork/assemblers.go create mode 100644 internal/controller/chianetwork/assemblers_test.go create mode 100644 internal/controller/chianetwork/controller.go create mode 100644 internal/controller/chianetwork/helpers.go create mode 100644 internal/controller/chianetwork/helpers_test.go create mode 100644 internal/controller/chianetwork_test.go diff --git a/PROJECT b/PROJECT index 9c9ccde..cbdb56a 100644 --- a/PROJECT +++ b/PROJECT @@ -89,4 +89,13 @@ resources: kind: ChiaCrawler path: github.com/chia-network/chia-operator/api/v1 version: v1 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: chia.net + group: k8s + kind: ChiaNetwork + path: github.com/chia-network/chia-operator/api/v1 + version: v1 version: "3" diff --git a/api/v1/chianetwork_types.go b/api/v1/chianetwork_types.go new file mode 100644 index 0000000..13f9e2d --- /dev/null +++ b/api/v1/chianetwork_types.go @@ -0,0 +1,124 @@ +/* +Copyright 2024 Chia Network Inc. +*/ + +package v1 + +import ( + "github.com/chia-network/go-chia-libs/pkg/config" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ChiaNetworkSpec defines the desired state of ChiaNetwork +type ChiaNetworkSpec struct { + // NetworkConstants specifies the network constants for this network in the config + // +optional + NetworkConstants *NetworkConstants `json:"constants"` + + // NetworkConfig is the config for the network (address prefix and default full_node port) + // +optional + NetworkConfig *config.NetworkConfig `json:"config"` + + // NetworkName is the name of the selected network in the config, and will also be used as the key for related network config and constants. + // If specified on a ChiaNetwork, and passed to a chia-deploying resource, this will override any value specified for `.spec.chia.network` on that resource. + // This field is optional, and network name will default to the ChiaNetwork name if unspecified. + // +optional + NetworkName *string `json:"networkName,omitempty"` + + // NetworkPort can be set to the port that full_nodes will use in the selected network. + // If specified on a ChiaNetwork, and passed to a chia-deploying resource, this will override any value specified for `.spec.chia.networkPort` on that resource. + // +optional + NetworkPort *uint16 `json:"networkPort,omitempty"` + + // IntroducerAddress can be set to the hostname or IP address of an introducer to set in the chia config. + // No port should be specified, it's taken from the value of the NetworkPort setting. + // If specified on a ChiaNetwork, and passed to a chia-deploying resource, this will override any value specified for `.spec.chia.introducerAddress` on that resource. + // +optional + IntroducerAddress *string `json:"introducerAddress,omitempty"` + + // DNSIntroducerAddress can be set to a hostname to a DNS Introducer server. + // If specified on a ChiaNetwork, and passed to a chia-deploying resource, this will override any value specified for `.spec.chia.dnsIntroducerAddress` on that resource. + // +optional + DNSIntroducerAddress *string `json:"dnsIntroducerAddress,omitempty"` +} + +// NetworkConstants the constants for each network +type NetworkConstants struct { + GenesisChallenge string `json:"GENESIS_CHALLENGE"` + GenesisPreFarmPoolPuzzleHash string `json:"GENESIS_PRE_FARM_POOL_PUZZLE_HASH"` + GenesisPreFarmFarmerPuzzleHash string `json:"GENESIS_PRE_FARM_FARMER_PUZZLE_HASH"` + + // +optional + AggSigMeAdditionalData string `json:"AGG_SIG_ME_ADDITIONAL_DATA,omitempty"` + + // +optional + DifficultyConstantFactor uint64 `json:"DIFFICULTY_CONSTANT_FACTOR,omitempty"` + + // +optional + DifficultyStarting uint64 `json:"DIFFICULTY_STARTING,omitempty"` + + // +optional + EpochBlocks uint32 `json:"EPOCH_BLOCKS,omitempty"` + + // +optional + MempoolBlockBuffer uint8 `json:"MEMPOOL_BLOCK_BUFFER,omitempty"` + + // +optional + MinPlotSize uint8 `json:"MIN_PLOT_SIZE,omitempty"` + + // +optional + NetworkType uint8 `json:"NETWORK_TYPE,omitempty"` + + // +optional + SubSlotItersStarting uint64 `json:"SUB_SLOT_ITERS_STARTING,omitempty"` + + // +optional + HardForkHeight uint32 `json:"HARD_FORK_HEIGHT,omitempty"` + + // +optional + SoftFork4Height uint32 `json:"SOFT_FORK4_HEIGHT,omitempty"` + + // +optional + SoftFork5Height uint32 `json:"SOFT_FORK5_HEIGHT,omitempty"` + + // +optional + PlotFilter128Height uint32 `json:"PLOT_FILTER_128_HEIGHT,omitempty"` + + // +optional + PlotFilter64Height uint32 `json:"PLOT_FILTER_64_HEIGHT,omitempty"` + + // +optional + PlotFilter32Height uint32 `json:"PLOT_FILTER_32_HEIGHT,omitempty"` +} + +// ChiaNetworkStatus defines the observed state of ChiaNetwork +type ChiaNetworkStatus struct { + // Ready says whether the ChiaNetwork is ready, which should be true when the ConfigMap is created + // +kubebuilder:default=false + Ready bool `json:"ready,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status + +// ChiaNetwork is the Schema for the chianetworks API +type ChiaNetwork struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ChiaNetworkSpec `json:"spec,omitempty"` + Status ChiaNetworkStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// ChiaNetworkList contains a list of ChiaNetwork +type ChiaNetworkList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ChiaNetwork `json:"items"` +} + +func init() { + SchemeBuilder.Register(&ChiaNetwork{}, &ChiaNetworkList{}) +} diff --git a/api/v1/chianetwork_types_test.go b/api/v1/chianetwork_types_test.go new file mode 100644 index 0000000..c73657c --- /dev/null +++ b/api/v1/chianetwork_types_test.go @@ -0,0 +1,96 @@ +/* +Copyright 2024 Chia Network Inc. +*/ + +package v1 + +import ( + "testing" + + "github.com/chia-network/go-chia-libs/pkg/config" + + "github.com/google/go-cmp/cmp" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/yaml" +) + +func TestUnmarshalChiaNetwork(t *testing.T) { + yamlData := []byte(` +apiVersion: k8s.chia.net/v1 +kind: ChiaNetwork +metadata: + labels: + app.kubernetes.io/name: chianetwork + app.kubernetes.io/instance: chianetwork-sample + app.kubernetes.io/part-of: chia-operator + app.kubernetes.io/created-by: chia-operator + name: chianetwork-sample +spec: + constants: + MIN_PLOT_SIZE: 18 + GENESIS_CHALLENGE: fb00c54298fc1c149afbf4c8996fb2317ae41e4649b934ca495991b7852b841 + GENESIS_PRE_FARM_POOL_PUZZLE_HASH: asdlsakldlskalskdsasdasdsadsadsadsadsdsadsas + GENESIS_PRE_FARM_FARMER_PUZZLE_HASH: testestestestestestestesrestestestestestest + config: + address_prefix: txch + default_full_node_port: 58444 + networkName: testnetz + networkPort: 58444 + introducerAddress: intro.testnetz.example.com + dnsIntroducerAddress: dnsintro.testnetz.example.com +`) + + var ( + networkConfig = config.NetworkConfig{ + AddressPrefix: "txch", + DefaultFullNodePort: 58444, + } + networkConsts = NetworkConstants{ + MinPlotSize: 18, + GenesisChallenge: "fb00c54298fc1c149afbf4c8996fb2317ae41e4649b934ca495991b7852b841", + GenesisPreFarmPoolPuzzleHash: "asdlsakldlskalskdsasdasdsadsadsadsadsdsadsas", + GenesisPreFarmFarmerPuzzleHash: "testestestestestestestesrestestestestestest", + } + network = "testnetz" + networkPort uint16 = 58444 + introducerAddress = "intro.testnetz.example.com" + dnsIntroducerAddress = "dnsintro.testnetz.example.com" + ) + + expect := ChiaNetwork{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "k8s.chia.net/v1", + Kind: "ChiaNetwork", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "chianetwork-sample", + Labels: map[string]string{ + "app.kubernetes.io/name": "chianetwork", + "app.kubernetes.io/instance": "chianetwork-sample", + "app.kubernetes.io/part-of": "chia-operator", + "app.kubernetes.io/created-by": "chia-operator", + }, + }, + Spec: ChiaNetworkSpec{ + NetworkConfig: &networkConfig, + NetworkConstants: &networkConsts, + NetworkName: &network, + NetworkPort: &networkPort, + IntroducerAddress: &introducerAddress, + DNSIntroducerAddress: &dnsIntroducerAddress, + }, + } + + var actual ChiaNetwork + err := yaml.Unmarshal(yamlData, &actual) + if err != nil { + t.Errorf("Error unmarshaling yaml: %v", err) + return + } + + diff := cmp.Diff(actual, expect) + if diff != "" { + t.Errorf("Unmarshaled struct does not match the expected struct. Actual: %+v\nExpected: %+v\nDiff: %s", actual, expect, diff) + return + } +} diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 326fe62..bf025d3 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -21,6 +21,7 @@ limitations under the License. package v1 import ( + "github.com/chia-network/go-chia-libs/pkg/config" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" runtime "k8s.io/apimachinery/pkg/runtime" @@ -603,6 +604,125 @@ func (in *ChiaIntroducerStatus) DeepCopy() *ChiaIntroducerStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ChiaNetwork) DeepCopyInto(out *ChiaNetwork) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ChiaNetwork. +func (in *ChiaNetwork) DeepCopy() *ChiaNetwork { + if in == nil { + return nil + } + out := new(ChiaNetwork) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ChiaNetwork) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ChiaNetworkList) DeepCopyInto(out *ChiaNetworkList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ChiaNetwork, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ChiaNetworkList. +func (in *ChiaNetworkList) DeepCopy() *ChiaNetworkList { + if in == nil { + return nil + } + out := new(ChiaNetworkList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ChiaNetworkList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ChiaNetworkSpec) DeepCopyInto(out *ChiaNetworkSpec) { + *out = *in + if in.NetworkConstants != nil { + in, out := &in.NetworkConstants, &out.NetworkConstants + *out = new(NetworkConstants) + **out = **in + } + if in.NetworkConfig != nil { + in, out := &in.NetworkConfig, &out.NetworkConfig + *out = new(config.NetworkConfig) + **out = **in + } + if in.NetworkName != nil { + in, out := &in.NetworkName, &out.NetworkName + *out = new(string) + **out = **in + } + if in.NetworkPort != nil { + in, out := &in.NetworkPort, &out.NetworkPort + *out = new(uint16) + **out = **in + } + if in.IntroducerAddress != nil { + in, out := &in.IntroducerAddress, &out.IntroducerAddress + *out = new(string) + **out = **in + } + if in.DNSIntroducerAddress != nil { + in, out := &in.DNSIntroducerAddress, &out.DNSIntroducerAddress + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ChiaNetworkSpec. +func (in *ChiaNetworkSpec) DeepCopy() *ChiaNetworkSpec { + if in == nil { + return nil + } + out := new(ChiaNetworkSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ChiaNetworkStatus) DeepCopyInto(out *ChiaNetworkStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ChiaNetworkStatus. +func (in *ChiaNetworkStatus) DeepCopy() *ChiaNetworkStatus { + if in == nil { + return nil + } + out := new(ChiaNetworkStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ChiaNode) DeepCopyInto(out *ChiaNode) { *out = *in @@ -1314,6 +1434,21 @@ func (in *InitContainer) DeepCopy() *InitContainer { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkConstants) DeepCopyInto(out *NetworkConstants) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkConstants. +func (in *NetworkConstants) DeepCopy() *NetworkConstants { + if in == nil { + return nil + } + out := new(NetworkConstants) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PersistentVolumeClaimConfig) DeepCopyInto(out *PersistentVolumeClaimConfig) { *out = *in diff --git a/cmd/main.go b/cmd/main.go index cd70e9f..a3631e2 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -8,8 +8,6 @@ import ( "flag" "os" - "github.com/chia-network/chia-operator/internal/controller/chiaintroducer" - _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/apimachinery/pkg/runtime" @@ -25,6 +23,8 @@ import ( "github.com/chia-network/chia-operator/internal/controller/chiacrawler" "github.com/chia-network/chia-operator/internal/controller/chiafarmer" "github.com/chia-network/chia-operator/internal/controller/chiaharvester" + "github.com/chia-network/chia-operator/internal/controller/chiaintroducer" + "github.com/chia-network/chia-operator/internal/controller/chianetwork" "github.com/chia-network/chia-operator/internal/controller/chianode" "github.com/chia-network/chia-operator/internal/controller/chiaseeder" "github.com/chia-network/chia-operator/internal/controller/chiatimelord" @@ -156,6 +156,14 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "ChiaCrawler") os.Exit(1) } + if err = (&chianetwork.ChiaNetworkReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Recorder: mgr.GetEventRecorderFor("chianetwork-controller"), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "ChiaNetwork") + os.Exit(1) + } //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/config/crd/bases/k8s.chia.net_chianetworks.yaml b/config/crd/bases/k8s.chia.net_chianetworks.yaml new file mode 100644 index 0000000..d255d13 --- /dev/null +++ b/config/crd/bases/k8s.chia.net_chianetworks.yaml @@ -0,0 +1,142 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.2 + name: chianetworks.k8s.chia.net +spec: + group: k8s.chia.net + names: + kind: ChiaNetwork + listKind: ChiaNetworkList + plural: chianetworks + singular: chianetwork + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ChiaNetwork is the Schema for the chianetworks API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: ChiaNetworkSpec defines the desired state of ChiaNetwork + properties: + config: + description: NetworkConfig is the config for the network (address + prefix and default full_node port) + properties: + address_prefix: + type: string + default_full_node_port: + type: integer + required: + - address_prefix + type: object + constants: + description: NetworkConstants specifies the network constants for + this network in the config + properties: + AGG_SIG_ME_ADDITIONAL_DATA: + type: string + DIFFICULTY_CONSTANT_FACTOR: + format: int64 + type: integer + DIFFICULTY_STARTING: + format: int64 + type: integer + EPOCH_BLOCKS: + format: int32 + type: integer + GENESIS_CHALLENGE: + type: string + GENESIS_PRE_FARM_FARMER_PUZZLE_HASH: + type: string + GENESIS_PRE_FARM_POOL_PUZZLE_HASH: + type: string + HARD_FORK_HEIGHT: + format: int32 + type: integer + MEMPOOL_BLOCK_BUFFER: + type: integer + MIN_PLOT_SIZE: + type: integer + NETWORK_TYPE: + type: integer + PLOT_FILTER_32_HEIGHT: + format: int32 + type: integer + PLOT_FILTER_64_HEIGHT: + format: int32 + type: integer + PLOT_FILTER_128_HEIGHT: + format: int32 + type: integer + SOFT_FORK4_HEIGHT: + format: int32 + type: integer + SOFT_FORK5_HEIGHT: + format: int32 + type: integer + SUB_SLOT_ITERS_STARTING: + format: int64 + type: integer + required: + - GENESIS_CHALLENGE + - GENESIS_PRE_FARM_FARMER_PUZZLE_HASH + - GENESIS_PRE_FARM_POOL_PUZZLE_HASH + type: object + dnsIntroducerAddress: + description: |- + DNSIntroducerAddress can be set to a hostname to a DNS Introducer server. + If specified on a ChiaNetwork, and passed to a chia-deploying resource, this will override any value specified for `.spec.chia.dnsIntroducerAddress` on that resource. + type: string + introducerAddress: + description: |- + IntroducerAddress can be set to the hostname or IP address of an introducer to set in the chia config. + No port should be specified, it's taken from the value of the NetworkPort setting. + If specified on a ChiaNetwork, and passed to a chia-deploying resource, this will override any value specified for `.spec.chia.introducerAddress` on that resource. + type: string + networkName: + description: |- + NetworkName is the name of the selected network in the config, and will also be used as the key for related network config and constants. + If specified on a ChiaNetwork, and passed to a chia-deploying resource, this will override any value specified for `.spec.chia.network` on that resource. + This field is optional, and network name will default to the ChiaNetwork name if unspecified. + type: string + networkPort: + description: |- + NetworkPort can be set to the port that full_nodes will use in the selected network. + If specified on a ChiaNetwork, and passed to a chia-deploying resource, this will override any value specified for `.spec.chia.networkPort` on that resource. + type: integer + type: object + status: + description: ChiaNetworkStatus defines the observed state of ChiaNetwork + properties: + ready: + default: false + description: Ready says whether the ChiaNetwork is ready, which should + be true when the ConfigMap is created + type: boolean + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index d876b9a..d39c9d4 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -11,6 +11,7 @@ resources: - bases/k8s.chia.net_chiaseeders.yaml - bases/k8s.chia.net_chiaintroducers.yaml - bases/k8s.chia.net_chiacrawlers.yaml +- bases/k8s.chia.net_chianetworks.yaml #+kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: @@ -34,6 +35,7 @@ patchesStrategicMerge: #- path: patches/cainjection_in_chiatimelords.yaml #- path: patches/cainjection_in_chiaintroducers.yaml #- path: patches/cainjection_in_chiacrawlers.yaml +#- path: patches/cainjection_in_chianetworks.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/rbac/chianetwork_editor_role.yaml b/config/rbac/chianetwork_editor_role.yaml new file mode 100644 index 0000000..b08f28e --- /dev/null +++ b/config/rbac/chianetwork_editor_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to edit chianetworks. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: chia-operator + app.kubernetes.io/managed-by: kustomize + name: chianetwork-editor-role +rules: +- apiGroups: + - k8s.chia.net + resources: + - chianetworks + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - k8s.chia.net + resources: + - chianetworks/status + verbs: + - get diff --git a/config/rbac/chianetwork_viewer_role.yaml b/config/rbac/chianetwork_viewer_role.yaml new file mode 100644 index 0000000..96c9993 --- /dev/null +++ b/config/rbac/chianetwork_viewer_role.yaml @@ -0,0 +1,23 @@ +# permissions for end users to view chianetworks. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: chia-operator + app.kubernetes.io/managed-by: kustomize + name: chianetwork-viewer-role +rules: +- apiGroups: + - k8s.chia.net + resources: + - chianetworks + verbs: + - get + - list + - watch +- apiGroups: + - k8s.chia.net + resources: + - chianetworks/status + verbs: + - get diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml index 31d0b0e..b2384da 100644 --- a/config/rbac/kustomization.yaml +++ b/config/rbac/kustomization.yaml @@ -13,6 +13,8 @@ resources: # default, aiding admins in cluster management. Those roles are # not used by the Project itself. You can comment the following lines # if you do not want those helpers be installed with your Project. +- chianetwork_editor_role.yaml +- chianetwork_viewer_role.yaml - chiacrawler_editor_role.yaml - chiacrawler_viewer_role.yaml - chiaintroducer_editor_role.yaml diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 8c0cd28..806acc7 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -4,6 +4,16 @@ kind: ClusterRole metadata: name: manager-role rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - create + - get + - list + - update + - watch - apiGroups: - "" resources: @@ -64,6 +74,7 @@ rules: - chiafarmers - chiaharvesters - chiaintroducers + - chianetworks - chianodes - chiaseeders - chiatimelords @@ -84,6 +95,7 @@ rules: - chiafarmers/finalizers - chiaharvesters/finalizers - chiaintroducers/finalizers + - chianetworks/finalizers - chianodes/finalizers - chiaseeders/finalizers - chiatimelords/finalizers @@ -98,6 +110,7 @@ rules: - chiafarmers/status - chiaharvesters/status - chiaintroducers/status + - chianetworks/status - chianodes/status - chiaseeders/status - chiatimelords/status diff --git a/config/samples/chianetwork.yaml b/config/samples/chianetwork.yaml new file mode 100644 index 0000000..c6d29cc --- /dev/null +++ b/config/samples/chianetwork.yaml @@ -0,0 +1,20 @@ +apiVersion: k8s.chia.net/v1 +kind: ChiaNetwork +metadata: + labels: + app.kubernetes.io/name: chia-operator + app.kubernetes.io/managed-by: kustomize + name: chianetwork-sample +spec: + name: testnetz + constants: + MIN_PLOT_SIZE: 18 + GENESIS_CHALLENGE: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + GENESIS_PRE_FARM_POOL_PUZZLE_HASH: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + GENESIS_PRE_FARM_FARMER_PUZZLE_HASH: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + config: + address_prefix: txch + default_full_node_port: 58444 + networkPort: 58444 + introducerAddress: intro.testnetz.cluster.local + dnsIntroducerAddress: dnsintro.testnetz.cluster.local diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 5ad3028..57e7f00 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -2,4 +2,5 @@ resources: - chiaintroducer.yaml - chiacrawler.yaml +- chianetwork.yaml # +kubebuilder:scaffold:manifestskustomizesamples diff --git a/go.mod b/go.mod index 24d8c55..cc42d9d 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/chia-network/chia-operator go 1.22.2 require ( - github.com/chia-network/go-chia-libs v0.13.0 + github.com/chia-network/go-chia-libs v0.14.2 github.com/google/go-cmp v0.6.0 github.com/onsi/ginkgo/v2 v2.20.2 github.com/onsi/gomega v1.34.2 @@ -51,6 +51,7 @@ require ( github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.58.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect + github.com/samber/mo v1.13.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/x448/float16 v0.8.4 // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/go.sum b/go.sum index bd7dd1c..df664f5 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chia-network/go-chia-libs v0.13.0 h1:kjxx4jCxdO/9ep+hX8Cw4JjyAWWVY02GgTPiQxKfxHM= -github.com/chia-network/go-chia-libs v0.13.0/go.mod h1:npTqaFSjTdMxE7hc0LOmWJmWGqcs+IERarK5fDxXk/I= +github.com/chia-network/go-chia-libs v0.14.2 h1:CMXPaxnyxT295T4kDohUzbEltgp6TMsIhFKgZ3qDJwk= +github.com/chia-network/go-chia-libs v0.14.2/go.mod h1:npTqaFSjTdMxE7hc0LOmWJmWGqcs+IERarK5fDxXk/I= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -92,6 +92,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/samber/mo v1.13.0 h1:LB1OwfJMju3a6FjghH+AIvzMG0ZPOzgTWj1qaHs1IQ4= +github.com/samber/mo v1.13.0/go.mod h1:BfkrCPuYzVG3ZljnZB783WIJIGk1mcZr9c9CPf8tAxs= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/internal/controller/chianetwork/assemblers.go b/internal/controller/chianetwork/assemblers.go new file mode 100644 index 0000000..5a3fd9a --- /dev/null +++ b/internal/controller/chianetwork/assemblers.go @@ -0,0 +1,75 @@ +/* +Copyright 2024 Chia Network Inc. +*/ + +package chianetwork + +import ( + "fmt" + "strconv" + + k8schianetv1 "github.com/chia-network/chia-operator/api/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func assembleConfigMap(network k8schianetv1.ChiaNetwork) (corev1.ConfigMap, error) { + data, err := assembleConfigMapData(network) + if err != nil { + return corev1.ConfigMap{}, err + } + + return corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: network.Name, + Namespace: network.Namespace, + }, + Data: data, + }, nil +} + +func assembleConfigMapData(network k8schianetv1.ChiaNetwork) (map[string]string, error) { + var data = make(map[string]string) + + // network env var + if network.Spec.NetworkName != nil && *network.Spec.NetworkName != "" { + data["network"] = *network.Spec.NetworkName + } else { + data["network"] = network.ObjectMeta.Name + } + + // network_port env var + if network.Spec.NetworkPort != nil && *network.Spec.NetworkPort != 0 { + data["network_port"] = strconv.Itoa(int(*network.Spec.NetworkPort)) + } + + // introducer_address env var + if network.Spec.IntroducerAddress != nil && *network.Spec.IntroducerAddress != "" { + data["introducer_address"] = *network.Spec.IntroducerAddress + } + + // dns_introducer_address env var + if network.Spec.DNSIntroducerAddress != nil && *network.Spec.DNSIntroducerAddress != "" { + data["dns_introducer_address"] = *network.Spec.DNSIntroducerAddress + } + + // chia.network_overrides.constants env var + if network.Spec.NetworkConstants != nil { + networkConstants, err := marshalNetworkOverride(data["network"], *network.Spec.NetworkConstants) + if err != nil { + return nil, fmt.Errorf("error marshaling network constants: %v", err) + } + data["chia.network_overrides.constants"] = networkConstants + } + + // chia.network_overrides.config env var + if network.Spec.NetworkConfig != nil { + networkConfig, err := marshalNetworkOverride(data["network"], *network.Spec.NetworkConfig) + if err != nil { + return nil, fmt.Errorf("error marshaling network config: %v", err) + } + data["chia.network_overrides.config"] = networkConfig + } + + return data, nil +} diff --git a/internal/controller/chianetwork/assemblers_test.go b/internal/controller/chianetwork/assemblers_test.go new file mode 100644 index 0000000..426c80d --- /dev/null +++ b/internal/controller/chianetwork/assemblers_test.go @@ -0,0 +1,72 @@ +/* +Copyright 2024 Chia Network Inc. +*/ + +package chianetwork + +import ( + "github.com/chia-network/go-chia-libs/pkg/config" + "strconv" + "testing" + + k8schianetv1 "github.com/chia-network/chia-operator/api/v1" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +var testNetwork = k8schianetv1.ChiaNetwork{ + TypeMeta: metav1.TypeMeta{ + Kind: "ChiaNetwork", + APIVersion: "k8s.chia.net/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "testname", + Namespace: "testnamespace", + }, + Spec: k8schianetv1.ChiaNetworkSpec{ + NetworkConstants: &networkConsts, + NetworkConfig: &networkConfig, + NetworkName: &network, + NetworkPort: &networkPort, + IntroducerAddress: &introducerAddress, + DNSIntroducerAddress: &dnsIntroducerAddress, + }, +} + +var ( + networkConfig = config.NetworkConfig{ + AddressPrefix: "txch", + DefaultFullNodePort: 58444, + } + networkConsts = k8schianetv1.NetworkConstants{ + MinPlotSize: 18, + GenesisChallenge: "fb00c54298fc1c149afbf4c8996fb2317ae41e4649b934ca495991b7852b841", + GenesisPreFarmPoolPuzzleHash: "asdlsakldlskalskdsasdasdsadsadsadsadsdsadsas", + GenesisPreFarmFarmerPuzzleHash: "testestestestestestestesrestestestestestest", + } + network = "testnetz" + networkPort uint16 = 58444 + introducerAddress = "intro.testnetz.example.com" + dnsIntroducerAddress = "dnsintro.testnetz.example.com" +) + +func TestAssembleConfigMap(t *testing.T) { + expected := corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "testname", + Namespace: "testnamespace", + }, + Data: map[string]string{ + "chia.network_overrides.constants": `{"testnetz":{"GENESIS_CHALLENGE":"fb00c54298fc1c149afbf4c8996fb2317ae41e4649b934ca495991b7852b841","GENESIS_PRE_FARM_POOL_PUZZLE_HASH":"asdlsakldlskalskdsasdasdsadsadsadsadsdsadsas","GENESIS_PRE_FARM_FARMER_PUZZLE_HASH":"testestestestestestestesrestestestestestest","MIN_PLOT_SIZE":18}}`, + "chia.network_overrides.config": `{"testnetz":{"address_prefix":"txch","default_full_node_port":58444}}`, + "network": network, + "network_port": strconv.Itoa(int(networkPort)), + "introducer_address": introducerAddress, + "dns_introducer_address": dnsIntroducerAddress, + }, + } + actual, err := assembleConfigMap(testNetwork) + require.NoError(t, err) + require.Equal(t, expected, actual) +} diff --git a/internal/controller/chianetwork/controller.go b/internal/controller/chianetwork/controller.go new file mode 100644 index 0000000..f31cd1f --- /dev/null +++ b/internal/controller/chianetwork/controller.go @@ -0,0 +1,112 @@ +/* +Copyright 2024 Chia Network Inc. +*/ + +package chianetwork + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/chia-network/chia-operator/internal/controller/common/kube" + "github.com/chia-network/chia-operator/internal/metrics" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/client-go/tools/record" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + k8schianetv1 "github.com/chia-network/chia-operator/api/v1" +) + +// ChiaNetworkReconciler reconciles a ChiaNetwork object +type ChiaNetworkReconciler struct { + client.Client + Scheme *runtime.Scheme + Recorder record.EventRecorder +} + +var chianetworks = make(map[string]bool) + +// +kubebuilder:rbac:groups=k8s.chia.net,resources=chianetworks,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=k8s.chia.net,resources=chianetworks/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=k8s.chia.net,resources=chianetworks/finalizers,verbs=update +//+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update + +// Reconcile is invoked on any event to a controlled Kubernetes resource +func (r *ChiaNetworkReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + klog := log.FromContext(ctx) + klog.Info("Running reconciler...") + + // Get the custom resource + var network k8schianetv1.ChiaNetwork + err := r.Get(ctx, req.NamespacedName, &network) + if err != nil && errors.IsNotFound(err) { + // Remove this object from the map for tracking and subtract this CR's total metric by 1 + _, exists := chianetworks[req.NamespacedName.String()] + if exists { + delete(chianetworks, req.NamespacedName.String()) + metrics.ChiaNetworks.Sub(1.0) + } + return ctrl.Result{}, nil + } + if err != nil { + klog.Error(err, "unable to fetch ChiaNetwork resource") + return ctrl.Result{}, err + } + + // Add this object to the tracking map and increment the gauge by 1, if it wasn't already added + _, exists := chianetworks[req.NamespacedName.String()] + if !exists { + chianetworks[req.NamespacedName.String()] = true + metrics.ChiaNetworks.Add(1.0) + } + + // Assemble configmap + configmap, err := assembleConfigMap(network) + if err != nil { + r.Recorder.Event(&network, corev1.EventTypeWarning, "Failed", "Failed to assemble network ConfigMap -- Check operator logs.") + return ctrl.Result{}, fmt.Errorf("encountered error assembling network ConfigMap: %v", err) + } + if err := controllerutil.SetControllerReference(&network, &configmap, r.Scheme); err != nil { + r.Recorder.Event(&network, corev1.EventTypeWarning, "Failed", "Failed to set controller reference on network ConfigMap -- Check operator logs.") + return ctrl.Result{}, fmt.Errorf("encountered error setting controller reference on network ConfigMap: %v", err) + } + + // Reconcile configmap + res, err := kube.ReconcileConfigMap(ctx, r.Client, configmap) + if err != nil { + r.Recorder.Event(&network, corev1.EventTypeWarning, "Failed", "Failed to reconcile network ConfigMap -- Check operator logs.") + return res, fmt.Errorf("encountered error reconciling network ConfigMap: %v", err) + } + + if !network.Status.Ready { + r.Recorder.Event(&network, corev1.EventTypeNormal, "Created", + fmt.Sprintf("Successfully created network ConfigMap in %s/%s", network.Namespace, network.Name)) + + network.Status.Ready = true + err = r.Status().Update(ctx, &network) + if err != nil { + if strings.Contains(err.Error(), kube.ObjectModifiedTryAgainError) { + return ctrl.Result{RequeueAfter: 1 * time.Second}, nil + } + klog.Error(err, "encountered error updating ChiaNetwork status") + return ctrl.Result{}, err + } + } + + return ctrl.Result{}, nil +} + +// SetupWithManager sets up the controller with the Manager. +func (r *ChiaNetworkReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&k8schianetv1.ChiaNetwork{}). + Complete(r) +} diff --git a/internal/controller/chianetwork/helpers.go b/internal/controller/chianetwork/helpers.go new file mode 100644 index 0000000..c6f8a50 --- /dev/null +++ b/internal/controller/chianetwork/helpers.go @@ -0,0 +1,20 @@ +/* +Copyright 2024 Chia Network Inc. +*/ + +package chianetwork + +import "encoding/json" + +func marshalNetworkOverride(name string, data interface{}) (string, error) { + wrappedData := map[string]interface{}{ + name: data, + } + + jsonData, err := json.Marshal(wrappedData) + if err != nil { + return "", err + } + + return string(jsonData), nil +} diff --git a/internal/controller/chianetwork/helpers_test.go b/internal/controller/chianetwork/helpers_test.go new file mode 100644 index 0000000..aa03f40 --- /dev/null +++ b/internal/controller/chianetwork/helpers_test.go @@ -0,0 +1,41 @@ +/* +Copyright 2024 Chia Network Inc. +*/ + +package chianetwork + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func TestMarshalNetworkOverride(t *testing.T) { + tests := []struct { + name string + data interface{} + expected string + wantErr bool + }{ + { + name: "test1", + data: "value1", + expected: `{"test1":"value1"}`, + }, + { + name: "test2", + data: 123, + expected: `{"test2":123}`, + }, + { + name: "test3", + data: map[string]interface{}{"key": "value"}, + expected: `{"test3":{"key":"value"}}`, + }, + } + + for _, test := range tests { + actual, err := marshalNetworkOverride(test.name, test.data) + require.NoError(t, err) + require.Equal(t, test.expected, actual) + } +} diff --git a/internal/controller/chianetwork_test.go b/internal/controller/chianetwork_test.go new file mode 100644 index 0000000..ac88406 --- /dev/null +++ b/internal/controller/chianetwork_test.go @@ -0,0 +1,85 @@ +/* +Copyright 2024 Chia Network Inc. +*/ + +package controller + +import ( + "context" + "github.com/chia-network/go-chia-libs/pkg/config" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + apiv1 "github.com/chia-network/chia-operator/api/v1" +) + +var _ = Describe("ChiaNetwork controller", func() { + var ( + timeout = time.Second * 10 + interval = time.Millisecond * 250 + + networkConfig = config.NetworkConfig{ + AddressPrefix: "txch", + DefaultFullNodePort: 58444, + } + networkConsts = apiv1.NetworkConstants{ + GenesisChallenge: "fb00c54298fc1c149afbf4c8996fb2317ae41e4649b934ca495991b7852b841", + GenesisPreFarmPoolPuzzleHash: "asdlsakldlskalskdsasdasdsadsadsadsadsdsadsas", + GenesisPreFarmFarmerPuzzleHash: "testestestestestestestesrestestestestestest", + } + ) + + Context("When creating ChiaNetwork", func() { + It("should apply to the cluster", func() { + By("By creating a new ChiaNetwork") + ctx := context.Background() + testNetwork := &apiv1.ChiaNetwork{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "k8s.chia.net/v1", + Kind: "ChiaNetwork", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-chianetwork", + Namespace: "default", + }, + Spec: apiv1.ChiaNetworkSpec{ + NetworkConstants: &networkConsts, + NetworkConfig: &networkConfig, + }, + } + expect := &apiv1.ChiaNetwork{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "k8s.chia.net/v1", + Kind: "ChiaNetwork", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-chianetwork", + Namespace: "default", + }, + Spec: apiv1.ChiaNetworkSpec{ + NetworkConstants: &networkConsts, + NetworkConfig: &networkConfig, + }, + } + + // Create ChiaNetwork + Expect(k8sClient.Create(ctx, testNetwork)).Should(Succeed()) + + // Look up the created ChiaNetwork + lookupKey := types.NamespacedName{Name: testNetwork.Name, Namespace: testNetwork.Namespace} + createdChiaNetwork := &apiv1.ChiaNetwork{} + Eventually(func() bool { + err := k8sClient.Get(ctx, lookupKey, createdChiaNetwork) + return err == nil + }, timeout, interval).Should(BeTrue()) + + // Ensure the ChiaNetwork's spec equals the expected spec + Expect(createdChiaNetwork.Spec).Should(Equal(expect.Spec)) + }) + }) +}) diff --git a/internal/controller/common/kube/reconcilers.go b/internal/controller/common/kube/reconcilers.go index b6b7e93..c3e68b2 100644 --- a/internal/controller/common/kube/reconcilers.go +++ b/internal/controller/common/kube/reconcilers.go @@ -298,3 +298,40 @@ func ReconcilePersistentVolumeClaim(ctx context.Context, c client.Client, storag return ctrl.Result{}, nil } + +// ReconcileConfigMap uses the controller-runtime client to determine if the ConfigMap resource needs to be created or updated +func ReconcileConfigMap(ctx context.Context, c client.Client, desired corev1.ConfigMap) (reconcile.Result, error) { + klog := log.FromContext(ctx).WithValues("ConfigMap.Namespace", desired.Namespace, "ConfigMap.Name", desired.Name) + + // Get existing ConfigMap + var current corev1.ConfigMap + err := c.Get(ctx, types.NamespacedName{ + Name: desired.Name, + Namespace: desired.Namespace, + }, ¤t) + if err != nil && errors.IsNotFound(err) { + // ConfigMap not found - create it + klog.Info("Creating new ConfigMap") + if err := c.Create(ctx, &desired); err != nil { + return ctrl.Result{}, fmt.Errorf("error creating ConfigMap \"%s\": %v", desired.Name, err) + } + } else if err != nil { + // Getting ConfigMap failed, but it wasn't because it doesn't exist, can't continue + return ctrl.Result{}, fmt.Errorf("error getting existing ConfigMap \"%s\": %v", desired.Name, err) + } else { + updated := current + + if !reflect.DeepEqual(current.Data, desired.Data) { + updated.Data = desired.Data + + if err := c.Update(ctx, &updated); err != nil { + if strings.Contains(err.Error(), ObjectModifiedTryAgainError) { + return ctrl.Result{RequeueAfter: 1 * time.Second}, nil + } + return ctrl.Result{}, fmt.Errorf("error updating ConfigMap \"%s\": %v", desired.Name, err) + } + } + } + + return ctrl.Result{}, nil +} diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go index 37e096d..6e3ed45 100644 --- a/internal/controller/suite_test.go +++ b/internal/controller/suite_test.go @@ -15,6 +15,7 @@ import ( "github.com/chia-network/chia-operator/internal/controller/chiafarmer" "github.com/chia-network/chia-operator/internal/controller/chiaharvester" "github.com/chia-network/chia-operator/internal/controller/chiaintroducer" + "github.com/chia-network/chia-operator/internal/controller/chianetwork" "github.com/chia-network/chia-operator/internal/controller/chianode" "github.com/chia-network/chia-operator/internal/controller/chiatimelord" "github.com/chia-network/chia-operator/internal/controller/chiawallet" @@ -128,6 +129,13 @@ var _ = BeforeSuite(func() { }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) + err = (&chianetwork.ChiaNetworkReconciler{ + Client: k8sManager.GetClient(), + Scheme: k8sManager.GetScheme(), + Recorder: k8sManager.GetEventRecorderFor("chianetwork-controller"), + }).SetupWithManager(k8sManager) + Expect(err).ToNot(HaveOccurred()) + err = (&chiaseeder.ChiaSeederReconciler{ Client: k8sManager.GetClient(), Scheme: k8sManager.GetScheme(), diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index e974e63..b995f3f 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -54,6 +54,14 @@ var ( }, ) + // ChiaNetworks is a gauge metric that keeps a running total of deployed ChiaNetworks + ChiaNetworks = prometheus.NewGauge( + prometheus.GaugeOpts{ + Name: "chia_operator_chianetwork_total", + Help: "Number of ChiaNetworks objects controlled by this operator", + }, + ) + // ChiaSeeders is a gauge metric that keeps a running total of deployed ChiaSeeders ChiaSeeders = prometheus.NewGauge( prometheus.GaugeOpts{ @@ -87,6 +95,7 @@ func init() { ChiaHarvesters, ChiaIntroducers, ChiaNodes, + ChiaNetworks, ChiaTimelords, ChiaWallets, ) From 13c7b08043f6eabd8f07c931ce7512dde5868dc5 Mon Sep 17 00:00:00 2001 From: Starttoaster Date: Fri, 13 Sep 2024 22:45:04 -0700 Subject: [PATCH 2/9] Add todo for DIFFICULTY_CONSTANT_FACTOR --- api/v1/chianetwork_types.go | 1 + 1 file changed, 1 insertion(+) diff --git a/api/v1/chianetwork_types.go b/api/v1/chianetwork_types.go index 13f9e2d..80fa165 100644 --- a/api/v1/chianetwork_types.go +++ b/api/v1/chianetwork_types.go @@ -51,6 +51,7 @@ type NetworkConstants struct { // +optional AggSigMeAdditionalData string `json:"AGG_SIG_ME_ADDITIONAL_DATA,omitempty"` + // TODO this should actually be a uint128 but it's much more difficult to implement a custom uint128 type with controller-tools generating CRDs yamls // +optional DifficultyConstantFactor uint64 `json:"DIFFICULTY_CONSTANT_FACTOR,omitempty"` From ef67376ef6efb5433e1097e71c06821d00d6307c Mon Sep 17 00:00:00 2001 From: Starttoaster Date: Fri, 13 Sep 2024 22:51:17 -0700 Subject: [PATCH 3/9] Fix lints --- internal/controller/chianetwork/assemblers_test.go | 3 ++- internal/controller/chianetwork/helpers_test.go | 3 ++- internal/controller/chianetwork_test.go | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/controller/chianetwork/assemblers_test.go b/internal/controller/chianetwork/assemblers_test.go index 426c80d..4ce3fc3 100644 --- a/internal/controller/chianetwork/assemblers_test.go +++ b/internal/controller/chianetwork/assemblers_test.go @@ -5,10 +5,11 @@ Copyright 2024 Chia Network Inc. package chianetwork import ( - "github.com/chia-network/go-chia-libs/pkg/config" "strconv" "testing" + "github.com/chia-network/go-chia-libs/pkg/config" + k8schianetv1 "github.com/chia-network/chia-operator/api/v1" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" diff --git a/internal/controller/chianetwork/helpers_test.go b/internal/controller/chianetwork/helpers_test.go index aa03f40..eb6ac28 100644 --- a/internal/controller/chianetwork/helpers_test.go +++ b/internal/controller/chianetwork/helpers_test.go @@ -5,8 +5,9 @@ Copyright 2024 Chia Network Inc. package chianetwork import ( - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) func TestMarshalNetworkOverride(t *testing.T) { diff --git a/internal/controller/chianetwork_test.go b/internal/controller/chianetwork_test.go index ac88406..30597ce 100644 --- a/internal/controller/chianetwork_test.go +++ b/internal/controller/chianetwork_test.go @@ -6,9 +6,10 @@ package controller import ( "context" - "github.com/chia-network/go-chia-libs/pkg/config" "time" + "github.com/chia-network/go-chia-libs/pkg/config" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" From 8ecd522d0ca4e14e62ed90d13eb54ccc80fd0059 Mon Sep 17 00:00:00 2001 From: Starttoaster Date: Fri, 13 Sep 2024 23:12:05 -0700 Subject: [PATCH 4/9] Add doc --- docs/chianetwork.md | 52 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 docs/chianetwork.md diff --git a/docs/chianetwork.md b/docs/chianetwork.md new file mode 100644 index 0000000..52ecaff --- /dev/null +++ b/docs/chianetwork.md @@ -0,0 +1,52 @@ +# ChiaNetwork + +ChiaNetwork resources contain the configuration for a blockchain network (network overrides, network name, network port, etc.) When you deploy a ChiaNetwork resource, you can use it in the spec for your other Chia-deploying resources (ChiaNode, etc.) to contain all of your network-related configuration in one place. + +NOTE: This API uses a new tool for setting complex values in your configuration file. Being a new tool, it may be appropriate to back up your chia configuration file before attaching a ChiaNetwork resource to any of your other resources. + +The most common use-case for ChiaNetwork resources will be for standing up non-default networks. Most people farming mainnet or the default testnet probably won't need to use this. + +Here's an example ChiaNetwork custom resource (CR): + +```yaml +apiVersion: k8s.chia.net/v1 +kind: ChiaNetwork +metadata: + name: testnetz +spec: + constants: + MIN_PLOT_SIZE: 18 + GENESIS_CHALLENGE: "ccd5bb71183532bff220ba46c268991a3ff07eb358e8255a65c30a2dce0e5fbb" + GENESIS_PRE_FARM_POOL_PUZZLE_HASH: "d23da14695a188ae5708dd152263c4db883eb27edeb936178d4d988b8f3ce5fc" + GENESIS_PRE_FARM_FARMER_PUZZLE_HASH: "3d8765d3a597ec1d99663f6c9816d915b9f68613ac94009884c4addaefcce6af" + config: + address_prefix: txch + default_full_node_port: 58444 + networkName: testnetz + networkPort: 58444 + introducerAddress: intro.testnetz.example.com + dnsIntroducerAddress: dnsintro.testnetz.example.com +``` + +- `networkName` is the name of the network. The name of the ChiaNetwork resource will be used if this is left unspecified. +- `networkPort` is the full_node port to use on this network. +- `introducerAddress` is the address to an introducer on this network. +- `dnsIntroducerAddress` is the address to a DNS introducer (seeder) on this network. +- `constants` are the network constants to be defined in the chia config for this network underneath network_overrides. +- `config` is the config to be defined in the chia config for this network underneath network_overrides. + +## Usage + +On a Chia-deploying resource (ChiaNode, ChiaFarmer, etc.) you can specify a ChiaNetwork resource to use for configuration like so: + +```yaml +spec: + chia: + chiaNetwork: "testnetz" +``` + +testnetz is the name of the ChiaNetwork deployed in the same kubernetes namespace. + +## Precedence + +Several of these configuration options are also available on Chia-deploying resources (ChiaNode, ChiaFarmer, etc.) If specified on the ChiaNetwork, the ChiaNetwork resource's fields will take precedence. From de09e9e80890501136ca7c66cfdba7d06c0ac270 Mon Sep 17 00:00:00 2001 From: Starttoaster Date: Sat, 14 Sep 2024 14:17:57 -0700 Subject: [PATCH 5/9] Add common chia env function --- internal/controller/chiacrawler/helpers.go | 92 +---------------- internal/controller/chiafarmer/helpers.go | 94 +----------------- internal/controller/chiaharvester/helpers.go | 92 +---------------- internal/controller/chiaintroducer/helpers.go | 92 +---------------- internal/controller/chianode/helpers.go | 93 +----------------- internal/controller/chiaseeder/helpers.go | 94 +----------------- internal/controller/chiatimelord/helpers.go | 98 +------------------ internal/controller/chiawallet/helpers.go | 94 +----------------- internal/controller/common/kube/helpers.go | 98 ++++++++++++++++++- 9 files changed, 120 insertions(+), 727 deletions(-) diff --git a/internal/controller/chiacrawler/helpers.go b/internal/controller/chiacrawler/helpers.go index 4a5c681..d0a4676 100644 --- a/internal/controller/chiacrawler/helpers.go +++ b/internal/controller/chiacrawler/helpers.go @@ -6,8 +6,6 @@ package chiacrawler import ( "fmt" - "strconv" - "github.com/chia-network/chia-operator/internal/controller/common/kube" corev1 "k8s.io/api/core/v1" @@ -83,100 +81,14 @@ func getChiaEnv(crawler k8schianetv1.ChiaCrawler) []corev1.EnvVar { Value: "crawler", }) - // CHIA_ROOT env var - env = append(env, corev1.EnvVar{ - Name: "CHIA_ROOT", - Value: "/chia-data", - }) - // keys env var -- no keys required for a crawler env = append(env, corev1.EnvVar{ Name: "keys", Value: "none", }) - // ca env var - env = append(env, corev1.EnvVar{ - Name: "ca", - Value: "/chia-ca", - }) - - // testnet env var - if crawler.Spec.ChiaConfig.Testnet != nil && *crawler.Spec.ChiaConfig.Testnet { - env = append(env, corev1.EnvVar{ - Name: "testnet", - Value: "true", - }) - } - - // network env var - if crawler.Spec.ChiaConfig.Network != nil && *crawler.Spec.ChiaConfig.Network != "" { - env = append(env, corev1.EnvVar{ - Name: "network", - Value: *crawler.Spec.ChiaConfig.Network, - }) - } - - // network_port env var - if crawler.Spec.ChiaConfig.NetworkPort != nil && *crawler.Spec.ChiaConfig.NetworkPort != 0 { - env = append(env, corev1.EnvVar{ - Name: "network_port", - Value: strconv.Itoa(int(*crawler.Spec.ChiaConfig.NetworkPort)), - }) - } - - // introducer_address env var - if crawler.Spec.ChiaConfig.IntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "introducer_address", - Value: *crawler.Spec.ChiaConfig.IntroducerAddress, - }) - } - - // dns_introducer_address env var - if crawler.Spec.ChiaConfig.DNSIntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "dns_introducer_address", - Value: *crawler.Spec.ChiaConfig.DNSIntroducerAddress, - }) - } - - // TZ env var - if crawler.Spec.ChiaConfig.Timezone != nil { - env = append(env, corev1.EnvVar{ - Name: "TZ", - Value: *crawler.Spec.ChiaConfig.Timezone, - }) - } - - // log_level env var - if crawler.Spec.ChiaConfig.LogLevel != nil { - env = append(env, corev1.EnvVar{ - Name: "log_level", - Value: *crawler.Spec.ChiaConfig.LogLevel, - }) - } - - // source_ref env var - if crawler.Spec.ChiaConfig.SourceRef != nil && *crawler.Spec.ChiaConfig.SourceRef != "" { - env = append(env, corev1.EnvVar{ - Name: "source_ref", - Value: *crawler.Spec.ChiaConfig.SourceRef, - }) - } - - // self_hostname env var - if crawler.Spec.ChiaConfig.SelfHostname != nil { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: *crawler.Spec.ChiaConfig.SelfHostname, - }) - } else { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: "0.0.0.0", - }) - } + // Add common env + env = append(env, kube.GetCommonChiaEnv(crawler.Spec.ChiaConfig.CommonSpecChia)...) return env } diff --git a/internal/controller/chiafarmer/helpers.go b/internal/controller/chiafarmer/helpers.go index 17caf92..cfacc66 100644 --- a/internal/controller/chiafarmer/helpers.go +++ b/internal/controller/chiafarmer/helpers.go @@ -6,8 +6,6 @@ package chiafarmer import ( "fmt" - "strconv" - "github.com/chia-network/chia-operator/internal/controller/common/kube" k8schianetv1 "github.com/chia-network/chia-operator/api/v1" @@ -88,95 +86,6 @@ func getChiaEnv(farmer k8schianetv1.ChiaFarmer) []corev1.EnvVar { Value: "farmer-only", }) - // CHIA_ROOT env var - env = append(env, corev1.EnvVar{ - Name: "CHIA_ROOT", - Value: "/chia-data", - }) - - // ca env var - env = append(env, corev1.EnvVar{ - Name: "ca", - Value: "/chia-ca", - }) - - // testnet env var - if farmer.Spec.ChiaConfig.Testnet != nil && *farmer.Spec.ChiaConfig.Testnet { - env = append(env, corev1.EnvVar{ - Name: "testnet", - Value: "true", - }) - } - - // network env var - if farmer.Spec.ChiaConfig.Network != nil && *farmer.Spec.ChiaConfig.Network != "" { - env = append(env, corev1.EnvVar{ - Name: "network", - Value: *farmer.Spec.ChiaConfig.Network, - }) - } - - // network_port env var - if farmer.Spec.ChiaConfig.NetworkPort != nil && *farmer.Spec.ChiaConfig.NetworkPort != 0 { - env = append(env, corev1.EnvVar{ - Name: "network_port", - Value: strconv.Itoa(int(*farmer.Spec.ChiaConfig.NetworkPort)), - }) - } - - // introducer_address env var - if farmer.Spec.ChiaConfig.IntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "introducer_address", - Value: *farmer.Spec.ChiaConfig.IntroducerAddress, - }) - } - - // dns_introducer_address env var - if farmer.Spec.ChiaConfig.DNSIntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "dns_introducer_address", - Value: *farmer.Spec.ChiaConfig.DNSIntroducerAddress, - }) - } - - // TZ env var - if farmer.Spec.ChiaConfig.Timezone != nil { - env = append(env, corev1.EnvVar{ - Name: "TZ", - Value: *farmer.Spec.ChiaConfig.Timezone, - }) - } - - // log_level env var - if farmer.Spec.ChiaConfig.LogLevel != nil { - env = append(env, corev1.EnvVar{ - Name: "log_level", - Value: *farmer.Spec.ChiaConfig.LogLevel, - }) - } - - // source_ref env var - if farmer.Spec.ChiaConfig.SourceRef != nil && *farmer.Spec.ChiaConfig.SourceRef != "" { - env = append(env, corev1.EnvVar{ - Name: "source_ref", - Value: *farmer.Spec.ChiaConfig.SourceRef, - }) - } - - // self_hostname env var - if farmer.Spec.ChiaConfig.SelfHostname != nil { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: *farmer.Spec.ChiaConfig.SelfHostname, - }) - } else { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: "0.0.0.0", - }) - } - // keys env var env = append(env, corev1.EnvVar{ Name: "keys", @@ -189,5 +98,8 @@ func getChiaEnv(farmer k8schianetv1.ChiaFarmer) []corev1.EnvVar { Value: farmer.Spec.ChiaConfig.FullNodePeer, }) + // Add common env + env = append(env, kube.GetCommonChiaEnv(farmer.Spec.ChiaConfig.CommonSpecChia)...) + return env } diff --git a/internal/controller/chiaharvester/helpers.go b/internal/controller/chiaharvester/helpers.go index be511c5..bb9b6a4 100644 --- a/internal/controller/chiaharvester/helpers.go +++ b/internal/controller/chiaharvester/helpers.go @@ -148,95 +148,6 @@ func getChiaEnv(harvester k8schianetv1.ChiaHarvester) []corev1.EnvVar { Value: "harvester", }) - // CHIA_ROOT env var - env = append(env, corev1.EnvVar{ - Name: "CHIA_ROOT", - Value: "/chia-data", - }) - - // ca env var - env = append(env, corev1.EnvVar{ - Name: "ca", - Value: "/chia-ca", - }) - - // testnet env var - if harvester.Spec.ChiaConfig.Testnet != nil && *harvester.Spec.ChiaConfig.Testnet { - env = append(env, corev1.EnvVar{ - Name: "testnet", - Value: "true", - }) - } - - // network env var - if harvester.Spec.ChiaConfig.Network != nil && *harvester.Spec.ChiaConfig.Network != "" { - env = append(env, corev1.EnvVar{ - Name: "network", - Value: *harvester.Spec.ChiaConfig.Network, - }) - } - - // network_port env var - if harvester.Spec.ChiaConfig.NetworkPort != nil && *harvester.Spec.ChiaConfig.NetworkPort != 0 { - env = append(env, corev1.EnvVar{ - Name: "network_port", - Value: strconv.Itoa(int(*harvester.Spec.ChiaConfig.NetworkPort)), - }) - } - - // introducer_address env var - if harvester.Spec.ChiaConfig.IntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "introducer_address", - Value: *harvester.Spec.ChiaConfig.IntroducerAddress, - }) - } - - // dns_introducer_address env var - if harvester.Spec.ChiaConfig.DNSIntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "dns_introducer_address", - Value: *harvester.Spec.ChiaConfig.DNSIntroducerAddress, - }) - } - - // TZ env var - if harvester.Spec.ChiaConfig.Timezone != nil { - env = append(env, corev1.EnvVar{ - Name: "TZ", - Value: *harvester.Spec.ChiaConfig.Timezone, - }) - } - - // log_level env var - if harvester.Spec.ChiaConfig.LogLevel != nil { - env = append(env, corev1.EnvVar{ - Name: "log_level", - Value: *harvester.Spec.ChiaConfig.LogLevel, - }) - } - - // source_ref env var - if harvester.Spec.ChiaConfig.SourceRef != nil && *harvester.Spec.ChiaConfig.SourceRef != "" { - env = append(env, corev1.EnvVar{ - Name: "source_ref", - Value: *harvester.Spec.ChiaConfig.SourceRef, - }) - } - - // self_hostname env var - if harvester.Spec.ChiaConfig.SelfHostname != nil { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: *harvester.Spec.ChiaConfig.SelfHostname, - }) - } else { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: "0.0.0.0", - }) - } - // recursive_plot_scan env var -- needed because all plot drives are just mounted as subdirs under `/plots`. // TODO make plot mount paths configurable -- make this var optional env = append(env, corev1.EnvVar{ @@ -254,5 +165,8 @@ func getChiaEnv(harvester k8schianetv1.ChiaHarvester) []corev1.EnvVar { Value: strconv.Itoa(consts.FarmerPort), }) + // Add common env + env = append(env, kube.GetCommonChiaEnv(harvester.Spec.ChiaConfig.CommonSpecChia)...) + return env } diff --git a/internal/controller/chiaintroducer/helpers.go b/internal/controller/chiaintroducer/helpers.go index 7a375d8..ed7ec22 100644 --- a/internal/controller/chiaintroducer/helpers.go +++ b/internal/controller/chiaintroducer/helpers.go @@ -6,8 +6,6 @@ package chiaintroducer import ( "fmt" - "strconv" - "github.com/chia-network/chia-operator/internal/controller/common/kube" corev1 "k8s.io/api/core/v1" @@ -83,100 +81,14 @@ func getChiaEnv(introducer k8schianetv1.ChiaIntroducer) []corev1.EnvVar { Value: "introducer", }) - // CHIA_ROOT env var - env = append(env, corev1.EnvVar{ - Name: "CHIA_ROOT", - Value: "/chia-data", - }) - // keys env var -- no keys required for a introducer env = append(env, corev1.EnvVar{ Name: "keys", Value: "none", }) - // ca env var - env = append(env, corev1.EnvVar{ - Name: "ca", - Value: "/chia-ca", - }) - - // testnet env var - if introducer.Spec.ChiaConfig.Testnet != nil && *introducer.Spec.ChiaConfig.Testnet { - env = append(env, corev1.EnvVar{ - Name: "testnet", - Value: "true", - }) - } - - // network env var - if introducer.Spec.ChiaConfig.Network != nil && *introducer.Spec.ChiaConfig.Network != "" { - env = append(env, corev1.EnvVar{ - Name: "network", - Value: *introducer.Spec.ChiaConfig.Network, - }) - } - - // network_port env var - // network_port env var is required for introducers because it sets the introducer's full_node port in the config - // The default full_node port in the initial config is 8445, which will often need overwriting - env = append(env, corev1.EnvVar{ - Name: "network_port", - Value: strconv.Itoa(int(kube.GetFullNodePort(introducer.Spec.ChiaConfig.CommonSpecChia))), - }) - - // introducer_address env var - if introducer.Spec.ChiaConfig.IntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "introducer_address", - Value: *introducer.Spec.ChiaConfig.IntroducerAddress, - }) - } - - // dns_introducer_address env var - if introducer.Spec.ChiaConfig.DNSIntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "dns_introducer_address", - Value: *introducer.Spec.ChiaConfig.DNSIntroducerAddress, - }) - } - - // TZ env var - if introducer.Spec.ChiaConfig.Timezone != nil { - env = append(env, corev1.EnvVar{ - Name: "TZ", - Value: *introducer.Spec.ChiaConfig.Timezone, - }) - } - - // log_level env var - if introducer.Spec.ChiaConfig.LogLevel != nil { - env = append(env, corev1.EnvVar{ - Name: "log_level", - Value: *introducer.Spec.ChiaConfig.LogLevel, - }) - } - - // source_ref env var - if introducer.Spec.ChiaConfig.SourceRef != nil && *introducer.Spec.ChiaConfig.SourceRef != "" { - env = append(env, corev1.EnvVar{ - Name: "source_ref", - Value: *introducer.Spec.ChiaConfig.SourceRef, - }) - } - - // self_hostname env var - if introducer.Spec.ChiaConfig.SelfHostname != nil { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: *introducer.Spec.ChiaConfig.SelfHostname, - }) - } else { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: "0.0.0.0", - }) - } + // Add common env + env = append(env, kube.GetCommonChiaEnv(introducer.Spec.ChiaConfig.CommonSpecChia)...) return env } diff --git a/internal/controller/chianode/helpers.go b/internal/controller/chianode/helpers.go index 616cd08..988eab6 100644 --- a/internal/controller/chianode/helpers.go +++ b/internal/controller/chianode/helpers.go @@ -8,8 +8,7 @@ import ( "context" "encoding/json" "fmt" - "strconv" - + "github.com/chia-network/chia-operator/internal/controller/common/kube" "sigs.k8s.io/controller-runtime/pkg/log" corev1 "k8s.io/api/core/v1" @@ -130,64 +129,12 @@ func getChiaEnv(ctx context.Context, node k8schianetv1.ChiaNode) []corev1.EnvVar Value: "node", }) - // CHIA_ROOT env var - env = append(env, corev1.EnvVar{ - Name: "CHIA_ROOT", - Value: "/chia-data", - }) - // keys env var -- no keys required for a node env = append(env, corev1.EnvVar{ Name: "keys", Value: "none", }) - // ca env var - env = append(env, corev1.EnvVar{ - Name: "ca", - Value: "/chia-ca", - }) - - // testnet env var - if node.Spec.ChiaConfig.Testnet != nil && *node.Spec.ChiaConfig.Testnet { - env = append(env, corev1.EnvVar{ - Name: "testnet", - Value: "true", - }) - } - - // network env var - if node.Spec.ChiaConfig.Network != nil && *node.Spec.ChiaConfig.Network != "" { - env = append(env, corev1.EnvVar{ - Name: "network", - Value: *node.Spec.ChiaConfig.Network, - }) - } - - // network_port env var - if node.Spec.ChiaConfig.NetworkPort != nil && *node.Spec.ChiaConfig.NetworkPort != 0 { - env = append(env, corev1.EnvVar{ - Name: "network_port", - Value: strconv.Itoa(int(*node.Spec.ChiaConfig.NetworkPort)), - }) - } - - // introducer_address env var - if node.Spec.ChiaConfig.IntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "introducer_address", - Value: *node.Spec.ChiaConfig.IntroducerAddress, - }) - } - - // dns_introducer_address env var - if node.Spec.ChiaConfig.DNSIntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "dns_introducer_address", - Value: *node.Spec.ChiaConfig.DNSIntroducerAddress, - }) - } - // trusted_cidrs env var if node.Spec.ChiaConfig.TrustedCIDRs != nil { // TODO should any special CIDR input checking happen here @@ -202,42 +149,8 @@ func getChiaEnv(ctx context.Context, node k8schianetv1.ChiaNode) []corev1.EnvVar } } - // TZ env var - if node.Spec.ChiaConfig.Timezone != nil { - env = append(env, corev1.EnvVar{ - Name: "TZ", - Value: *node.Spec.ChiaConfig.Timezone, - }) - } - - // log_level env var - if node.Spec.ChiaConfig.LogLevel != nil { - env = append(env, corev1.EnvVar{ - Name: "log_level", - Value: *node.Spec.ChiaConfig.LogLevel, - }) - } - - // source_ref env var - if node.Spec.ChiaConfig.SourceRef != nil && *node.Spec.ChiaConfig.SourceRef != "" { - env = append(env, corev1.EnvVar{ - Name: "source_ref", - Value: *node.Spec.ChiaConfig.SourceRef, - }) - } - - // self_hostname env var - if node.Spec.ChiaConfig.SelfHostname != nil { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: *node.Spec.ChiaConfig.SelfHostname, - }) - } else { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: "0.0.0.0", - }) - } + // Add common env + env = append(env, kube.GetCommonChiaEnv(node.Spec.ChiaConfig.CommonSpecChia)...) return env } diff --git a/internal/controller/chiaseeder/helpers.go b/internal/controller/chiaseeder/helpers.go index 864ed8d..b4f6abb 100644 --- a/internal/controller/chiaseeder/helpers.go +++ b/internal/controller/chiaseeder/helpers.go @@ -6,8 +6,6 @@ package chiaseeder import ( "fmt" - "strconv" - "github.com/chia-network/chia-operator/internal/controller/common/kube" corev1 "k8s.io/api/core/v1" @@ -84,101 +82,12 @@ func getChiaEnv(seeder k8schianetv1.ChiaSeeder) []corev1.EnvVar { Value: "seeder", }) - // CHIA_ROOT env var - env = append(env, corev1.EnvVar{ - Name: "CHIA_ROOT", - Value: "/chia-data", - }) - // keys env var -- no keys required for a seeder env = append(env, corev1.EnvVar{ Name: "keys", Value: "none", }) - // ca env var - env = append(env, corev1.EnvVar{ - Name: "ca", - Value: "/chia-ca", - }) - - // testnet env var - if seeder.Spec.ChiaConfig.Testnet != nil && *seeder.Spec.ChiaConfig.Testnet { - env = append(env, corev1.EnvVar{ - Name: "testnet", - Value: "true", - }) - } - - // network env var - if seeder.Spec.ChiaConfig.Network != nil && *seeder.Spec.ChiaConfig.Network != "" { - env = append(env, corev1.EnvVar{ - Name: "network", - Value: *seeder.Spec.ChiaConfig.Network, - }) - } - - // network_port env var - if seeder.Spec.ChiaConfig.NetworkPort != nil && *seeder.Spec.ChiaConfig.NetworkPort != 0 { - env = append(env, corev1.EnvVar{ - Name: "network_port", - Value: strconv.Itoa(int(*seeder.Spec.ChiaConfig.NetworkPort)), - }) - } - - // introducer_address env var - if seeder.Spec.ChiaConfig.IntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "introducer_address", - Value: *seeder.Spec.ChiaConfig.IntroducerAddress, - }) - } - - // dns_introducer_address env var - if seeder.Spec.ChiaConfig.DNSIntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "dns_introducer_address", - Value: *seeder.Spec.ChiaConfig.DNSIntroducerAddress, - }) - } - - // TZ env var - if seeder.Spec.ChiaConfig.Timezone != nil { - env = append(env, corev1.EnvVar{ - Name: "TZ", - Value: *seeder.Spec.ChiaConfig.Timezone, - }) - } - - // log_level env var - if seeder.Spec.ChiaConfig.LogLevel != nil { - env = append(env, corev1.EnvVar{ - Name: "log_level", - Value: *seeder.Spec.ChiaConfig.LogLevel, - }) - } - - // source_ref env var - if seeder.Spec.ChiaConfig.SourceRef != nil && *seeder.Spec.ChiaConfig.SourceRef != "" { - env = append(env, corev1.EnvVar{ - Name: "source_ref", - Value: *seeder.Spec.ChiaConfig.SourceRef, - }) - } - - // self_hostname env var - if seeder.Spec.ChiaConfig.SelfHostname != nil { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: *seeder.Spec.ChiaConfig.SelfHostname, - }) - } else { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: "0.0.0.0", - }) - } - // seeder_bootstrap_peers env var if seeder.Spec.ChiaConfig.BootstrapPeer != nil { env = append(env, corev1.EnvVar{ @@ -221,6 +130,9 @@ func getChiaEnv(seeder k8schianetv1.ChiaSeeder) []corev1.EnvVar { }) } + // Add common env + env = append(env, kube.GetCommonChiaEnv(seeder.Spec.ChiaConfig.CommonSpecChia)...) + return env } diff --git a/internal/controller/chiatimelord/helpers.go b/internal/controller/chiatimelord/helpers.go index ec17bee..81ed337 100644 --- a/internal/controller/chiatimelord/helpers.go +++ b/internal/controller/chiatimelord/helpers.go @@ -6,8 +6,6 @@ package chiatimelord import ( "fmt" - "strconv" - "github.com/chia-network/chia-operator/internal/controller/common/kube" k8schianetv1 "github.com/chia-network/chia-operator/api/v1" @@ -65,7 +63,7 @@ func getChiaVolumeMounts() []corev1.VolumeMount { } // getChiaEnv retrieves the environment variables from the Chia config struct -func getChiaEnv(tl k8schianetv1.ChiaTimelord) []corev1.EnvVar { +func getChiaEnv(timelord k8schianetv1.ChiaTimelord) []corev1.EnvVar { var env []corev1.EnvVar // service env var @@ -74,100 +72,14 @@ func getChiaEnv(tl k8schianetv1.ChiaTimelord) []corev1.EnvVar { Value: "timelord-only timelord-launcher-only", }) - // CHIA_ROOT env var - env = append(env, corev1.EnvVar{ - Name: "CHIA_ROOT", - Value: "/chia-data", - }) - - // ca env var - env = append(env, corev1.EnvVar{ - Name: "ca", - Value: "/chia-ca", - }) - - // testnet env var - if tl.Spec.ChiaConfig.Testnet != nil && *tl.Spec.ChiaConfig.Testnet { - env = append(env, corev1.EnvVar{ - Name: "testnet", - Value: "true", - }) - } - - // network env var - if tl.Spec.ChiaConfig.Network != nil && *tl.Spec.ChiaConfig.Network != "" { - env = append(env, corev1.EnvVar{ - Name: "network", - Value: *tl.Spec.ChiaConfig.Network, - }) - } - - // network_port env var - if tl.Spec.ChiaConfig.NetworkPort != nil && *tl.Spec.ChiaConfig.NetworkPort != 0 { - env = append(env, corev1.EnvVar{ - Name: "network_port", - Value: strconv.Itoa(int(*tl.Spec.ChiaConfig.NetworkPort)), - }) - } - - // introducer_address env var - if tl.Spec.ChiaConfig.IntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "introducer_address", - Value: *tl.Spec.ChiaConfig.IntroducerAddress, - }) - } - - // dns_introducer_address env var - if tl.Spec.ChiaConfig.DNSIntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "dns_introducer_address", - Value: *tl.Spec.ChiaConfig.DNSIntroducerAddress, - }) - } - - // TZ env var - if tl.Spec.ChiaConfig.Timezone != nil { - env = append(env, corev1.EnvVar{ - Name: "TZ", - Value: *tl.Spec.ChiaConfig.Timezone, - }) - } - - // log_level env var - if tl.Spec.ChiaConfig.LogLevel != nil { - env = append(env, corev1.EnvVar{ - Name: "log_level", - Value: *tl.Spec.ChiaConfig.LogLevel, - }) - } - - // source_ref env var - if tl.Spec.ChiaConfig.SourceRef != nil && *tl.Spec.ChiaConfig.SourceRef != "" { - env = append(env, corev1.EnvVar{ - Name: "source_ref", - Value: *tl.Spec.ChiaConfig.SourceRef, - }) - } - - // self_hostname env var - if tl.Spec.ChiaConfig.SelfHostname != nil { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: *tl.Spec.ChiaConfig.SelfHostname, - }) - } else { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: "0.0.0.0", - }) - } - // node peer env var env = append(env, corev1.EnvVar{ Name: "full_node_peer", - Value: tl.Spec.ChiaConfig.FullNodePeer, + Value: timelord.Spec.ChiaConfig.FullNodePeer, }) + // Add common env + env = append(env, kube.GetCommonChiaEnv(timelord.Spec.ChiaConfig.CommonSpecChia)...) + return env } diff --git a/internal/controller/chiawallet/helpers.go b/internal/controller/chiawallet/helpers.go index f99e25b..22c7bfa 100644 --- a/internal/controller/chiawallet/helpers.go +++ b/internal/controller/chiawallet/helpers.go @@ -8,8 +8,6 @@ import ( "context" "encoding/json" "fmt" - "strconv" - "github.com/chia-network/chia-operator/internal/controller/common/kube" "sigs.k8s.io/controller-runtime/pkg/log" @@ -113,58 +111,6 @@ func getChiaEnv(ctx context.Context, wallet k8schianetv1.ChiaWallet) []corev1.En Value: "wallet", }) - // CHIA_ROOT env var - env = append(env, corev1.EnvVar{ - Name: "CHIA_ROOT", - Value: "/chia-data", - }) - - // ca env var - env = append(env, corev1.EnvVar{ - Name: "ca", - Value: "/chia-ca", - }) - - // testnet env var - if wallet.Spec.ChiaConfig.Testnet != nil && *wallet.Spec.ChiaConfig.Testnet { - env = append(env, corev1.EnvVar{ - Name: "testnet", - Value: "true", - }) - } - - // network env var - if wallet.Spec.ChiaConfig.Network != nil && *wallet.Spec.ChiaConfig.Network != "" { - env = append(env, corev1.EnvVar{ - Name: "network", - Value: *wallet.Spec.ChiaConfig.Network, - }) - } - - // network_port env var - if wallet.Spec.ChiaConfig.NetworkPort != nil && *wallet.Spec.ChiaConfig.NetworkPort != 0 { - env = append(env, corev1.EnvVar{ - Name: "network_port", - Value: strconv.Itoa(int(*wallet.Spec.ChiaConfig.NetworkPort)), - }) - } - - // introducer_address env var - if wallet.Spec.ChiaConfig.IntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "introducer_address", - Value: *wallet.Spec.ChiaConfig.IntroducerAddress, - }) - } - - // dns_introducer_address env var - if wallet.Spec.ChiaConfig.DNSIntroducerAddress != nil { - env = append(env, corev1.EnvVar{ - Name: "dns_introducer_address", - Value: *wallet.Spec.ChiaConfig.DNSIntroducerAddress, - }) - } - // trusted_cidrs env var if wallet.Spec.ChiaConfig.TrustedCIDRs != nil { // TODO should any special CIDR input checking happen here @@ -179,43 +125,6 @@ func getChiaEnv(ctx context.Context, wallet k8schianetv1.ChiaWallet) []corev1.En } } - // TZ env var - if wallet.Spec.ChiaConfig.Timezone != nil { - env = append(env, corev1.EnvVar{ - Name: "TZ", - Value: *wallet.Spec.ChiaConfig.Timezone, - }) - } - - // log_level env var - if wallet.Spec.ChiaConfig.LogLevel != nil { - env = append(env, corev1.EnvVar{ - Name: "log_level", - Value: *wallet.Spec.ChiaConfig.LogLevel, - }) - } - - // source_ref env var - if wallet.Spec.ChiaConfig.SourceRef != nil && *wallet.Spec.ChiaConfig.SourceRef != "" { - env = append(env, corev1.EnvVar{ - Name: "source_ref", - Value: *wallet.Spec.ChiaConfig.SourceRef, - }) - } - - // self_hostname env var - if wallet.Spec.ChiaConfig.SelfHostname != nil { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: *wallet.Spec.ChiaConfig.SelfHostname, - }) - } else { - env = append(env, corev1.EnvVar{ - Name: "self_hostname", - Value: "0.0.0.0", - }) - } - // keys env var env = append(env, corev1.EnvVar{ Name: "keys", @@ -230,5 +139,8 @@ func getChiaEnv(ctx context.Context, wallet k8schianetv1.ChiaWallet) []corev1.En }) } + // Add common env + env = append(env, kube.GetCommonChiaEnv(wallet.Spec.ChiaConfig.CommonSpecChia)...) + return env } diff --git a/internal/controller/common/kube/helpers.go b/internal/controller/common/kube/helpers.go index 054acfb..6e5ba01 100644 --- a/internal/controller/common/kube/helpers.go +++ b/internal/controller/common/kube/helpers.go @@ -8,9 +8,9 @@ import ( k8schianetv1 "github.com/chia-network/chia-operator/api/v1" "github.com/chia-network/chia-operator/internal/controller/common/consts" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/intstr" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "strconv" ) // GetCommonLabels gives some common labels for chia-operator related objects @@ -140,3 +140,97 @@ func GetExistingChiaRootVolume(storage *k8schianetv1.StorageConfig) corev1.Volum }, } } + +// GetCommonChiaEnv retrieves the environment variables from the CommonSpecChia config struct +func GetCommonChiaEnv(commonSpecChia k8schianetv1.CommonSpecChia) []corev1.EnvVar { + var env []corev1.EnvVar + + // CHIA_ROOT env var + env = append(env, corev1.EnvVar{ + Name: "CHIA_ROOT", + Value: "/chia-data", + }) + + // ca env var + env = append(env, corev1.EnvVar{ + Name: "ca", + Value: "/chia-ca", + }) + + // testnet env var + if commonSpecChia.Testnet != nil && *commonSpecChia.Testnet { + env = append(env, corev1.EnvVar{ + Name: "testnet", + Value: "true", + }) + } + + // network env var + if commonSpecChia.Network != nil && *commonSpecChia.Network != "" { + env = append(env, corev1.EnvVar{ + Name: "network", + Value: *commonSpecChia.Network, + }) + } + + // network_port env var + env = append(env, corev1.EnvVar{ + Name: "network_port", + Value: strconv.Itoa(int(GetFullNodePort(commonSpecChia))), + }) + + // introducer_address env var + if commonSpecChia.IntroducerAddress != nil && *commonSpecChia.IntroducerAddress != "" { + env = append(env, corev1.EnvVar{ + Name: "introducer_address", + Value: *commonSpecChia.IntroducerAddress, + }) + } + + // dns_introducer_address env var + if commonSpecChia.DNSIntroducerAddress != nil && *commonSpecChia.DNSIntroducerAddress != "" { + env = append(env, corev1.EnvVar{ + Name: "dns_introducer_address", + Value: *commonSpecChia.DNSIntroducerAddress, + }) + } + + // TZ env var + if commonSpecChia.Timezone != nil && *commonSpecChia.Timezone != "" { + env = append(env, corev1.EnvVar{ + Name: "TZ", + Value: *commonSpecChia.Timezone, + }) + } + + // log_level env var + if commonSpecChia.LogLevel != nil && *commonSpecChia.LogLevel != "" { + env = append(env, corev1.EnvVar{ + Name: "log_level", + Value: *commonSpecChia.LogLevel, + }) + } + + // source_ref env var + if commonSpecChia.SourceRef != nil && *commonSpecChia.SourceRef != "" { + env = append(env, corev1.EnvVar{ + Name: "source_ref", + Value: *commonSpecChia.SourceRef, + }) + } + + // self_hostname env var + if commonSpecChia.SelfHostname != nil && *commonSpecChia.SelfHostname != "" { + env = append(env, corev1.EnvVar{ + Name: "self_hostname", + Value: *commonSpecChia.SelfHostname, + }) + } else { + env = append(env, corev1.EnvVar{ + Name: "self_hostname", + Value: "0.0.0.0", + }) + } + + return env +} From a0ce0a480630b9fe8d34d532b35dc464d6de46e0 Mon Sep 17 00:00:00 2001 From: Starttoaster Date: Sat, 14 Sep 2024 14:18:42 -0700 Subject: [PATCH 6/9] Fix lints --- internal/controller/chiacrawler/helpers.go | 1 + internal/controller/chiafarmer/helpers.go | 1 + internal/controller/chiaintroducer/helpers.go | 1 + internal/controller/chianetwork/controller.go | 2 +- internal/controller/chianode/helpers.go | 1 + internal/controller/chiaseeder/helpers.go | 1 + internal/controller/chiatimelord/helpers.go | 1 + internal/controller/chiawallet/helpers.go | 1 + internal/controller/common/kube/helpers.go | 3 ++- 9 files changed, 10 insertions(+), 2 deletions(-) diff --git a/internal/controller/chiacrawler/helpers.go b/internal/controller/chiacrawler/helpers.go index d0a4676..c484b77 100644 --- a/internal/controller/chiacrawler/helpers.go +++ b/internal/controller/chiacrawler/helpers.go @@ -6,6 +6,7 @@ package chiacrawler import ( "fmt" + "github.com/chia-network/chia-operator/internal/controller/common/kube" corev1 "k8s.io/api/core/v1" diff --git a/internal/controller/chiafarmer/helpers.go b/internal/controller/chiafarmer/helpers.go index cfacc66..2d3757e 100644 --- a/internal/controller/chiafarmer/helpers.go +++ b/internal/controller/chiafarmer/helpers.go @@ -6,6 +6,7 @@ package chiafarmer import ( "fmt" + "github.com/chia-network/chia-operator/internal/controller/common/kube" k8schianetv1 "github.com/chia-network/chia-operator/api/v1" diff --git a/internal/controller/chiaintroducer/helpers.go b/internal/controller/chiaintroducer/helpers.go index ed7ec22..c9971c7 100644 --- a/internal/controller/chiaintroducer/helpers.go +++ b/internal/controller/chiaintroducer/helpers.go @@ -6,6 +6,7 @@ package chiaintroducer import ( "fmt" + "github.com/chia-network/chia-operator/internal/controller/common/kube" corev1 "k8s.io/api/core/v1" diff --git a/internal/controller/chianetwork/controller.go b/internal/controller/chianetwork/controller.go index f31cd1f..ef5d6b2 100644 --- a/internal/controller/chianetwork/controller.go +++ b/internal/controller/chianetwork/controller.go @@ -37,7 +37,7 @@ var chianetworks = make(map[string]bool) // +kubebuilder:rbac:groups=k8s.chia.net,resources=chianetworks,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=k8s.chia.net,resources=chianetworks/status,verbs=get;update;patch // +kubebuilder:rbac:groups=k8s.chia.net,resources=chianetworks/finalizers,verbs=update -//+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update +// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update // Reconcile is invoked on any event to a controlled Kubernetes resource func (r *ChiaNetworkReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { diff --git a/internal/controller/chianode/helpers.go b/internal/controller/chianode/helpers.go index 988eab6..b78eb13 100644 --- a/internal/controller/chianode/helpers.go +++ b/internal/controller/chianode/helpers.go @@ -8,6 +8,7 @@ import ( "context" "encoding/json" "fmt" + "github.com/chia-network/chia-operator/internal/controller/common/kube" "sigs.k8s.io/controller-runtime/pkg/log" diff --git a/internal/controller/chiaseeder/helpers.go b/internal/controller/chiaseeder/helpers.go index b4f6abb..cf607b3 100644 --- a/internal/controller/chiaseeder/helpers.go +++ b/internal/controller/chiaseeder/helpers.go @@ -6,6 +6,7 @@ package chiaseeder import ( "fmt" + "github.com/chia-network/chia-operator/internal/controller/common/kube" corev1 "k8s.io/api/core/v1" diff --git a/internal/controller/chiatimelord/helpers.go b/internal/controller/chiatimelord/helpers.go index 81ed337..e726b66 100644 --- a/internal/controller/chiatimelord/helpers.go +++ b/internal/controller/chiatimelord/helpers.go @@ -6,6 +6,7 @@ package chiatimelord import ( "fmt" + "github.com/chia-network/chia-operator/internal/controller/common/kube" k8schianetv1 "github.com/chia-network/chia-operator/api/v1" diff --git a/internal/controller/chiawallet/helpers.go b/internal/controller/chiawallet/helpers.go index 22c7bfa..6934503 100644 --- a/internal/controller/chiawallet/helpers.go +++ b/internal/controller/chiawallet/helpers.go @@ -8,6 +8,7 @@ import ( "context" "encoding/json" "fmt" + "github.com/chia-network/chia-operator/internal/controller/common/kube" "sigs.k8s.io/controller-runtime/pkg/log" diff --git a/internal/controller/common/kube/helpers.go b/internal/controller/common/kube/helpers.go index 6e5ba01..6ef3491 100644 --- a/internal/controller/common/kube/helpers.go +++ b/internal/controller/common/kube/helpers.go @@ -5,12 +5,13 @@ Copyright 2023 Chia Network Inc. package kube import ( + "strconv" + k8schianetv1 "github.com/chia-network/chia-operator/api/v1" "github.com/chia-network/chia-operator/internal/controller/common/consts" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - "strconv" ) // GetCommonLabels gives some common labels for chia-operator related objects From 7392306ea9a1354ca9ac42d5d12c3554f919a063 Mon Sep 17 00:00:00 2001 From: Starttoaster Date: Sat, 14 Sep 2024 20:00:54 -0700 Subject: [PATCH 7/9] Add ChiaNetwork config option to all chia-deploying resources --- api/v1/chiacommon_types.go | 4 ++ api/v1/zz_generated.deepcopy.go | 5 +++ .../crd/bases/k8s.chia.net_chiacrawlers.yaml | 4 ++ .../crd/bases/k8s.chia.net_chiafarmers.yaml | 4 ++ .../bases/k8s.chia.net_chiaharvesters.yaml | 4 ++ .../bases/k8s.chia.net_chiaintroducers.yaml | 4 ++ config/crd/bases/k8s.chia.net_chianodes.yaml | 4 ++ .../crd/bases/k8s.chia.net_chiaseeders.yaml | 4 ++ .../crd/bases/k8s.chia.net_chiatimelords.yaml | 4 ++ .../crd/bases/k8s.chia.net_chiawallets.yaml | 4 ++ internal/controller/chiacrawler/assemblers.go | 27 ++++++++---- internal/controller/chiacrawler/controller.go | 6 ++- internal/controller/chiacrawler/helpers.go | 13 ++++-- internal/controller/chiafarmer/assemblers.go | 27 ++++++++---- internal/controller/chiafarmer/controller.go | 6 ++- internal/controller/chiafarmer/helpers.go | 13 ++++-- .../controller/chiaharvester/assemblers.go | 27 ++++++++---- .../controller/chiaharvester/controller.go | 6 ++- internal/controller/chiaharvester/helpers.go | 13 ++++-- .../controller/chiaintroducer/assemblers.go | 27 ++++++++---- .../controller/chiaintroducer/controller.go | 6 ++- internal/controller/chiaintroducer/helpers.go | 13 ++++-- internal/controller/chianode/assemblers.go | 26 ++++++++---- internal/controller/chianode/controller.go | 10 +++-- internal/controller/chianode/helpers.go | 12 ++++-- internal/controller/chiaseeder/assemblers.go | 27 ++++++++---- internal/controller/chiaseeder/controller.go | 6 ++- internal/controller/chiaseeder/helpers.go | 13 ++++-- .../controller/chiatimelord/assemblers.go | 27 ++++++++---- .../controller/chiatimelord/controller.go | 6 ++- internal/controller/chiatimelord/helpers.go | 13 ++++-- internal/controller/chiawallet/assemblers.go | 26 ++++++++---- internal/controller/chiawallet/controller.go | 6 ++- internal/controller/chiawallet/helpers.go | 12 ++++-- internal/controller/common/kube/helpers.go | 42 ++++++++++++++++++- 35 files changed, 359 insertions(+), 92 deletions(-) diff --git a/api/v1/chiacommon_types.go b/api/v1/chiacommon_types.go index e25f93b..351bfec 100644 --- a/api/v1/chiacommon_types.go +++ b/api/v1/chiacommon_types.go @@ -84,6 +84,10 @@ type CommonSpecChia struct { // +optional Testnet *bool `json:"testnet,omitempty"` + // ChiaNetwork is the name of a ChiaNetwork resource in the same namespace as this resource + // +optional + ChiaNetwork *string `json:"chiaNetwork,omitempty"` + // Network can be set to a network name in the chia configuration file to switch to // +optional Network *string `json:"network,omitempty"` diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index bf025d3..dd89cd3 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -1322,6 +1322,11 @@ func (in *CommonSpecChia) DeepCopyInto(out *CommonSpecChia) { *out = new(bool) **out = **in } + if in.ChiaNetwork != nil { + in, out := &in.ChiaNetwork, &out.ChiaNetwork + *out = new(string) + **out = **in + } if in.Network != nil { in, out := &in.Network, &out.Network *out = new(string) diff --git a/config/crd/bases/k8s.chia.net_chiacrawlers.yaml b/config/crd/bases/k8s.chia.net_chiacrawlers.yaml index 66c0a1c..eea46b3 100644 --- a/config/crd/bases/k8s.chia.net_chiacrawlers.yaml +++ b/config/crd/bases/k8s.chia.net_chiacrawlers.yaml @@ -1019,6 +1019,10 @@ spec: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for seeders. type: string + chiaNetwork: + description: ChiaNetwork is the name of a ChiaNetwork resource + in the same namespace as this resource + type: string daemonService: description: |- DaemonService defines settings for the daemon Service installed with any Chia component resource. diff --git a/config/crd/bases/k8s.chia.net_chiafarmers.yaml b/config/crd/bases/k8s.chia.net_chiafarmers.yaml index 5931dab..2d5fdca 100644 --- a/config/crd/bases/k8s.chia.net_chiafarmers.yaml +++ b/config/crd/bases/k8s.chia.net_chiafarmers.yaml @@ -1019,6 +1019,10 @@ spec: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for seeders. type: string + chiaNetwork: + description: ChiaNetwork is the name of a ChiaNetwork resource + in the same namespace as this resource + type: string daemonService: description: |- DaemonService defines settings for the daemon Service installed with any Chia component resource. diff --git a/config/crd/bases/k8s.chia.net_chiaharvesters.yaml b/config/crd/bases/k8s.chia.net_chiaharvesters.yaml index 7b0a612..3ccf750 100644 --- a/config/crd/bases/k8s.chia.net_chiaharvesters.yaml +++ b/config/crd/bases/k8s.chia.net_chiaharvesters.yaml @@ -1019,6 +1019,10 @@ spec: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for seeders. type: string + chiaNetwork: + description: ChiaNetwork is the name of a ChiaNetwork resource + in the same namespace as this resource + type: string daemonService: description: |- DaemonService defines settings for the daemon Service installed with any Chia component resource. diff --git a/config/crd/bases/k8s.chia.net_chiaintroducers.yaml b/config/crd/bases/k8s.chia.net_chiaintroducers.yaml index 0a2495f..9f3d385 100644 --- a/config/crd/bases/k8s.chia.net_chiaintroducers.yaml +++ b/config/crd/bases/k8s.chia.net_chiaintroducers.yaml @@ -1019,6 +1019,10 @@ spec: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for introducers. type: string + chiaNetwork: + description: ChiaNetwork is the name of a ChiaNetwork resource + in the same namespace as this resource + type: string daemonService: description: |- DaemonService defines settings for the daemon Service installed with any Chia component resource. diff --git a/config/crd/bases/k8s.chia.net_chianodes.yaml b/config/crd/bases/k8s.chia.net_chianodes.yaml index e8c719a..0f6a340 100644 --- a/config/crd/bases/k8s.chia.net_chianodes.yaml +++ b/config/crd/bases/k8s.chia.net_chianodes.yaml @@ -1019,6 +1019,10 @@ spec: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for seeders. type: string + chiaNetwork: + description: ChiaNetwork is the name of a ChiaNetwork resource + in the same namespace as this resource + type: string daemonService: description: |- DaemonService defines settings for the daemon Service installed with any Chia component resource. diff --git a/config/crd/bases/k8s.chia.net_chiaseeders.yaml b/config/crd/bases/k8s.chia.net_chiaseeders.yaml index 8424740..c0b46bd 100644 --- a/config/crd/bases/k8s.chia.net_chiaseeders.yaml +++ b/config/crd/bases/k8s.chia.net_chiaseeders.yaml @@ -1023,6 +1023,10 @@ spec: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for seeders. type: string + chiaNetwork: + description: ChiaNetwork is the name of a ChiaNetwork resource + in the same namespace as this resource + type: string daemonService: description: |- DaemonService defines settings for the daemon Service installed with any Chia component resource. diff --git a/config/crd/bases/k8s.chia.net_chiatimelords.yaml b/config/crd/bases/k8s.chia.net_chiatimelords.yaml index 3c7886e..a97e533 100644 --- a/config/crd/bases/k8s.chia.net_chiatimelords.yaml +++ b/config/crd/bases/k8s.chia.net_chiatimelords.yaml @@ -1019,6 +1019,10 @@ spec: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for seeders. type: string + chiaNetwork: + description: ChiaNetwork is the name of a ChiaNetwork resource + in the same namespace as this resource + type: string daemonService: description: |- DaemonService defines settings for the daemon Service installed with any Chia component resource. diff --git a/config/crd/bases/k8s.chia.net_chiawallets.yaml b/config/crd/bases/k8s.chia.net_chiawallets.yaml index f73d0f3..87b575d 100644 --- a/config/crd/bases/k8s.chia.net_chiawallets.yaml +++ b/config/crd/bases/k8s.chia.net_chiawallets.yaml @@ -1019,6 +1019,10 @@ spec: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for seeders. type: string + chiaNetwork: + description: ChiaNetwork is the name of a ChiaNetwork resource + in the same namespace as this resource + type: string daemonService: description: |- DaemonService defines settings for the daemon Service installed with any Chia component resource. diff --git a/internal/controller/chiacrawler/assemblers.go b/internal/controller/chiacrawler/assemblers.go index dfe3030..bfc44ef 100644 --- a/internal/controller/chiacrawler/assemblers.go +++ b/internal/controller/chiacrawler/assemblers.go @@ -5,8 +5,11 @@ Copyright 2024 Chia Network Inc. package chiacrawler import ( + "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "k8s.io/apimachinery/pkg/api/resource" appsv1 "k8s.io/api/apps/v1" @@ -235,7 +238,7 @@ func assembleVolumeClaim(crawler k8schianetv1.ChiaCrawler) (*corev1.PersistentVo } // assembleDeployment assembles the crawler Deployment resource for a ChiaCrawler CR -func assembleDeployment(crawler k8schianetv1.ChiaCrawler) appsv1.Deployment { +func assembleDeployment(ctx context.Context, c client.Client, crawler k8schianetv1.ChiaCrawler) (appsv1.Deployment, error) { var deploy = appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf(chiacrawlerNamePattern, crawler.Name), @@ -253,7 +256,6 @@ func assembleDeployment(crawler k8schianetv1.ChiaCrawler) appsv1.Deployment { Annotations: crawler.Spec.AdditionalMetadata.Annotations, }, Spec: corev1.PodSpec{ - Containers: []corev1.Container{assembleChiaContainer(crawler)}, Affinity: crawler.Spec.Affinity, NodeSelector: crawler.Spec.NodeSelector, Volumes: getChiaVolumes(crawler), @@ -262,6 +264,12 @@ func assembleDeployment(crawler k8schianetv1.ChiaCrawler) appsv1.Deployment { }, } + chiaContainer, err := assembleChiaContainer(ctx, c, crawler) + if err != nil { + return appsv1.Deployment{}, err + } + deploy.Spec.Template.Spec.Containers = append(deploy.Spec.Template.Spec.Containers, chiaContainer) + if len(crawler.Spec.InitContainers) != 0 { // Overwrite any volumeMounts specified in init containers. Not currently supported. for _, cont := range crawler.Spec.InitContainers { @@ -274,7 +282,7 @@ func assembleDeployment(crawler k8schianetv1.ChiaCrawler) appsv1.Deployment { // Share chia env if enabled if cont.ShareEnv { - cont.Container.Env = append(cont.Container.Env, getChiaEnv(crawler)...) + cont.Container.Env = append(cont.Container.Env, chiaContainer.Env...) } deploy.Spec.Template.Spec.InitContainers = append(deploy.Spec.Template.Spec.InitContainers, cont.Container) @@ -304,14 +312,13 @@ func assembleDeployment(crawler k8schianetv1.ChiaCrawler) appsv1.Deployment { // TODO add pod affinity, tolerations - return deploy + return deploy, nil } -func assembleChiaContainer(crawler k8schianetv1.ChiaCrawler) corev1.Container { +func assembleChiaContainer(ctx context.Context, c client.Client, crawler k8schianetv1.ChiaCrawler) (corev1.Container, error) { input := kube.AssembleChiaContainerInputs{ Image: crawler.Spec.ChiaConfig.Image, ImagePullPolicy: crawler.Spec.ImagePullPolicy, - Env: getChiaEnv(crawler), Ports: []corev1.ContainerPort{ { Name: "daemon", @@ -332,6 +339,12 @@ func assembleChiaContainer(crawler k8schianetv1.ChiaCrawler) corev1.Container { VolumeMounts: getChiaVolumeMounts(crawler), } + env, err := getChiaEnv(ctx, c, crawler) + if err != nil { + return corev1.Container{}, err + } + input.Env = env + if crawler.Spec.ChiaConfig.SecurityContext != nil { input.SecurityContext = crawler.Spec.ChiaConfig.SecurityContext } @@ -352,7 +365,7 @@ func assembleChiaContainer(crawler k8schianetv1.ChiaCrawler) corev1.Container { input.ResourceRequirements = crawler.Spec.ChiaConfig.Resources } - return kube.AssembleChiaContainer(input) + return kube.AssembleChiaContainer(input), nil } func assembleChiaExporterContainer(crawler k8schianetv1.ChiaCrawler) corev1.Container { diff --git a/internal/controller/chiacrawler/controller.go b/internal/controller/chiacrawler/controller.go index 243cf64..1f4a5f7 100644 --- a/internal/controller/chiacrawler/controller.go +++ b/internal/controller/chiacrawler/controller.go @@ -151,7 +151,11 @@ func (r *ChiaCrawlerReconciler) Reconcile(ctx context.Context, req ctrl.Request) } // Assemble Deployment - deploy := assembleDeployment(crawler) + deploy, err := assembleDeployment(ctx, r.Client, crawler) + if err != nil { + r.Recorder.Event(&crawler, corev1.EventTypeWarning, "Failed", "Failed to assemble crawler Deployment -- Check operator logs.") + return reconcile.Result{}, fmt.Errorf("ChiaCrawlerReconciler ChiaCrawler=%s %v", req.NamespacedName, err) + } if err := controllerutil.SetControllerReference(&crawler, &deploy, r.Scheme); err != nil { r.Recorder.Event(&crawler, corev1.EventTypeWarning, "Failed", "Failed to assemble crawler Deployment -- Check operator logs.") return reconcile.Result{}, fmt.Errorf("ChiaCrawlerReconciler ChiaCrawler=%s %v", req.NamespacedName, err) diff --git a/internal/controller/chiacrawler/helpers.go b/internal/controller/chiacrawler/helpers.go index c484b77..161d17c 100644 --- a/internal/controller/chiacrawler/helpers.go +++ b/internal/controller/chiacrawler/helpers.go @@ -5,8 +5,11 @@ Copyright 2024 Chia Network Inc. package chiacrawler import ( + "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/chia-network/chia-operator/internal/controller/common/kube" corev1 "k8s.io/api/core/v1" @@ -73,7 +76,7 @@ func getChiaVolumeMounts(crawler k8schianetv1.ChiaCrawler) []corev1.VolumeMount } // getChiaEnv retrieves the environment variables from the Chia config struct -func getChiaEnv(crawler k8schianetv1.ChiaCrawler) []corev1.EnvVar { +func getChiaEnv(ctx context.Context, c client.Client, crawler k8schianetv1.ChiaCrawler) ([]corev1.EnvVar, error) { var env []corev1.EnvVar // service env var @@ -89,7 +92,11 @@ func getChiaEnv(crawler k8schianetv1.ChiaCrawler) []corev1.EnvVar { }) // Add common env - env = append(env, kube.GetCommonChiaEnv(crawler.Spec.ChiaConfig.CommonSpecChia)...) + commonEnv, err := kube.GetCommonChiaEnv(ctx, c, crawler.ObjectMeta.Namespace, crawler.Spec.ChiaConfig.CommonSpecChia) + if err != nil { + return env, err + } + env = append(env, commonEnv...) - return env + return env, nil } diff --git a/internal/controller/chiafarmer/assemblers.go b/internal/controller/chiafarmer/assemblers.go index 57e2f04..e04a400 100644 --- a/internal/controller/chiafarmer/assemblers.go +++ b/internal/controller/chiafarmer/assemblers.go @@ -5,8 +5,11 @@ Copyright 2023 Chia Network Inc. package chiafarmer import ( + "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "k8s.io/apimachinery/pkg/api/resource" appsv1 "k8s.io/api/apps/v1" @@ -235,7 +238,7 @@ func assembleVolumeClaim(farmer k8schianetv1.ChiaFarmer) (*corev1.PersistentVolu } // assembleDeployment assembles the farmer Deployment resource for a ChiaFarmer CR -func assembleDeployment(farmer k8schianetv1.ChiaFarmer) appsv1.Deployment { +func assembleDeployment(ctx context.Context, c client.Client, farmer k8schianetv1.ChiaFarmer) (appsv1.Deployment, error) { var deploy = appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf(chiafarmerNamePattern, farmer.Name), @@ -253,7 +256,6 @@ func assembleDeployment(farmer k8schianetv1.ChiaFarmer) appsv1.Deployment { Annotations: farmer.Spec.AdditionalMetadata.Annotations, }, Spec: corev1.PodSpec{ - Containers: []corev1.Container{assembleChiaContainer(farmer)}, Affinity: farmer.Spec.Affinity, NodeSelector: farmer.Spec.NodeSelector, Volumes: getChiaVolumes(farmer), @@ -262,6 +264,12 @@ func assembleDeployment(farmer k8schianetv1.ChiaFarmer) appsv1.Deployment { }, } + chiaContainer, err := assembleChiaContainer(ctx, c, farmer) + if err != nil { + return appsv1.Deployment{}, err + } + deploy.Spec.Template.Spec.Containers = append(deploy.Spec.Template.Spec.Containers, chiaContainer) + if len(farmer.Spec.InitContainers) != 0 { // Overwrite any volumeMounts specified in init containers. Not currently supported. for _, cont := range farmer.Spec.InitContainers { @@ -274,7 +282,7 @@ func assembleDeployment(farmer k8schianetv1.ChiaFarmer) appsv1.Deployment { // Share chia env if enabled if cont.ShareEnv { - cont.Container.Env = append(cont.Container.Env, getChiaEnv(farmer)...) + cont.Container.Env = append(cont.Container.Env, chiaContainer.Env...) } deploy.Spec.Template.Spec.InitContainers = append(deploy.Spec.Template.Spec.InitContainers, cont.Container) @@ -304,14 +312,13 @@ func assembleDeployment(farmer k8schianetv1.ChiaFarmer) appsv1.Deployment { // TODO add pod affinity, tolerations - return deploy + return deploy, nil } -func assembleChiaContainer(farmer k8schianetv1.ChiaFarmer) corev1.Container { +func assembleChiaContainer(ctx context.Context, c client.Client, farmer k8schianetv1.ChiaFarmer) (corev1.Container, error) { input := kube.AssembleChiaContainerInputs{ Image: farmer.Spec.ChiaConfig.Image, ImagePullPolicy: farmer.Spec.ImagePullPolicy, - Env: getChiaEnv(farmer), Ports: []corev1.ContainerPort{ { Name: "daemon", @@ -332,6 +339,12 @@ func assembleChiaContainer(farmer k8schianetv1.ChiaFarmer) corev1.Container { VolumeMounts: getChiaVolumeMounts(), } + env, err := getChiaEnv(ctx, c, farmer) + if err != nil { + return corev1.Container{}, err + } + input.Env = env + if farmer.Spec.ChiaConfig.SecurityContext != nil { input.SecurityContext = farmer.Spec.ChiaConfig.SecurityContext } @@ -352,7 +365,7 @@ func assembleChiaContainer(farmer k8schianetv1.ChiaFarmer) corev1.Container { input.ResourceRequirements = farmer.Spec.ChiaConfig.Resources } - return kube.AssembleChiaContainer(input) + return kube.AssembleChiaContainer(input), nil } func assembleChiaExporterContainer(farmer k8schianetv1.ChiaFarmer) corev1.Container { diff --git a/internal/controller/chiafarmer/controller.go b/internal/controller/chiafarmer/controller.go index e3bfd3a..a70dbd6 100644 --- a/internal/controller/chiafarmer/controller.go +++ b/internal/controller/chiafarmer/controller.go @@ -151,7 +151,11 @@ func (r *ChiaFarmerReconciler) Reconcile(ctx context.Context, req ctrl.Request) } // Assemble Deployment - deploy := assembleDeployment(farmer) + deploy, err := assembleDeployment(ctx, r.Client, farmer) + if err != nil { + r.Recorder.Event(&farmer, corev1.EventTypeWarning, "Failed", "Failed to assemble farmer Deployment -- Check operator logs.") + return reconcile.Result{}, fmt.Errorf("ChiaFarmerReconciler ChiaFarmer=%s %v", req.NamespacedName, err) + } if err := controllerutil.SetControllerReference(&farmer, &deploy, r.Scheme); err != nil { r.Recorder.Event(&farmer, corev1.EventTypeWarning, "Failed", "Failed to assemble farmer Deployment -- Check operator logs.") return reconcile.Result{}, fmt.Errorf("ChiaFarmerReconciler ChiaFarmer=%s %v", req.NamespacedName, err) diff --git a/internal/controller/chiafarmer/helpers.go b/internal/controller/chiafarmer/helpers.go index 2d3757e..6e3b102 100644 --- a/internal/controller/chiafarmer/helpers.go +++ b/internal/controller/chiafarmer/helpers.go @@ -5,8 +5,11 @@ Copyright 2023 Chia Network Inc. package chiafarmer import ( + "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/chia-network/chia-operator/internal/controller/common/kube" k8schianetv1 "github.com/chia-network/chia-operator/api/v1" @@ -78,7 +81,7 @@ func getChiaVolumeMounts() []corev1.VolumeMount { } // getChiaEnv retrieves the environment variables from the Chia config struct -func getChiaEnv(farmer k8schianetv1.ChiaFarmer) []corev1.EnvVar { +func getChiaEnv(ctx context.Context, c client.Client, farmer k8schianetv1.ChiaFarmer) ([]corev1.EnvVar, error) { var env []corev1.EnvVar // service env var @@ -100,7 +103,11 @@ func getChiaEnv(farmer k8schianetv1.ChiaFarmer) []corev1.EnvVar { }) // Add common env - env = append(env, kube.GetCommonChiaEnv(farmer.Spec.ChiaConfig.CommonSpecChia)...) + commonEnv, err := kube.GetCommonChiaEnv(ctx, c, farmer.ObjectMeta.Namespace, farmer.Spec.ChiaConfig.CommonSpecChia) + if err != nil { + return env, err + } + env = append(env, commonEnv...) - return env + return env, nil } diff --git a/internal/controller/chiaharvester/assemblers.go b/internal/controller/chiaharvester/assemblers.go index 6592239..7d746a4 100644 --- a/internal/controller/chiaharvester/assemblers.go +++ b/internal/controller/chiaharvester/assemblers.go @@ -5,8 +5,11 @@ Copyright 2023 Chia Network Inc. package chiaharvester import ( + "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "k8s.io/apimachinery/pkg/api/resource" appsv1 "k8s.io/api/apps/v1" @@ -235,7 +238,7 @@ func assembleVolumeClaim(harvester k8schianetv1.ChiaHarvester) (*corev1.Persiste } // assembleDeployment assembles the harvester Deployment resource for a ChiaHarvester CR -func assembleDeployment(harvester k8schianetv1.ChiaHarvester) appsv1.Deployment { +func assembleDeployment(ctx context.Context, c client.Client, harvester k8schianetv1.ChiaHarvester) (appsv1.Deployment, error) { var deploy = appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf(chiaharvesterNamePattern, harvester.Name), @@ -253,7 +256,6 @@ func assembleDeployment(harvester k8schianetv1.ChiaHarvester) appsv1.Deployment Annotations: harvester.Spec.AdditionalMetadata.Annotations, }, Spec: corev1.PodSpec{ - Containers: []corev1.Container{assembleChiaContainer(harvester)}, Affinity: harvester.Spec.Affinity, NodeSelector: harvester.Spec.NodeSelector, Volumes: getChiaVolumes(harvester), @@ -262,6 +264,12 @@ func assembleDeployment(harvester k8schianetv1.ChiaHarvester) appsv1.Deployment }, } + chiaContainer, err := assembleChiaContainer(ctx, c, harvester) + if err != nil { + return appsv1.Deployment{}, err + } + deploy.Spec.Template.Spec.Containers = append(deploy.Spec.Template.Spec.Containers, chiaContainer) + if len(harvester.Spec.InitContainers) != 0 { // Overwrite any volumeMounts specified in init containers. Not currently supported. for _, cont := range harvester.Spec.InitContainers { @@ -274,7 +282,7 @@ func assembleDeployment(harvester k8schianetv1.ChiaHarvester) appsv1.Deployment // Share chia env if enabled if cont.ShareEnv { - cont.Container.Env = append(cont.Container.Env, getChiaEnv(harvester)...) + cont.Container.Env = append(cont.Container.Env, chiaContainer.Env...) } deploy.Spec.Template.Spec.InitContainers = append(deploy.Spec.Template.Spec.InitContainers, cont.Container) @@ -304,14 +312,13 @@ func assembleDeployment(harvester k8schianetv1.ChiaHarvester) appsv1.Deployment // TODO add pod affinity, tolerations - return deploy + return deploy, nil } -func assembleChiaContainer(harvester k8schianetv1.ChiaHarvester) corev1.Container { +func assembleChiaContainer(ctx context.Context, c client.Client, harvester k8schianetv1.ChiaHarvester) (corev1.Container, error) { input := kube.AssembleChiaContainerInputs{ Image: harvester.Spec.ChiaConfig.Image, ImagePullPolicy: harvester.Spec.ImagePullPolicy, - Env: getChiaEnv(harvester), Ports: []corev1.ContainerPort{ { Name: "daemon", @@ -332,6 +339,12 @@ func assembleChiaContainer(harvester k8schianetv1.ChiaHarvester) corev1.Containe VolumeMounts: getChiaVolumeMounts(harvester), } + env, err := getChiaEnv(ctx, c, harvester) + if err != nil { + return corev1.Container{}, err + } + input.Env = env + if harvester.Spec.ChiaConfig.SecurityContext != nil { input.SecurityContext = harvester.Spec.ChiaConfig.SecurityContext } @@ -352,7 +365,7 @@ func assembleChiaContainer(harvester k8schianetv1.ChiaHarvester) corev1.Containe input.ResourceRequirements = harvester.Spec.ChiaConfig.Resources } - return kube.AssembleChiaContainer(input) + return kube.AssembleChiaContainer(input), nil } func assembleChiaExporterContainer(harvester k8schianetv1.ChiaHarvester) corev1.Container { diff --git a/internal/controller/chiaharvester/controller.go b/internal/controller/chiaharvester/controller.go index 69bfa57..a0ecf8b 100644 --- a/internal/controller/chiaharvester/controller.go +++ b/internal/controller/chiaharvester/controller.go @@ -151,7 +151,11 @@ func (r *ChiaHarvesterReconciler) Reconcile(ctx context.Context, req ctrl.Reques } // Assemble Deployment - deploy := assembleDeployment(harvester) + deploy, err := assembleDeployment(ctx, r.Client, harvester) + if err != nil { + r.Recorder.Event(&harvester, corev1.EventTypeWarning, "Failed", "Failed to assemble harvester Deployment -- Check operator logs.") + return reconcile.Result{}, fmt.Errorf("ChiaHarvesterReconciler ChiaHarvester=%s %v", req.NamespacedName, err) + } if err := controllerutil.SetControllerReference(&harvester, &deploy, r.Scheme); err != nil { r.Recorder.Event(&harvester, corev1.EventTypeWarning, "Failed", "Failed to assemble harvester Deployment -- Check operator logs.") return reconcile.Result{}, fmt.Errorf("ChiaHarvesterReconciler ChiaHarvester=%s %v", req.NamespacedName, err) diff --git a/internal/controller/chiaharvester/helpers.go b/internal/controller/chiaharvester/helpers.go index bb9b6a4..af2cf08 100644 --- a/internal/controller/chiaharvester/helpers.go +++ b/internal/controller/chiaharvester/helpers.go @@ -5,9 +5,12 @@ Copyright 2023 Chia Network Inc. package chiaharvester import ( + "context" "fmt" "strconv" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/chia-network/chia-operator/internal/controller/common/kube" k8schianetv1 "github.com/chia-network/chia-operator/api/v1" @@ -139,7 +142,7 @@ func getChiaVolumeMounts(harvester k8schianetv1.ChiaHarvester) []corev1.VolumeMo } // getChiaEnv retrieves the environment variables from the Chia config struct -func getChiaEnv(harvester k8schianetv1.ChiaHarvester) []corev1.EnvVar { +func getChiaEnv(ctx context.Context, c client.Client, harvester k8schianetv1.ChiaHarvester) ([]corev1.EnvVar, error) { var env []corev1.EnvVar // service env var @@ -166,7 +169,11 @@ func getChiaEnv(harvester k8schianetv1.ChiaHarvester) []corev1.EnvVar { }) // Add common env - env = append(env, kube.GetCommonChiaEnv(harvester.Spec.ChiaConfig.CommonSpecChia)...) + commonEnv, err := kube.GetCommonChiaEnv(ctx, c, harvester.ObjectMeta.Namespace, harvester.Spec.ChiaConfig.CommonSpecChia) + if err != nil { + return env, err + } + env = append(env, commonEnv...) - return env + return env, nil } diff --git a/internal/controller/chiaintroducer/assemblers.go b/internal/controller/chiaintroducer/assemblers.go index cb424b7..5ba4648 100644 --- a/internal/controller/chiaintroducer/assemblers.go +++ b/internal/controller/chiaintroducer/assemblers.go @@ -5,8 +5,11 @@ Copyright 2024 Chia Network Inc. package chiaintroducer import ( + "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "k8s.io/apimachinery/pkg/api/resource" appsv1 "k8s.io/api/apps/v1" @@ -192,7 +195,7 @@ func assembleVolumeClaim(introducer k8schianetv1.ChiaIntroducer) (*corev1.Persis } // assembleDeployment assembles the introducer Deployment resource for a ChiaIntroducer CR -func assembleDeployment(introducer k8schianetv1.ChiaIntroducer) appsv1.Deployment { +func assembleDeployment(ctx context.Context, c client.Client, introducer k8schianetv1.ChiaIntroducer) (appsv1.Deployment, error) { var deploy = appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf(chiaintroducerNamePattern, introducer.Name), @@ -210,7 +213,6 @@ func assembleDeployment(introducer k8schianetv1.ChiaIntroducer) appsv1.Deploymen Annotations: introducer.Spec.AdditionalMetadata.Annotations, }, Spec: corev1.PodSpec{ - Containers: []corev1.Container{assembleChiaContainer(introducer)}, Affinity: introducer.Spec.Affinity, NodeSelector: introducer.Spec.NodeSelector, Volumes: getChiaVolumes(introducer), @@ -219,6 +221,12 @@ func assembleDeployment(introducer k8schianetv1.ChiaIntroducer) appsv1.Deploymen }, } + chiaContainer, err := assembleChiaContainer(ctx, c, introducer) + if err != nil { + return appsv1.Deployment{}, err + } + deploy.Spec.Template.Spec.Containers = append(deploy.Spec.Template.Spec.Containers, chiaContainer) + if len(introducer.Spec.InitContainers) != 0 { // Overwrite any volumeMounts specified in init containers. Not currently supported. for _, cont := range introducer.Spec.InitContainers { @@ -231,7 +239,7 @@ func assembleDeployment(introducer k8schianetv1.ChiaIntroducer) appsv1.Deploymen // Share chia env if enabled if cont.ShareEnv { - cont.Container.Env = append(cont.Container.Env, getChiaEnv(introducer)...) + cont.Container.Env = append(cont.Container.Env, chiaContainer.Env...) } deploy.Spec.Template.Spec.InitContainers = append(deploy.Spec.Template.Spec.InitContainers, cont.Container) @@ -261,14 +269,13 @@ func assembleDeployment(introducer k8schianetv1.ChiaIntroducer) appsv1.Deploymen // TODO add pod affinity, tolerations - return deploy + return deploy, nil } -func assembleChiaContainer(introducer k8schianetv1.ChiaIntroducer) corev1.Container { +func assembleChiaContainer(ctx context.Context, c client.Client, introducer k8schianetv1.ChiaIntroducer) (corev1.Container, error) { input := kube.AssembleChiaContainerInputs{ Image: introducer.Spec.ChiaConfig.Image, ImagePullPolicy: introducer.Spec.ImagePullPolicy, - Env: getChiaEnv(introducer), Ports: []corev1.ContainerPort{ { Name: "daemon", @@ -284,6 +291,12 @@ func assembleChiaContainer(introducer k8schianetv1.ChiaIntroducer) corev1.Contai VolumeMounts: getChiaVolumeMounts(introducer), } + env, err := getChiaEnv(ctx, c, introducer) + if err != nil { + return corev1.Container{}, err + } + input.Env = env + if introducer.Spec.ChiaConfig.SecurityContext != nil { input.SecurityContext = introducer.Spec.ChiaConfig.SecurityContext } @@ -304,7 +317,7 @@ func assembleChiaContainer(introducer k8schianetv1.ChiaIntroducer) corev1.Contai input.ResourceRequirements = introducer.Spec.ChiaConfig.Resources } - return kube.AssembleChiaContainer(input) + return kube.AssembleChiaContainer(input), nil } func assembleChiaExporterContainer(introducer k8schianetv1.ChiaIntroducer) corev1.Container { diff --git a/internal/controller/chiaintroducer/controller.go b/internal/controller/chiaintroducer/controller.go index b8f1a7d..c99cd89 100644 --- a/internal/controller/chiaintroducer/controller.go +++ b/internal/controller/chiaintroducer/controller.go @@ -139,7 +139,11 @@ func (r *ChiaIntroducerReconciler) Reconcile(ctx context.Context, req ctrl.Reque } // Assemble Deployment - deploy := assembleDeployment(introducer) + deploy, err := assembleDeployment(ctx, r.Client, introducer) + if err != nil { + r.Recorder.Event(&introducer, corev1.EventTypeWarning, "Failed", "Failed to assemble introducer Deployment -- Check operator logs.") + return reconcile.Result{}, fmt.Errorf("ChiaIntroducerReconciler ChiaIntroducer=%s %v", req.NamespacedName, err) + } if err := controllerutil.SetControllerReference(&introducer, &deploy, r.Scheme); err != nil { r.Recorder.Event(&introducer, corev1.EventTypeWarning, "Failed", "Failed to assemble introducer Deployment -- Check operator logs.") return reconcile.Result{}, fmt.Errorf("ChiaIntroducerReconciler ChiaIntroducer=%s %v", req.NamespacedName, err) diff --git a/internal/controller/chiaintroducer/helpers.go b/internal/controller/chiaintroducer/helpers.go index c9971c7..83eec09 100644 --- a/internal/controller/chiaintroducer/helpers.go +++ b/internal/controller/chiaintroducer/helpers.go @@ -5,8 +5,11 @@ Copyright 2024 Chia Network Inc. package chiaintroducer import ( + "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/chia-network/chia-operator/internal/controller/common/kube" corev1 "k8s.io/api/core/v1" @@ -73,7 +76,7 @@ func getChiaVolumeMounts(introducer k8schianetv1.ChiaIntroducer) []corev1.Volume } // getChiaEnv retrieves the environment variables from the Chia config struct -func getChiaEnv(introducer k8schianetv1.ChiaIntroducer) []corev1.EnvVar { +func getChiaEnv(ctx context.Context, c client.Client, introducer k8schianetv1.ChiaIntroducer) ([]corev1.EnvVar, error) { var env []corev1.EnvVar // service env var @@ -89,7 +92,11 @@ func getChiaEnv(introducer k8schianetv1.ChiaIntroducer) []corev1.EnvVar { }) // Add common env - env = append(env, kube.GetCommonChiaEnv(introducer.Spec.ChiaConfig.CommonSpecChia)...) + commonEnv, err := kube.GetCommonChiaEnv(ctx, c, introducer.ObjectMeta.Namespace, introducer.Spec.ChiaConfig.CommonSpecChia) + if err != nil { + return env, err + } + env = append(env, commonEnv...) - return env + return env, nil } diff --git a/internal/controller/chianode/assemblers.go b/internal/controller/chianode/assemblers.go index f889bff..fd7253c 100644 --- a/internal/controller/chianode/assemblers.go +++ b/internal/controller/chianode/assemblers.go @@ -8,6 +8,8 @@ import ( "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -259,7 +261,7 @@ func assembleLocalPeerService(node k8schianetv1.ChiaNode) corev1.Service { } // assembleStatefulset assembles the node StatefulSet resource for a ChiaNode CR -func assembleStatefulset(ctx context.Context, node k8schianetv1.ChiaNode) appsv1.StatefulSet { +func assembleStatefulset(ctx context.Context, c client.Client, node k8schianetv1.ChiaNode) (appsv1.StatefulSet, error) { vols, volClaimTemplates := getChiaVolumesAndTemplates(node) stateful := appsv1.StatefulSet{ @@ -282,7 +284,6 @@ func assembleStatefulset(ctx context.Context, node k8schianetv1.ChiaNode) appsv1 }, Spec: corev1.PodSpec{ // TODO add: serviceAccountName config - Containers: []corev1.Container{assembleChiaContainer(ctx, node)}, Affinity: node.Spec.Affinity, NodeSelector: node.Spec.NodeSelector, Volumes: vols, @@ -292,6 +293,12 @@ func assembleStatefulset(ctx context.Context, node k8schianetv1.ChiaNode) appsv1 }, } + chiaContainer, err := assembleChiaContainer(ctx, c, node) + if err != nil { + return appsv1.StatefulSet{}, err + } + stateful.Spec.Template.Spec.Containers = append(stateful.Spec.Template.Spec.Containers, chiaContainer) + if len(node.Spec.InitContainers) != 0 { // Overwrite any volumeMounts specified in init containers. Not currently supported. for _, cont := range node.Spec.InitContainers { @@ -304,7 +311,7 @@ func assembleStatefulset(ctx context.Context, node k8schianetv1.ChiaNode) appsv1 // Share chia env if enabled if cont.ShareEnv { - cont.Container.Env = append(cont.Container.Env, getChiaEnv(ctx, node)...) + cont.Container.Env = append(cont.Container.Env, chiaContainer.Env...) } stateful.Spec.Template.Spec.InitContainers = append(stateful.Spec.Template.Spec.InitContainers, cont.Container) @@ -337,14 +344,13 @@ func assembleStatefulset(ctx context.Context, node k8schianetv1.ChiaNode) appsv1 // TODO add pod affinity, tolerations - return stateful + return stateful, nil } -func assembleChiaContainer(ctx context.Context, node k8schianetv1.ChiaNode) corev1.Container { +func assembleChiaContainer(ctx context.Context, c client.Client, node k8schianetv1.ChiaNode) (corev1.Container, error) { input := kube.AssembleChiaContainerInputs{ Image: node.Spec.ChiaConfig.Image, ImagePullPolicy: node.Spec.ImagePullPolicy, - Env: getChiaEnv(ctx, node), Ports: []corev1.ContainerPort{ { Name: "daemon", @@ -365,6 +371,12 @@ func assembleChiaContainer(ctx context.Context, node k8schianetv1.ChiaNode) core VolumeMounts: getChiaVolumeMounts(), } + env, err := getChiaEnv(ctx, c, node) + if err != nil { + return corev1.Container{}, err + } + input.Env = env + if node.Spec.ChiaConfig.SecurityContext != nil { input.SecurityContext = node.Spec.ChiaConfig.SecurityContext } @@ -401,7 +413,7 @@ func assembleChiaContainer(ctx context.Context, node k8schianetv1.ChiaNode) core input.ResourceRequirements = node.Spec.ChiaConfig.Resources } - return kube.AssembleChiaContainer(input) + return kube.AssembleChiaContainer(input), nil } func assembleChiaExporterContainer(node k8schianetv1.ChiaNode) corev1.Container { diff --git a/internal/controller/chianode/controller.go b/internal/controller/chianode/controller.go index 86f6f18..783ea6a 100644 --- a/internal/controller/chianode/controller.go +++ b/internal/controller/chianode/controller.go @@ -169,13 +169,17 @@ func (r *ChiaNodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c } } - // Assemble Deployment - stateful := assembleStatefulset(ctx, node) + // Assemble StatefulSet + stateful, err := assembleStatefulset(ctx, r.Client, node) + if err != nil { + r.Recorder.Event(&node, corev1.EventTypeWarning, "Failed", "Failed to assemble node Deployment -- Check operator logs.") + return reconcile.Result{}, fmt.Errorf("ChiaNodeReconciler ChiaNode=%s %v", req.NamespacedName, err) + } if err := controllerutil.SetControllerReference(&node, &stateful, r.Scheme); err != nil { r.Recorder.Event(&node, corev1.EventTypeWarning, "Failed", "Failed to assemble seeder Statefulset -- Check operator logs.") return reconcile.Result{}, fmt.Errorf("ChiaNodeReconciler ChiaNode=%s %v", req.NamespacedName, err) } - // Reconcile Deployment + // Reconcile StatefulSet res, err = kube.ReconcileStatefulset(ctx, r.Client, stateful) if err != nil { r.Recorder.Event(&node, corev1.EventTypeWarning, "Failed", "Failed to create seeder Statefulset -- Check operator logs.") diff --git a/internal/controller/chianode/helpers.go b/internal/controller/chianode/helpers.go index b78eb13..7799ee4 100644 --- a/internal/controller/chianode/helpers.go +++ b/internal/controller/chianode/helpers.go @@ -9,6 +9,8 @@ import ( "encoding/json" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/chia-network/chia-operator/internal/controller/common/kube" "sigs.k8s.io/controller-runtime/pkg/log" @@ -120,7 +122,7 @@ func getChiaVolumeMounts() []corev1.VolumeMount { } // getChiaEnv retrieves the environment variables from the Chia config struct -func getChiaEnv(ctx context.Context, node k8schianetv1.ChiaNode) []corev1.EnvVar { +func getChiaEnv(ctx context.Context, c client.Client, node k8schianetv1.ChiaNode) ([]corev1.EnvVar, error) { logr := log.FromContext(ctx) var env []corev1.EnvVar @@ -151,7 +153,11 @@ func getChiaEnv(ctx context.Context, node k8schianetv1.ChiaNode) []corev1.EnvVar } // Add common env - env = append(env, kube.GetCommonChiaEnv(node.Spec.ChiaConfig.CommonSpecChia)...) + commonEnv, err := kube.GetCommonChiaEnv(ctx, c, node.ObjectMeta.Namespace, node.Spec.ChiaConfig.CommonSpecChia) + if err != nil { + return env, err + } + env = append(env, commonEnv...) - return env + return env, nil } diff --git a/internal/controller/chiaseeder/assemblers.go b/internal/controller/chiaseeder/assemblers.go index 0ff1c4c..4fb53fa 100644 --- a/internal/controller/chiaseeder/assemblers.go +++ b/internal/controller/chiaseeder/assemblers.go @@ -5,8 +5,11 @@ Copyright 2023 Chia Network Inc. package chiaseeder import ( + "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "k8s.io/apimachinery/pkg/api/resource" appsv1 "k8s.io/api/apps/v1" @@ -294,7 +297,7 @@ func assembleVolumeClaim(seeder k8schianetv1.ChiaSeeder) (*corev1.PersistentVolu } // assembleDeployment assembles the seeder Deployment resource for a ChiaSeeder CR -func assembleDeployment(seeder k8schianetv1.ChiaSeeder) appsv1.Deployment { +func assembleDeployment(ctx context.Context, c client.Client, seeder k8schianetv1.ChiaSeeder) (appsv1.Deployment, error) { var deploy = appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf(chiaseederNamePattern, seeder.Name), @@ -312,7 +315,6 @@ func assembleDeployment(seeder k8schianetv1.ChiaSeeder) appsv1.Deployment { Annotations: seeder.Spec.AdditionalMetadata.Annotations, }, Spec: corev1.PodSpec{ - Containers: []corev1.Container{assembleChiaContainer(seeder)}, Affinity: seeder.Spec.Affinity, NodeSelector: seeder.Spec.NodeSelector, Volumes: getChiaVolumes(seeder), @@ -321,6 +323,12 @@ func assembleDeployment(seeder k8schianetv1.ChiaSeeder) appsv1.Deployment { }, } + chiaContainer, err := assembleChiaContainer(ctx, c, seeder) + if err != nil { + return appsv1.Deployment{}, err + } + deploy.Spec.Template.Spec.Containers = append(deploy.Spec.Template.Spec.Containers, chiaContainer) + if len(seeder.Spec.InitContainers) != 0 { // Overwrite any volumeMounts specified in init containers. Not currently supported. for _, cont := range seeder.Spec.InitContainers { @@ -333,7 +341,7 @@ func assembleDeployment(seeder k8schianetv1.ChiaSeeder) appsv1.Deployment { // Share chia env if enabled if cont.ShareEnv { - cont.Container.Env = append(cont.Container.Env, getChiaEnv(seeder)...) + cont.Container.Env = append(cont.Container.Env, chiaContainer.Env...) } deploy.Spec.Template.Spec.InitContainers = append(deploy.Spec.Template.Spec.InitContainers, cont.Container) @@ -366,18 +374,23 @@ func assembleDeployment(seeder k8schianetv1.ChiaSeeder) appsv1.Deployment { // TODO add pod affinity, tolerations - return deploy + return deploy, nil } -func assembleChiaContainer(seeder k8schianetv1.ChiaSeeder) corev1.Container { +func assembleChiaContainer(ctx context.Context, c client.Client, seeder k8schianetv1.ChiaSeeder) (corev1.Container, error) { input := kube.AssembleChiaContainerInputs{ Image: seeder.Spec.ChiaConfig.Image, ImagePullPolicy: seeder.Spec.ImagePullPolicy, - Env: getChiaEnv(seeder), Ports: getChiaPorts(seeder), VolumeMounts: getChiaVolumeMounts(seeder), } + env, err := getChiaEnv(ctx, c, seeder) + if err != nil { + return corev1.Container{}, err + } + input.Env = env + if seeder.Spec.ChiaConfig.SecurityContext != nil { input.SecurityContext = seeder.Spec.ChiaConfig.SecurityContext } else { @@ -422,7 +435,7 @@ func assembleChiaContainer(seeder k8schianetv1.ChiaSeeder) corev1.Container { input.ResourceRequirements = seeder.Spec.ChiaConfig.Resources } - return kube.AssembleChiaContainer(input) + return kube.AssembleChiaContainer(input), nil } func assembleChiaExporterContainer(seeder k8schianetv1.ChiaSeeder) corev1.Container { diff --git a/internal/controller/chiaseeder/controller.go b/internal/controller/chiaseeder/controller.go index 72c9c5b..8dce2cb 100644 --- a/internal/controller/chiaseeder/controller.go +++ b/internal/controller/chiaseeder/controller.go @@ -181,7 +181,11 @@ func (r *ChiaSeederReconciler) Reconcile(ctx context.Context, req ctrl.Request) } // Assemble Deployment - deploy := assembleDeployment(seeder) + deploy, err := assembleDeployment(ctx, r.Client, seeder) + if err != nil { + r.Recorder.Event(&seeder, corev1.EventTypeWarning, "Failed", "Failed to assemble seeder Deployment -- Check operator logs.") + return reconcile.Result{}, fmt.Errorf("ChiaSeederReconciler ChiaSeeder=%s %v", req.NamespacedName, err) + } if err := controllerutil.SetControllerReference(&seeder, &deploy, r.Scheme); err != nil { r.Recorder.Event(&seeder, corev1.EventTypeWarning, "Failed", "Failed to assemble seeder Deployment -- Check operator logs.") return reconcile.Result{}, fmt.Errorf("ChiaSeederReconciler ChiaSeeder=%s %v", req.NamespacedName, err) diff --git a/internal/controller/chiaseeder/helpers.go b/internal/controller/chiaseeder/helpers.go index cf607b3..2ee5a4d 100644 --- a/internal/controller/chiaseeder/helpers.go +++ b/internal/controller/chiaseeder/helpers.go @@ -5,8 +5,11 @@ Copyright 2023 Chia Network Inc. package chiaseeder import ( + "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/chia-network/chia-operator/internal/controller/common/kube" corev1 "k8s.io/api/core/v1" @@ -74,7 +77,7 @@ func getChiaVolumeMounts(seeder k8schianetv1.ChiaSeeder) []corev1.VolumeMount { } // getChiaEnv retrieves the environment variables from the Chia config struct -func getChiaEnv(seeder k8schianetv1.ChiaSeeder) []corev1.EnvVar { +func getChiaEnv(ctx context.Context, c client.Client, seeder k8schianetv1.ChiaSeeder) ([]corev1.EnvVar, error) { var env []corev1.EnvVar // service env var @@ -132,9 +135,13 @@ func getChiaEnv(seeder k8schianetv1.ChiaSeeder) []corev1.EnvVar { } // Add common env - env = append(env, kube.GetCommonChiaEnv(seeder.Spec.ChiaConfig.CommonSpecChia)...) + commonEnv, err := kube.GetCommonChiaEnv(ctx, c, seeder.ObjectMeta.Namespace, seeder.Spec.ChiaConfig.CommonSpecChia) + if err != nil { + return env, err + } + env = append(env, commonEnv...) - return env + return env, nil } // getChiaPorts returns the ports to a chia container diff --git a/internal/controller/chiatimelord/assemblers.go b/internal/controller/chiatimelord/assemblers.go index 1a18776..fe6d586 100644 --- a/internal/controller/chiatimelord/assemblers.go +++ b/internal/controller/chiatimelord/assemblers.go @@ -5,8 +5,11 @@ Copyright 2023 Chia Network Inc. package chiatimelord import ( + "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "k8s.io/apimachinery/pkg/api/resource" appsv1 "k8s.io/api/apps/v1" @@ -270,7 +273,7 @@ func assembleVolumeClaim(tl k8schianetv1.ChiaTimelord) (*corev1.PersistentVolume } // assembleDeployment assembles the tl Deployment resource for a ChiaTimelord CR -func assembleDeployment(tl k8schianetv1.ChiaTimelord) appsv1.Deployment { +func assembleDeployment(ctx context.Context, c client.Client, tl k8schianetv1.ChiaTimelord) (appsv1.Deployment, error) { var deploy = appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf(chiatimelordNamePattern, tl.Name), @@ -288,7 +291,6 @@ func assembleDeployment(tl k8schianetv1.ChiaTimelord) appsv1.Deployment { Annotations: tl.Spec.AdditionalMetadata.Annotations, }, Spec: corev1.PodSpec{ - Containers: []corev1.Container{assembleChiaContainer(tl)}, Affinity: tl.Spec.Affinity, NodeSelector: tl.Spec.NodeSelector, Volumes: getChiaVolumes(tl), @@ -297,6 +299,12 @@ func assembleDeployment(tl k8schianetv1.ChiaTimelord) appsv1.Deployment { }, } + chiaContainer, err := assembleChiaContainer(ctx, c, tl) + if err != nil { + return appsv1.Deployment{}, err + } + deploy.Spec.Template.Spec.Containers = append(deploy.Spec.Template.Spec.Containers, chiaContainer) + if len(tl.Spec.InitContainers) != 0 { // Overwrite any volumeMounts specified in init containers. Not currently supported. for _, cont := range tl.Spec.InitContainers { @@ -309,7 +317,7 @@ func assembleDeployment(tl k8schianetv1.ChiaTimelord) appsv1.Deployment { // Share chia env if enabled if cont.ShareEnv { - cont.Container.Env = append(cont.Container.Env, getChiaEnv(tl)...) + cont.Container.Env = append(cont.Container.Env, chiaContainer.Env...) } deploy.Spec.Template.Spec.InitContainers = append(deploy.Spec.Template.Spec.InitContainers, cont.Container) @@ -343,14 +351,13 @@ func assembleDeployment(tl k8schianetv1.ChiaTimelord) appsv1.Deployment { // TODO add pod affinity, tolerations - return deploy + return deploy, nil } -func assembleChiaContainer(tl k8schianetv1.ChiaTimelord) corev1.Container { +func assembleChiaContainer(ctx context.Context, c client.Client, tl k8schianetv1.ChiaTimelord) (corev1.Container, error) { input := kube.AssembleChiaContainerInputs{ Image: tl.Spec.ChiaConfig.Image, ImagePullPolicy: tl.Spec.ImagePullPolicy, - Env: getChiaEnv(tl), Ports: []corev1.ContainerPort{ { Name: "daemon", @@ -371,6 +378,12 @@ func assembleChiaContainer(tl k8schianetv1.ChiaTimelord) corev1.Container { VolumeMounts: getChiaVolumeMounts(), } + env, err := getChiaEnv(ctx, c, tl) + if err != nil { + return corev1.Container{}, err + } + input.Env = env + if tl.Spec.ChiaConfig.SecurityContext != nil { input.SecurityContext = tl.Spec.ChiaConfig.SecurityContext } @@ -407,7 +420,7 @@ func assembleChiaContainer(tl k8schianetv1.ChiaTimelord) corev1.Container { input.ResourceRequirements = tl.Spec.ChiaConfig.Resources } - return kube.AssembleChiaContainer(input) + return kube.AssembleChiaContainer(input), nil } func assembleChiaExporterContainer(tl k8schianetv1.ChiaTimelord) corev1.Container { diff --git a/internal/controller/chiatimelord/controller.go b/internal/controller/chiatimelord/controller.go index 4e64d4a..424e5b9 100644 --- a/internal/controller/chiatimelord/controller.go +++ b/internal/controller/chiatimelord/controller.go @@ -166,7 +166,11 @@ func (r *ChiaTimelordReconciler) Reconcile(ctx context.Context, req ctrl.Request } // Assemble Deployment - deploy := assembleDeployment(timelord) + deploy, err := assembleDeployment(ctx, r.Client, timelord) + if err != nil { + r.Recorder.Event(&timelord, corev1.EventTypeWarning, "Failed", "Failed to assemble timelord Deployment -- Check operator logs.") + return reconcile.Result{}, fmt.Errorf("ChiaTimelordReconciler ChiaTimelord=%s %v", req.NamespacedName, err) + } if err := controllerutil.SetControllerReference(&timelord, &deploy, r.Scheme); err != nil { r.Recorder.Event(&timelord, corev1.EventTypeWarning, "Failed", "Failed to assemble timelord Deployment -- Check operator logs.") return reconcile.Result{}, fmt.Errorf("ChiaTimelordReconciler ChiaTimelord=%s %v", req.NamespacedName, err) diff --git a/internal/controller/chiatimelord/helpers.go b/internal/controller/chiatimelord/helpers.go index e726b66..70e95fa 100644 --- a/internal/controller/chiatimelord/helpers.go +++ b/internal/controller/chiatimelord/helpers.go @@ -5,8 +5,11 @@ Copyright 2023 Chia Network Inc. package chiatimelord import ( + "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/chia-network/chia-operator/internal/controller/common/kube" k8schianetv1 "github.com/chia-network/chia-operator/api/v1" @@ -64,7 +67,7 @@ func getChiaVolumeMounts() []corev1.VolumeMount { } // getChiaEnv retrieves the environment variables from the Chia config struct -func getChiaEnv(timelord k8schianetv1.ChiaTimelord) []corev1.EnvVar { +func getChiaEnv(ctx context.Context, c client.Client, timelord k8schianetv1.ChiaTimelord) ([]corev1.EnvVar, error) { var env []corev1.EnvVar // service env var @@ -80,7 +83,11 @@ func getChiaEnv(timelord k8schianetv1.ChiaTimelord) []corev1.EnvVar { }) // Add common env - env = append(env, kube.GetCommonChiaEnv(timelord.Spec.ChiaConfig.CommonSpecChia)...) + commonEnv, err := kube.GetCommonChiaEnv(ctx, c, timelord.ObjectMeta.Namespace, timelord.Spec.ChiaConfig.CommonSpecChia) + if err != nil { + return env, err + } + env = append(env, commonEnv...) - return env + return env, nil } diff --git a/internal/controller/chiawallet/assemblers.go b/internal/controller/chiawallet/assemblers.go index 12de0e6..5a9ac51 100644 --- a/internal/controller/chiawallet/assemblers.go +++ b/internal/controller/chiawallet/assemblers.go @@ -8,6 +8,8 @@ import ( "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/intstr" @@ -235,7 +237,7 @@ func assembleVolumeClaim(wallet k8schianetv1.ChiaWallet) (*corev1.PersistentVolu } // assembleDeployment assembles the wallet Deployment resource for a ChiaWallet CR -func assembleDeployment(ctx context.Context, wallet k8schianetv1.ChiaWallet) appsv1.Deployment { +func assembleDeployment(ctx context.Context, c client.Client, wallet k8schianetv1.ChiaWallet) (appsv1.Deployment, error) { var deploy = appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf(chiawalletNamePattern, wallet.Name), @@ -253,7 +255,6 @@ func assembleDeployment(ctx context.Context, wallet k8schianetv1.ChiaWallet) app Annotations: wallet.Spec.AdditionalMetadata.Annotations, }, Spec: corev1.PodSpec{ - Containers: []corev1.Container{assembleChiaContainer(ctx, wallet)}, Affinity: wallet.Spec.Affinity, NodeSelector: wallet.Spec.NodeSelector, Volumes: getChiaVolumes(wallet), @@ -262,6 +263,12 @@ func assembleDeployment(ctx context.Context, wallet k8schianetv1.ChiaWallet) app }, } + chiaContainer, err := assembleChiaContainer(ctx, c, wallet) + if err != nil { + return appsv1.Deployment{}, err + } + deploy.Spec.Template.Spec.Containers = append(deploy.Spec.Template.Spec.Containers, chiaContainer) + if len(wallet.Spec.InitContainers) != 0 { // Overwrite any volumeMounts specified in init containers. Not currently supported. for _, cont := range wallet.Spec.InitContainers { @@ -274,7 +281,7 @@ func assembleDeployment(ctx context.Context, wallet k8schianetv1.ChiaWallet) app // Share chia env if enabled if cont.ShareEnv { - cont.Container.Env = append(cont.Container.Env, getChiaEnv(ctx, wallet)...) + cont.Container.Env = append(cont.Container.Env, chiaContainer.Env...) } deploy.Spec.Template.Spec.InitContainers = append(deploy.Spec.Template.Spec.InitContainers, cont.Container) @@ -304,18 +311,23 @@ func assembleDeployment(ctx context.Context, wallet k8schianetv1.ChiaWallet) app // TODO add pod affinity, tolerations - return deploy + return deploy, nil } -func assembleChiaContainer(ctx context.Context, wallet k8schianetv1.ChiaWallet) corev1.Container { +func assembleChiaContainer(ctx context.Context, c client.Client, wallet k8schianetv1.ChiaWallet) (corev1.Container, error) { input := kube.AssembleChiaContainerInputs{ Image: wallet.Spec.ChiaConfig.Image, ImagePullPolicy: wallet.Spec.ImagePullPolicy, - Env: getChiaEnv(ctx, wallet), Ports: getChiaPorts(), VolumeMounts: getChiaVolumeMounts(), } + env, err := getChiaEnv(ctx, c, wallet) + if err != nil { + return corev1.Container{}, err + } + input.Env = env + if wallet.Spec.ChiaConfig.SecurityContext != nil { input.SecurityContext = wallet.Spec.ChiaConfig.SecurityContext } @@ -336,7 +348,7 @@ func assembleChiaContainer(ctx context.Context, wallet k8schianetv1.ChiaWallet) input.ResourceRequirements = wallet.Spec.ChiaConfig.Resources } - return kube.AssembleChiaContainer(input) + return kube.AssembleChiaContainer(input), nil } func assembleChiaExporterContainer(wallet k8schianetv1.ChiaWallet) corev1.Container { diff --git a/internal/controller/chiawallet/controller.go b/internal/controller/chiawallet/controller.go index 8abd1b0..a99022b 100644 --- a/internal/controller/chiawallet/controller.go +++ b/internal/controller/chiawallet/controller.go @@ -151,7 +151,11 @@ func (r *ChiaWalletReconciler) Reconcile(ctx context.Context, req ctrl.Request) } // Assemble Deployment - deploy := assembleDeployment(ctx, wallet) + deploy, err := assembleDeployment(ctx, r.Client, wallet) + if err != nil { + r.Recorder.Event(&wallet, corev1.EventTypeWarning, "Failed", "Failed to assemble wallet Deployment -- Check operator logs.") + return reconcile.Result{}, fmt.Errorf("ChiaWalletReconciler ChiaWallet=%s %v", req.NamespacedName, err) + } if err := controllerutil.SetControllerReference(&wallet, &deploy, r.Scheme); err != nil { r.Recorder.Event(&wallet, corev1.EventTypeWarning, "Failed", "Failed to assemble wallet Deployment -- Check operator logs.") return reconcile.Result{}, fmt.Errorf("ChiaWalletReconciler ChiaWallet=%s %v", req.NamespacedName, err) diff --git a/internal/controller/chiawallet/helpers.go b/internal/controller/chiawallet/helpers.go index 6934503..1b3b480 100644 --- a/internal/controller/chiawallet/helpers.go +++ b/internal/controller/chiawallet/helpers.go @@ -9,6 +9,8 @@ import ( "encoding/json" "fmt" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/chia-network/chia-operator/internal/controller/common/kube" "sigs.k8s.io/controller-runtime/pkg/log" @@ -102,7 +104,7 @@ func getChiaVolumeMounts() []corev1.VolumeMount { } // getChiaEnv retrieves the environment variables from the Chia config struct -func getChiaEnv(ctx context.Context, wallet k8schianetv1.ChiaWallet) []corev1.EnvVar { +func getChiaEnv(ctx context.Context, c client.Client, wallet k8schianetv1.ChiaWallet) ([]corev1.EnvVar, error) { logr := log.FromContext(ctx) var env []corev1.EnvVar @@ -141,7 +143,11 @@ func getChiaEnv(ctx context.Context, wallet k8schianetv1.ChiaWallet) []corev1.En } // Add common env - env = append(env, kube.GetCommonChiaEnv(wallet.Spec.ChiaConfig.CommonSpecChia)...) + commonEnv, err := kube.GetCommonChiaEnv(ctx, c, wallet.ObjectMeta.Namespace, wallet.Spec.ChiaConfig.CommonSpecChia) + if err != nil { + return env, err + } + env = append(env, commonEnv...) - return env + return env, nil } diff --git a/internal/controller/common/kube/helpers.go b/internal/controller/common/kube/helpers.go index 6ef3491..35df529 100644 --- a/internal/controller/common/kube/helpers.go +++ b/internal/controller/common/kube/helpers.go @@ -5,13 +5,19 @@ Copyright 2023 Chia Network Inc. package kube import ( + "context" + "fmt" "strconv" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + k8schianetv1 "github.com/chia-network/chia-operator/api/v1" "github.com/chia-network/chia-operator/internal/controller/common/consts" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/controller-runtime/pkg/client" ) // GetCommonLabels gives some common labels for chia-operator related objects @@ -143,7 +149,7 @@ func GetExistingChiaRootVolume(storage *k8schianetv1.StorageConfig) corev1.Volum } // GetCommonChiaEnv retrieves the environment variables from the CommonSpecChia config struct -func GetCommonChiaEnv(commonSpecChia k8schianetv1.CommonSpecChia) []corev1.EnvVar { +func GetCommonChiaEnv(ctx context.Context, c client.Client, namespace string, commonSpecChia k8schianetv1.CommonSpecChia) ([]corev1.EnvVar, error) { var env []corev1.EnvVar // CHIA_ROOT env var @@ -233,5 +239,37 @@ func GetCommonChiaEnv(commonSpecChia k8schianetv1.CommonSpecChia) []corev1.EnvVa }) } - return env + // Check for ChiaNetwork, retrieve matching ConfigMap if specified + if commonSpecChia.ChiaNetwork != nil && *commonSpecChia.ChiaNetwork != "" { + var chianetworkConfig corev1.ConfigMap + err := c.Get(ctx, types.NamespacedName{ + Name: *commonSpecChia.ChiaNetwork, + Namespace: namespace, + }, &chianetworkConfig) + if err != nil && errors.IsNotFound(err) { + return []corev1.EnvVar{}, fmt.Errorf("ChiaNetwork specified but its ConfigMap was not found: %v", err) + } else if err != nil { + return []corev1.EnvVar{}, fmt.Errorf("error getting existing ChiaNetwork's ConfigMap: %v", err) + } + + // Loop over data keys, see if any match current environment variables. Overwrite the environment variable, or append a new one + for k, v := range chianetworkConfig.Data { + found := false + for i := range env { + if env[i].Name == k { + env[i].Name = v + found = true + break + } + } + if !found { + env = append(env, corev1.EnvVar{ + Name: k, + Value: v, + }) + } + } + } + + return env, nil } From ce454c105a7fc68ec0de4443322adf23d3b75438 Mon Sep 17 00:00:00 2001 From: Starttoaster Date: Sat, 14 Sep 2024 21:47:15 -0700 Subject: [PATCH 8/9] Add sort to common environment variables --- internal/controller/common/kube/helpers.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/internal/controller/common/kube/helpers.go b/internal/controller/common/kube/helpers.go index 35df529..31825d7 100644 --- a/internal/controller/common/kube/helpers.go +++ b/internal/controller/common/kube/helpers.go @@ -7,6 +7,7 @@ package kube import ( "context" "fmt" + "sort" "strconv" "k8s.io/apimachinery/pkg/api/errors" @@ -257,7 +258,7 @@ func GetCommonChiaEnv(ctx context.Context, c client.Client, namespace string, co found := false for i := range env { if env[i].Name == k { - env[i].Name = v + env[i].Value = v found = true break } @@ -271,5 +272,14 @@ func GetCommonChiaEnv(ctx context.Context, c client.Client, namespace string, co } } + // Need to alphabetize the env slice because if the order of environment variables + // changes but none of the values changed, it still triggers a StatefulSet rollout. + // When the StatefulSet rolls out, it triggers another reconcile run, which can cause another StatefulSet rollout. + // Only need to do this for common env variables because we use a map for some variables from a ConfigMap's data, + // where looping over a map causes randomness. + sort.Slice(env, func(i, j int) bool { + return env[i].Name < env[j].Name + }) + return env, nil } From a26003656a893d6fc39056bdd9624ca237f087a2 Mon Sep 17 00:00:00 2001 From: Starttoaster Date: Sat, 14 Sep 2024 21:48:29 -0700 Subject: [PATCH 9/9] Add sort to common environment variables --- internal/controller/common/kube/helpers.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/controller/common/kube/helpers.go b/internal/controller/common/kube/helpers.go index 31825d7..3a997e0 100644 --- a/internal/controller/common/kube/helpers.go +++ b/internal/controller/common/kube/helpers.go @@ -275,6 +275,7 @@ func GetCommonChiaEnv(ctx context.Context, c client.Client, namespace string, co // Need to alphabetize the env slice because if the order of environment variables // changes but none of the values changed, it still triggers a StatefulSet rollout. // When the StatefulSet rolls out, it triggers another reconcile run, which can cause another StatefulSet rollout. + // This is probably also an issue for Deployments. // Only need to do this for common env variables because we use a map for some variables from a ConfigMap's data, // where looping over a map causes randomness. sort.Slice(env, func(i, j int) bool {