Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code organization and test refinements #27

Merged
merged 14 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion CONTIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,13 @@ When creating a pull request, have a clear summary of what the change does and w

```
This pull request adds support for Chia Wallets. This would be useful for writing 3rd party apps to be deployed to kubernetes that need to communicate to a Chia wallet's RPCs.
```
```

### API Contributions

These rules/guidelines are meant to help keep a well defined style for accomplishing controller logic, and in some cases also helps persist controller-gen/kubebuilder defaults in comment tags because it can be easy to accidentally override the API default with a type's zero value on accident, for example.

1. Optional fields should always include omitempty as an option in the json tag. ex. `json:"image,omitempty"`
2. Optional embedded struct fields, and sometimes string/bool/int fields, with no defaults should use pointers. A general rule of thumb is to consider how you want to handle the configuration logic surrounding that field in the controller code. If the field may not be configured commonly then it may be convenient to do a simple `if x == nil` check to keep it blank in the resulting K8s Kind struct. Optional embedded struct fields are especially convenient to just check against nil.
3. A required field should usually specify a default, and that default should usually try to match a default configuration from chia-blockchain, or one that is especially advantageous to running in kubernetes. Some required fields don't need defaults, like the one for a chia mnemonic.
4. Fields that are autogenerated by kubebuilder should be left as-is and these rules do not apply to them.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Deploy the operator:
make deploy
```

See the documentation for more in [docs](docs)

### Start a farm

This guide installs everything in the default namespace, but you can of course install them in any namespace. These are also all fairly minimal examples with just enough config to be helpful. Other options are supported. See the `config/samples` directory of this repo for more full examples.
Expand Down Expand Up @@ -179,8 +181,8 @@ Finally, apply this ChiaWallet with `kubectl apply -f wallet.yaml`
## TODO

- Add to examples in `config/samples`. The full API for all of this operator's CRDs are shown in Go structs in `api/v1`
- Add support for other Chia components (timelord, dns-introducer, etc)
- Make chia-exporter an optional container in the pod
- Add support for other Chia components (dns-introducer, etc)
- Additional controller tests for CRs with all options set to something non-default, currently all the tests use fairly minimal implementations to test overlaying CRD defaults on top of the submitted CR

## License

Expand Down
6 changes: 5 additions & 1 deletion api/v1/chiaca_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ import (
type ChiaCASpec struct {
// Image defines the CA generator image to run
// +kubebuilder:default="ghcr.io/chia-network/chia-operator/ca-gen:latest"
// +optional
Image string `json:"image,omitempty"`

// ImagePullSecret defines an ImagePullSecret for the CA generator image
// +optional
ImagePullSecret string `json:"imagePullSecret,omitempty"`

// Secret defines the name of the secret to contain CA files
Secret string `json:"secret"`
// +kubebuilder:default="chia-ca"
// +optional
Secret string `json:"secret,omitempty"`
}

// ChiaCAStatus defines the observed state of ChiaCA
Expand Down
65 changes: 65 additions & 0 deletions api/v1/chiaca_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
Copyright 2023 Chia Network Inc.
*/

package v1

import (
"testing"

"github.com/google/go-cmp/cmp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"
)

func TestUnmarshalChiaCA(t *testing.T) {
yamlData := []byte(`
apiVersion: k8s.chia.net/v1
kind: ChiaCA
metadata:
labels:
app.kubernetes.io/name: chiaca
app.kubernetes.io/instance: chiaca-sample
app.kubernetes.io/part-of: chia-operator
app.kubernetes.io/created-by: chia-operator
name: chiaca-sample
spec:
image: "ca-gen-image:latest"
imagePullSecret: registrypullsecret
secret: chiaca-secret
`)

expect := ChiaCA{
TypeMeta: metav1.TypeMeta{
APIVersion: "k8s.chia.net/v1",
Kind: "ChiaCA",
},
ObjectMeta: metav1.ObjectMeta{
Name: "chiaca-sample",
Labels: map[string]string{
"app.kubernetes.io/name": "chiaca",
"app.kubernetes.io/instance": "chiaca-sample",
"app.kubernetes.io/part-of": "chia-operator",
"app.kubernetes.io/created-by": "chia-operator",
},
},
Spec: ChiaCASpec{
Image: "ca-gen-image:latest",
ImagePullSecret: "registrypullsecret",
Secret: "chiaca-secret",
},
}

var actual ChiaCA
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
}
}
91 changes: 86 additions & 5 deletions api/v1/chiacommon_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,101 @@ Copyright 2023 Chia Network Inc.

package v1

// ChiaExporterConfigSpec defines the desired state of Chia exporter configuration
type ChiaExporterConfigSpec struct {
import corev1 "k8s.io/api/core/v1"

// CommonSpec represents the common configuration options for controller APIs at the top-spec level
type CommonSpec struct {
AdditionalMetadata `json:",inline"`

// ChiaExporterConfig defines the configuration options available to Chia component containers
// +optional
ChiaExporterConfig SpecChiaExporter `json:"chiaExporter,omitempty"`

//StorageConfig defines the Chia container's CHIA_ROOT storage config
// +optional
Storage *StorageConfig `json:"storage,omitempty"`

// ServiceType is the type of the service that governs this ChiaNode StatefulSet.
// +optional
// +kubebuilder:default="ClusterIP"
ServiceType string `json:"serviceType,omitempty"`

// ImagePullPolicy is the pull policy for containers in the pod
// +optional
// +kubebuilder:default="Always"
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`

// NodeSelector selects a node by key value pairs
// +optional
NodeSelector map[string]string `json:"nodeSelector,omitempty"`

// PodSecurityContext defines the security context for the pod
// +optional
PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"`
}

// CommonSpecChia represents the common configuration options for a chia spec
type CommonSpecChia struct {
// Image defines the image to use for the chia component containers
// +kubebuilder:default="ghcr.io/chia-network/chia:latest"
// +optional
Image string `json:"image,omitempty"`

// CASecretName is the name of the secret that contains the CA crt and key.
CASecretName string `json:"caSecretName"`

// Testnet is set to true if the Chia container should switch to the latest default testnet's settings
// +optional
Testnet *bool `json:"testnet,omitempty"`

// Timezone can be set to your local timezone for accurate timestamps. Defaults to UTC
// +optional
Timezone *string `json:"timezone,omitempty"`

// LogLevel is set to the desired chia config log_level
// +optional
LogLevel *string `json:"logLevel,omitempty"`

// Periodic probe of container liveness.
// +optional
LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty"`

// Periodic probe of container service readiness.
// +optional
ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty"`

// StartupProbe indicates that the Pod has successfully initialized.
// +optional
StartupProbe *corev1.Probe `json:"startupProbe,omitempty"`

// Resources defines the compute resources for the Chia container
// +optional
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`

// SecurityContext defines the security context for the chia container
// +optional
SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"`
}

// SpecChiaExporter defines the desired state of Chia exporter configuration
type SpecChiaExporter struct {
// Enabled defines whether a chia-exporter sidecar container should run with the chia container
// +kubebuilder:default=true
// +optional
Enabled bool `json:"enabled,omitempty"`

// Image defines the image to use for the chia exporter containers
// +kubebuilder:default="ghcr.io/chia-network/chia-exporter:latest"
// +optional
Image string `json:"image"`
Image string `json:"image,omitempty"`

// Labels is a map of string keys and values to attach to the chia exporter k8s Service
// +optional
ServiceLabels map[string]string `json:"serviceLabels,omitempty"`
}

// ChiaKeysSpec defines the name of a kubernetes secret and key in that secret that contains the Chia mnemonic
type ChiaKeysSpec struct {
// ChiaSecretKey defines the name of a kubernetes secret and key in that namespace that contains the Chia mnemonic
type ChiaSecretKey struct {
// SecretName is the name of the kubernetes secret containing a mnemonic key
Name string `json:"name"`

Expand Down
79 changes: 7 additions & 72 deletions api/v1/chiafarmer_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,92 +5,27 @@ Copyright 2023 Chia Network Inc.
package v1

import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// ChiaFarmerSpec defines the desired state of ChiaFarmer
type ChiaFarmerSpec struct {
AdditionalMetadata `json:",inline"`
CommonSpec `json:",inline"`

// ChiaConfig defines the configuration options available to Chia component containers
ChiaConfig ChiaFarmerConfigSpec `json:"chia"`

// ChiaExporterConfig defines the configuration options available to Chia component containers
// +optional
ChiaExporterConfig ChiaExporterConfigSpec `json:"chiaExporter"`

//StorageConfig defines the Chia container's CHIA_ROOT storage config
// +optional
Storage *StorageConfig `json:"storage,omitempty"`

// ServiceType is the type of the service for the farmer instance
// +optional
// +kubebuilder:default="ClusterIP"
ServiceType string `json:"serviceType"`

// ImagePullPolicy is the pull policy for containers in the pod
// +optional
// +kubebuilder:default="Always"
ImagePullPolicy *corev1.PullPolicy `json:"imagePullPolicy,omitempty"`

// NodeSelector selects a node by key value pairs
// +optional
NodeSelector map[string]string `json:"nodeSelector,omitempty"`

// PodSecurityContext defines the security context for the pod
// +optional
PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"`
ChiaConfig ChiaFarmerSpecChia `json:"chia"`
}

// ChiaFarmerConfigSpec defines the desired state of Chia component configuration
type ChiaFarmerConfigSpec struct {
// CASecretName is the name of the secret that contains the CA crt and key.
CASecretName string `json:"caSecretName"`
// ChiaFarmerSpecChia defines the desired state of Chia component configuration
type ChiaFarmerSpecChia struct {
CommonSpecChia `json:",inline"`

// SecretKeySpec defines the k8s Secret name and key for a Chia mnemonic
SecretKeySpec ChiaKeysSpec `json:"secretKey"`
// SecretKey defines the k8s Secret name and key for a Chia mnemonic
SecretKey ChiaSecretKey `json:"secretKey"`

// FullNodePeer defines the farmer's full_node peer in host:port format.
// In Kubernetes this is likely to be <node service name>.<namespace>.svc.cluster.local:8555
FullNodePeer string `json:"fullNodePeer"`

// Testnet is set to true if the Chia container should switch to the latest default testnet's settings
// +optional
Testnet *bool `json:"testnet,omitempty"`

// LogLevel is set to the desired chia config log_level
// +optional
LogLevel *string `json:"logLevel,omitempty"`

// Timezone can be set to your local timezone for accurate timestamps. Defaults to UTC
// +optional
Timezone *string `json:"timezone,omitempty"`

// Image defines the image to use for the chia component containers
// +kubebuilder:default="ghcr.io/chia-network/chia:latest"
// +optional
Image string `json:"image"`

// Periodic probe of container liveness.
// +optional
LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty"`

// Periodic probe of container service readiness.
// +optional
ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty"`

// StartupProbe indicates that the Pod has successfully initialized.
// +optional
StartupProbe *corev1.Probe `json:"startupProbe,omitempty"`

// Resources defines the compute resources for the Chia container
// +optional
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`

// SecurityContext defines the security context for the chia container
// +optional
SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"`
}

// ChiaFarmerStatus defines the observed state of ChiaFarmer
Expand Down
Loading