diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index f7ccb80..ede6829 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -105,6 +105,15 @@ jobs: fi echo "Expected 1 endpoint, found $service_endpoints_number" + - name: Check to make sure ChiaNode all-port Service has one endpoint + run: | + service_endpoints_number=$(kubectl get endpoints chianode-test-node-all -o json | jq '.subsets[].addresses | length') + if [ "$service_endpoints_number" -ne 1 ]; then + echo "ChiaNode all-port Service was found to have $service_endpoints_number endpoints, expected 1" + exit 1 + fi + echo "Expected 1 endpoint, found $service_endpoints_number" + - name: Check to make sure ChiaNode RPC Service has one endpoint run: | service_endpoints_number=$(kubectl get endpoints chianode-test-node-rpc -o json | jq '.subsets[].addresses | length') diff --git a/api/v1/chiacommon_types.go b/api/v1/chiacommon_types.go index 5d9c254..bd1bcc6 100644 --- a/api/v1/chiacommon_types.go +++ b/api/v1/chiacommon_types.go @@ -129,6 +129,11 @@ type CommonSpecChia struct { // +optional RPCService Service `json:"rpcService,omitempty"` + // AllService defines settings for a Service that contains all the ports from the peer, daemon, and RPC Services installed with any Chia component resource. + // This Service will default to being enabled with a ClusterIP Service type. + // +optional + AllService Service `json:"allService,omitempty"` + // Periodic probe of container liveness. // +optional LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty"` diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 00118bf..01e1b63 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -1235,6 +1235,7 @@ func (in *CommonSpecChia) DeepCopyInto(out *CommonSpecChia) { in.PeerService.DeepCopyInto(&out.PeerService) in.DaemonService.DeepCopyInto(&out.DaemonService) in.RPCService.DeepCopyInto(&out.RPCService) + in.AllService.DeepCopyInto(&out.AllService) if in.LivenessProbe != nil { in, out := &in.LivenessProbe, &out.LivenessProbe *out = new(corev1.Probe) diff --git a/config/crd/bases/k8s.chia.net_chiacrawlers.yaml b/config/crd/bases/k8s.chia.net_chiacrawlers.yaml index d1e1d85..7258d11 100644 --- a/config/crd/bases/k8s.chia.net_chiacrawlers.yaml +++ b/config/crd/bases/k8s.chia.net_chiacrawlers.yaml @@ -970,6 +970,51 @@ spec: description: ChiaConfig defines the configuration options available to Chia component containers properties: + allService: + description: |- + AllService defines settings for a Service that contains all the ports from the peer, daemon, and RPC Services installed with any Chia component resource. + This Service will default to being enabled with a ClusterIP Service type. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of string keys and values + to attach to created objects + type: object + enabled: + description: Enabled is a boolean selector for a Service if + it should be generated. + type: boolean + ipFamilies: + description: IPFamilies represents a list of IP families (IPv4 + and/or IPv6) required by a Service + items: + description: |- + IPFamily represents the IP Family (IPv4 or IPv6). This type is used + to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). + type: string + type: array + ipFamilyPolicy: + description: IPFamilyPolicy represents the dual-stack-ness + requested or required by a Service + type: string + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values to + attach to created objects + type: object + rollIntoPeerService: + description: |- + RollIntoPeerService tells the controller to not actually generate this Service, but instead roll the Service ports of this Service into the peer Service. + The peer Service is often considered the primary Service generated for a chia resource, as it is the most likely Service to expose publicly. + This option is default, and only provides its functionality on chia-healthcheck Services. It may be included to other Services someday if a use case arises. + type: boolean + type: + description: ServiceType is the Type of the Service. Defaults + to ClusterIP + type: string + type: object caSecretName: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for seeders. diff --git a/config/crd/bases/k8s.chia.net_chiafarmers.yaml b/config/crd/bases/k8s.chia.net_chiafarmers.yaml index 7022f4e..c08fefc 100644 --- a/config/crd/bases/k8s.chia.net_chiafarmers.yaml +++ b/config/crd/bases/k8s.chia.net_chiafarmers.yaml @@ -970,6 +970,51 @@ spec: description: ChiaConfig defines the configuration options available to Chia component containers properties: + allService: + description: |- + AllService defines settings for a Service that contains all the ports from the peer, daemon, and RPC Services installed with any Chia component resource. + This Service will default to being enabled with a ClusterIP Service type. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of string keys and values + to attach to created objects + type: object + enabled: + description: Enabled is a boolean selector for a Service if + it should be generated. + type: boolean + ipFamilies: + description: IPFamilies represents a list of IP families (IPv4 + and/or IPv6) required by a Service + items: + description: |- + IPFamily represents the IP Family (IPv4 or IPv6). This type is used + to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). + type: string + type: array + ipFamilyPolicy: + description: IPFamilyPolicy represents the dual-stack-ness + requested or required by a Service + type: string + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values to + attach to created objects + type: object + rollIntoPeerService: + description: |- + RollIntoPeerService tells the controller to not actually generate this Service, but instead roll the Service ports of this Service into the peer Service. + The peer Service is often considered the primary Service generated for a chia resource, as it is the most likely Service to expose publicly. + This option is default, and only provides its functionality on chia-healthcheck Services. It may be included to other Services someday if a use case arises. + type: boolean + type: + description: ServiceType is the Type of the Service. Defaults + to ClusterIP + type: string + type: object caSecretName: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for seeders. diff --git a/config/crd/bases/k8s.chia.net_chiaharvesters.yaml b/config/crd/bases/k8s.chia.net_chiaharvesters.yaml index 7ccf7fd..51931ac 100644 --- a/config/crd/bases/k8s.chia.net_chiaharvesters.yaml +++ b/config/crd/bases/k8s.chia.net_chiaharvesters.yaml @@ -970,6 +970,51 @@ spec: description: ChiaConfig defines the configuration options available to Chia component containers properties: + allService: + description: |- + AllService defines settings for a Service that contains all the ports from the peer, daemon, and RPC Services installed with any Chia component resource. + This Service will default to being enabled with a ClusterIP Service type. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of string keys and values + to attach to created objects + type: object + enabled: + description: Enabled is a boolean selector for a Service if + it should be generated. + type: boolean + ipFamilies: + description: IPFamilies represents a list of IP families (IPv4 + and/or IPv6) required by a Service + items: + description: |- + IPFamily represents the IP Family (IPv4 or IPv6). This type is used + to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). + type: string + type: array + ipFamilyPolicy: + description: IPFamilyPolicy represents the dual-stack-ness + requested or required by a Service + type: string + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values to + attach to created objects + type: object + rollIntoPeerService: + description: |- + RollIntoPeerService tells the controller to not actually generate this Service, but instead roll the Service ports of this Service into the peer Service. + The peer Service is often considered the primary Service generated for a chia resource, as it is the most likely Service to expose publicly. + This option is default, and only provides its functionality on chia-healthcheck Services. It may be included to other Services someday if a use case arises. + type: boolean + type: + description: ServiceType is the Type of the Service. Defaults + to ClusterIP + type: string + type: object caSecretName: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for seeders. diff --git a/config/crd/bases/k8s.chia.net_chiaintroducers.yaml b/config/crd/bases/k8s.chia.net_chiaintroducers.yaml index 0749228..1c39db0 100644 --- a/config/crd/bases/k8s.chia.net_chiaintroducers.yaml +++ b/config/crd/bases/k8s.chia.net_chiaintroducers.yaml @@ -970,6 +970,51 @@ spec: description: ChiaConfig defines the configuration options available to Chia component containers properties: + allService: + description: |- + AllService defines settings for a Service that contains all the ports from the peer, daemon, and RPC Services installed with any Chia component resource. + This Service will default to being enabled with a ClusterIP Service type. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of string keys and values + to attach to created objects + type: object + enabled: + description: Enabled is a boolean selector for a Service if + it should be generated. + type: boolean + ipFamilies: + description: IPFamilies represents a list of IP families (IPv4 + and/or IPv6) required by a Service + items: + description: |- + IPFamily represents the IP Family (IPv4 or IPv6). This type is used + to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). + type: string + type: array + ipFamilyPolicy: + description: IPFamilyPolicy represents the dual-stack-ness + requested or required by a Service + type: string + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values to + attach to created objects + type: object + rollIntoPeerService: + description: |- + RollIntoPeerService tells the controller to not actually generate this Service, but instead roll the Service ports of this Service into the peer Service. + The peer Service is often considered the primary Service generated for a chia resource, as it is the most likely Service to expose publicly. + This option is default, and only provides its functionality on chia-healthcheck Services. It may be included to other Services someday if a use case arises. + type: boolean + type: + description: ServiceType is the Type of the Service. Defaults + to ClusterIP + type: string + type: object caSecretName: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for introducers. diff --git a/config/crd/bases/k8s.chia.net_chianodes.yaml b/config/crd/bases/k8s.chia.net_chianodes.yaml index 5371a6d..b0c227b 100644 --- a/config/crd/bases/k8s.chia.net_chianodes.yaml +++ b/config/crd/bases/k8s.chia.net_chianodes.yaml @@ -970,6 +970,51 @@ spec: description: ChiaConfig defines the configuration options available to Chia component containers properties: + allService: + description: |- + AllService defines settings for a Service that contains all the ports from the peer, daemon, and RPC Services installed with any Chia component resource. + This Service will default to being enabled with a ClusterIP Service type. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of string keys and values + to attach to created objects + type: object + enabled: + description: Enabled is a boolean selector for a Service if + it should be generated. + type: boolean + ipFamilies: + description: IPFamilies represents a list of IP families (IPv4 + and/or IPv6) required by a Service + items: + description: |- + IPFamily represents the IP Family (IPv4 or IPv6). This type is used + to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). + type: string + type: array + ipFamilyPolicy: + description: IPFamilyPolicy represents the dual-stack-ness + requested or required by a Service + type: string + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values to + attach to created objects + type: object + rollIntoPeerService: + description: |- + RollIntoPeerService tells the controller to not actually generate this Service, but instead roll the Service ports of this Service into the peer Service. + The peer Service is often considered the primary Service generated for a chia resource, as it is the most likely Service to expose publicly. + This option is default, and only provides its functionality on chia-healthcheck Services. It may be included to other Services someday if a use case arises. + type: boolean + type: + description: ServiceType is the Type of the Service. Defaults + to ClusterIP + type: string + type: object caSecretName: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for seeders. diff --git a/config/crd/bases/k8s.chia.net_chiaseeders.yaml b/config/crd/bases/k8s.chia.net_chiaseeders.yaml index 2115890..832fa39 100644 --- a/config/crd/bases/k8s.chia.net_chiaseeders.yaml +++ b/config/crd/bases/k8s.chia.net_chiaseeders.yaml @@ -970,6 +970,51 @@ spec: description: ChiaConfig defines the configuration options available to Chia component containers properties: + allService: + description: |- + AllService defines settings for a Service that contains all the ports from the peer, daemon, and RPC Services installed with any Chia component resource. + This Service will default to being enabled with a ClusterIP Service type. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of string keys and values + to attach to created objects + type: object + enabled: + description: Enabled is a boolean selector for a Service if + it should be generated. + type: boolean + ipFamilies: + description: IPFamilies represents a list of IP families (IPv4 + and/or IPv6) required by a Service + items: + description: |- + IPFamily represents the IP Family (IPv4 or IPv6). This type is used + to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). + type: string + type: array + ipFamilyPolicy: + description: IPFamilyPolicy represents the dual-stack-ness + requested or required by a Service + type: string + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values to + attach to created objects + type: object + rollIntoPeerService: + description: |- + RollIntoPeerService tells the controller to not actually generate this Service, but instead roll the Service ports of this Service into the peer Service. + The peer Service is often considered the primary Service generated for a chia resource, as it is the most likely Service to expose publicly. + This option is default, and only provides its functionality on chia-healthcheck Services. It may be included to other Services someday if a use case arises. + type: boolean + type: + description: ServiceType is the Type of the Service. Defaults + to ClusterIP + type: string + type: object bootstrapPeer: description: BootstrapPeer a peer to bootstrap the seeder's peer database diff --git a/config/crd/bases/k8s.chia.net_chiatimelords.yaml b/config/crd/bases/k8s.chia.net_chiatimelords.yaml index 5a89d9c..ca56ca4 100644 --- a/config/crd/bases/k8s.chia.net_chiatimelords.yaml +++ b/config/crd/bases/k8s.chia.net_chiatimelords.yaml @@ -970,6 +970,51 @@ spec: description: ChiaConfig defines the configuration options available to Chia component containers properties: + allService: + description: |- + AllService defines settings for a Service that contains all the ports from the peer, daemon, and RPC Services installed with any Chia component resource. + This Service will default to being enabled with a ClusterIP Service type. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of string keys and values + to attach to created objects + type: object + enabled: + description: Enabled is a boolean selector for a Service if + it should be generated. + type: boolean + ipFamilies: + description: IPFamilies represents a list of IP families (IPv4 + and/or IPv6) required by a Service + items: + description: |- + IPFamily represents the IP Family (IPv4 or IPv6). This type is used + to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). + type: string + type: array + ipFamilyPolicy: + description: IPFamilyPolicy represents the dual-stack-ness + requested or required by a Service + type: string + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values to + attach to created objects + type: object + rollIntoPeerService: + description: |- + RollIntoPeerService tells the controller to not actually generate this Service, but instead roll the Service ports of this Service into the peer Service. + The peer Service is often considered the primary Service generated for a chia resource, as it is the most likely Service to expose publicly. + This option is default, and only provides its functionality on chia-healthcheck Services. It may be included to other Services someday if a use case arises. + type: boolean + type: + description: ServiceType is the Type of the Service. Defaults + to ClusterIP + type: string + type: object caSecretName: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for seeders. diff --git a/config/crd/bases/k8s.chia.net_chiawallets.yaml b/config/crd/bases/k8s.chia.net_chiawallets.yaml index 45d65cf..8a9fb82 100644 --- a/config/crd/bases/k8s.chia.net_chiawallets.yaml +++ b/config/crd/bases/k8s.chia.net_chiawallets.yaml @@ -970,6 +970,51 @@ spec: description: ChiaConfig defines the configuration options available to Chia component containers properties: + allService: + description: |- + AllService defines settings for a Service that contains all the ports from the peer, daemon, and RPC Services installed with any Chia component resource. + This Service will default to being enabled with a ClusterIP Service type. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of string keys and values + to attach to created objects + type: object + enabled: + description: Enabled is a boolean selector for a Service if + it should be generated. + type: boolean + ipFamilies: + description: IPFamilies represents a list of IP families (IPv4 + and/or IPv6) required by a Service + items: + description: |- + IPFamily represents the IP Family (IPv4 or IPv6). This type is used + to express the family of an IP expressed by a type (e.g. service.spec.ipFamilies). + type: string + type: array + ipFamilyPolicy: + description: IPFamilyPolicy represents the dual-stack-ness + requested or required by a Service + type: string + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values to + attach to created objects + type: object + rollIntoPeerService: + description: |- + RollIntoPeerService tells the controller to not actually generate this Service, but instead roll the Service ports of this Service into the peer Service. + The peer Service is often considered the primary Service generated for a chia resource, as it is the most likely Service to expose publicly. + This option is default, and only provides its functionality on chia-healthcheck Services. It may be included to other Services someday if a use case arises. + type: boolean + type: + description: ServiceType is the Type of the Service. Defaults + to ClusterIP + type: string + type: object caSecretName: description: CASecretName is the name of the secret that contains the CA crt and key. Not required for seeders. diff --git a/internal/controller/chiacrawler/assemblers.go b/internal/controller/chiacrawler/assemblers.go index a9a98da..b81c50b 100644 --- a/internal/controller/chiacrawler/assemblers.go +++ b/internal/controller/chiacrawler/assemblers.go @@ -57,6 +57,50 @@ func assemblePeerService(crawler k8schianetv1.ChiaCrawler) corev1.Service { return kube.AssembleCommonService(inputs) } +// assembleAllService assembles the all-port Service resource for a ChiaCrawler CR +func assembleAllService(crawler k8schianetv1.ChiaCrawler) corev1.Service { + inputs := kube.AssembleCommonServiceInputs{ + Name: fmt.Sprintf(chiacrawlerNamePattern, crawler.Name) + "-all", + Namespace: crawler.Namespace, + Ports: []corev1.ServicePort{ + { + Port: kube.GetFullNodePort(crawler.Spec.ChiaConfig.CommonSpecChia), + TargetPort: intstr.FromString("peers"), + Protocol: "TCP", + Name: "peers", + }, + { + Port: consts.CrawlerRPCPort, + TargetPort: intstr.FromString("rpc"), + Protocol: "TCP", + Name: "rpc", + }, + }, + } + inputs.Ports = append(inputs.Ports, kube.GetChiaDaemonServicePorts()...) + + inputs.ServiceType = crawler.Spec.ChiaConfig.AllService.ServiceType + inputs.IPFamilyPolicy = crawler.Spec.ChiaConfig.AllService.IPFamilyPolicy + inputs.IPFamilies = crawler.Spec.ChiaConfig.AllService.IPFamilies + + // Labels + var additionalServiceLabels = make(map[string]string) + if crawler.Spec.ChiaConfig.AllService.Labels != nil { + additionalServiceLabels = crawler.Spec.ChiaConfig.AllService.Labels + } + inputs.Labels = kube.GetCommonLabels(crawler.Kind, crawler.ObjectMeta, crawler.Spec.AdditionalMetadata.Labels, additionalServiceLabels) + inputs.SelectorLabels = kube.GetCommonLabels(crawler.Kind, crawler.ObjectMeta, crawler.Spec.AdditionalMetadata.Labels) + + // Annotations + var additionalServiceAnnotations = make(map[string]string) + if crawler.Spec.ChiaConfig.AllService.Annotations != nil { + additionalServiceAnnotations = crawler.Spec.ChiaConfig.AllService.Annotations + } + inputs.Annotations = kube.CombineMaps(crawler.Spec.AdditionalMetadata.Annotations, additionalServiceAnnotations) + + return kube.AssembleCommonService(inputs) +} + // assembleDaemonService assembles the daemon Service resource for a ChiaCrawler CR func assembleDaemonService(crawler k8schianetv1.ChiaCrawler) corev1.Service { inputs := kube.AssembleCommonServiceInputs{ diff --git a/internal/controller/chiacrawler/controller.go b/internal/controller/chiacrawler/controller.go index baec6e3..aa6e30b 100644 --- a/internal/controller/chiacrawler/controller.go +++ b/internal/controller/chiacrawler/controller.go @@ -105,6 +105,39 @@ func (r *ChiaCrawlerReconciler) Reconcile(ctx context.Context, req ctrl.Request) } } + if kube.ShouldMakeService(crawler.Spec.ChiaConfig.AllService, true) { + srv := assembleAllService(crawler) + if err := controllerutil.SetControllerReference(&crawler, &srv, r.Scheme); err != nil { + return ctrl.Result{}, err + } + res, err := kube.ReconcileService(ctx, resourceReconciler, srv) + if err != nil { + if res == nil { + res = &reconcile.Result{} + } + metrics.OperatorErrors.Add(1.0) + r.Recorder.Event(&crawler, corev1.EventTypeWarning, "Failed", "Failed to create crawler all-ports Service -- Check operator logs.") + return *res, fmt.Errorf("ChiaCrawlerReconciler ChiaCrawler=%s encountered error reconciling crawler all-ports Service: %v", req.NamespacedName, err) + } + } else { + // Need to check if the resource exists and delete if it does + var srv corev1.Service + err := r.Get(ctx, types.NamespacedName{ + Namespace: req.NamespacedName.Namespace, + Name: fmt.Sprintf(chiacrawlerNamePattern, crawler.Name) + "-all", + }, &srv) + if err != nil { + if !errors.IsNotFound(err) { + log.Error(err, fmt.Sprintf("ChiaCrawlerReconciler ChiaCrawler=%s unable to GET ChiaCrawler all-ports Service resource", req.NamespacedName)) + } + } else { + err = r.Delete(ctx, &srv) + if err != nil { + log.Error(err, fmt.Sprintf("ChiaCrawlerReconciler ChiaCrawler=%s unable to DELETE ChiaCrawler all-ports Service resource", req.NamespacedName)) + } + } + } + if kube.ShouldMakeService(crawler.Spec.ChiaConfig.DaemonService, true) { srv := assembleDaemonService(crawler) if err := controllerutil.SetControllerReference(&crawler, &srv, r.Scheme); err != nil { diff --git a/internal/controller/chiafarmer/assemblers.go b/internal/controller/chiafarmer/assemblers.go index 4c6c59a..7cbf606 100644 --- a/internal/controller/chiafarmer/assemblers.go +++ b/internal/controller/chiafarmer/assemblers.go @@ -57,6 +57,50 @@ func assemblePeerService(farmer k8schianetv1.ChiaFarmer) corev1.Service { return kube.AssembleCommonService(inputs) } +// assembleAllService assembles the all-port Service resource for a ChiaFarmer CR +func assembleAllService(farmer k8schianetv1.ChiaFarmer) corev1.Service { + inputs := kube.AssembleCommonServiceInputs{ + Name: fmt.Sprintf(chiafarmerNamePattern, farmer.Name) + "-all", + Namespace: farmer.Namespace, + Ports: []corev1.ServicePort{ + { + Port: consts.FarmerPort, + TargetPort: intstr.FromString("peers"), + Protocol: "TCP", + Name: "peers", + }, + { + Port: consts.FarmerRPCPort, + TargetPort: intstr.FromString("rpc"), + Protocol: "TCP", + Name: "rpc", + }, + }, + } + inputs.Ports = append(inputs.Ports, kube.GetChiaDaemonServicePorts()...) + + inputs.ServiceType = farmer.Spec.ChiaConfig.AllService.ServiceType + inputs.IPFamilyPolicy = farmer.Spec.ChiaConfig.AllService.IPFamilyPolicy + inputs.IPFamilies = farmer.Spec.ChiaConfig.AllService.IPFamilies + + // Labels + var additionalServiceLabels = make(map[string]string) + if farmer.Spec.ChiaConfig.AllService.Labels != nil { + additionalServiceLabels = farmer.Spec.ChiaConfig.AllService.Labels + } + inputs.Labels = kube.GetCommonLabels(farmer.Kind, farmer.ObjectMeta, farmer.Spec.AdditionalMetadata.Labels, additionalServiceLabels) + inputs.SelectorLabels = kube.GetCommonLabels(farmer.Kind, farmer.ObjectMeta, farmer.Spec.AdditionalMetadata.Labels) + + // Annotations + var additionalServiceAnnotations = make(map[string]string) + if farmer.Spec.ChiaConfig.AllService.Annotations != nil { + additionalServiceAnnotations = farmer.Spec.ChiaConfig.AllService.Annotations + } + inputs.Annotations = kube.CombineMaps(farmer.Spec.AdditionalMetadata.Annotations, additionalServiceAnnotations) + + return kube.AssembleCommonService(inputs) +} + // assembleDaemonService assembles the daemon Service resource for a ChiaFarmer CR func assembleDaemonService(farmer k8schianetv1.ChiaFarmer) corev1.Service { inputs := kube.AssembleCommonServiceInputs{ diff --git a/internal/controller/chiafarmer/controller.go b/internal/controller/chiafarmer/controller.go index 57c7e6e..15039dd 100644 --- a/internal/controller/chiafarmer/controller.go +++ b/internal/controller/chiafarmer/controller.go @@ -107,6 +107,39 @@ func (r *ChiaFarmerReconciler) Reconcile(ctx context.Context, req ctrl.Request) } } + if kube.ShouldMakeService(farmer.Spec.ChiaConfig.AllService, true) { + srv := assembleAllService(farmer) + if err := controllerutil.SetControllerReference(&farmer, &srv, r.Scheme); err != nil { + return ctrl.Result{}, err + } + res, err := kube.ReconcileService(ctx, resourceReconciler, srv) + if err != nil { + if res == nil { + res = &reconcile.Result{} + } + metrics.OperatorErrors.Add(1.0) + r.Recorder.Event(&farmer, corev1.EventTypeWarning, "Failed", "Failed to create farmer all-ports Service -- Check operator logs.") + return *res, fmt.Errorf("ChiaFarmerReconciler ChiaFarmer=%s encountered error reconciling farmer all-ports Service: %v", req.NamespacedName, err) + } + } else { + // Need to check if the resource exists and delete if it does + var srv corev1.Service + err := r.Get(ctx, types.NamespacedName{ + Namespace: req.NamespacedName.Namespace, + Name: fmt.Sprintf(chiafarmerNamePattern, farmer.Name) + "-all", + }, &srv) + if err != nil { + if !errors.IsNotFound(err) { + log.Error(err, fmt.Sprintf("ChiaFarmerReconciler ChiaFarmer=%s unable to GET ChiaFarmer all-ports Service resource", req.NamespacedName)) + } + } else { + err = r.Delete(ctx, &srv) + if err != nil { + log.Error(err, fmt.Sprintf("ChiaFarmerReconciler ChiaFarmer=%s unable to DELETE ChiaFarmer all-ports Service resource", req.NamespacedName)) + } + } + } + if kube.ShouldMakeService(farmer.Spec.ChiaConfig.DaemonService, true) { srv := assembleDaemonService(farmer) if err := controllerutil.SetControllerReference(&farmer, &srv, r.Scheme); err != nil { diff --git a/internal/controller/chiaharvester/assemblers.go b/internal/controller/chiaharvester/assemblers.go index 7db4e19..3b6e8c0 100644 --- a/internal/controller/chiaharvester/assemblers.go +++ b/internal/controller/chiaharvester/assemblers.go @@ -57,6 +57,50 @@ func assemblePeerService(harvester k8schianetv1.ChiaHarvester) corev1.Service { return kube.AssembleCommonService(inputs) } +// assembleAllService assembles the all-port Service resource for a ChiaHarvester CR +func assembleAllService(harvester k8schianetv1.ChiaHarvester) corev1.Service { + inputs := kube.AssembleCommonServiceInputs{ + Name: fmt.Sprintf(chiaharvesterNamePattern, harvester.Name) + "-all", + Namespace: harvester.Namespace, + Ports: []corev1.ServicePort{ + { + Port: consts.HarvesterPort, + TargetPort: intstr.FromString("peers"), + Protocol: "TCP", + Name: "peers", + }, + { + Port: consts.HarvesterRPCPort, + TargetPort: intstr.FromString("rpc"), + Protocol: "TCP", + Name: "rpc", + }, + }, + } + inputs.Ports = append(inputs.Ports, kube.GetChiaDaemonServicePorts()...) + + inputs.ServiceType = harvester.Spec.ChiaConfig.AllService.ServiceType + inputs.IPFamilyPolicy = harvester.Spec.ChiaConfig.AllService.IPFamilyPolicy + inputs.IPFamilies = harvester.Spec.ChiaConfig.AllService.IPFamilies + + // Labels + var additionalServiceLabels = make(map[string]string) + if harvester.Spec.ChiaConfig.AllService.Labels != nil { + additionalServiceLabels = harvester.Spec.ChiaConfig.AllService.Labels + } + inputs.Labels = kube.GetCommonLabels(harvester.Kind, harvester.ObjectMeta, harvester.Spec.AdditionalMetadata.Labels, additionalServiceLabels) + inputs.SelectorLabels = kube.GetCommonLabels(harvester.Kind, harvester.ObjectMeta, harvester.Spec.AdditionalMetadata.Labels) + + // Annotations + var additionalServiceAnnotations = make(map[string]string) + if harvester.Spec.ChiaConfig.AllService.Annotations != nil { + additionalServiceAnnotations = harvester.Spec.ChiaConfig.AllService.Annotations + } + inputs.Annotations = kube.CombineMaps(harvester.Spec.AdditionalMetadata.Annotations, additionalServiceAnnotations) + + return kube.AssembleCommonService(inputs) +} + // assembleDaemonService assembles the daemon Service resource for a ChiaHarvester CR func assembleDaemonService(harvester k8schianetv1.ChiaHarvester) corev1.Service { inputs := kube.AssembleCommonServiceInputs{ diff --git a/internal/controller/chiaharvester/controller.go b/internal/controller/chiaharvester/controller.go index 848ad1f..0df90b6 100644 --- a/internal/controller/chiaharvester/controller.go +++ b/internal/controller/chiaharvester/controller.go @@ -107,6 +107,39 @@ func (r *ChiaHarvesterReconciler) Reconcile(ctx context.Context, req ctrl.Reques } } + if kube.ShouldMakeService(harvester.Spec.ChiaConfig.AllService, true) { + srv := assembleAllService(harvester) + if err := controllerutil.SetControllerReference(&harvester, &srv, r.Scheme); err != nil { + return ctrl.Result{}, err + } + res, err := kube.ReconcileService(ctx, resourceReconciler, srv) + if err != nil { + if res == nil { + res = &reconcile.Result{} + } + metrics.OperatorErrors.Add(1.0) + r.Recorder.Event(&harvester, corev1.EventTypeWarning, "Failed", "Failed to create harvester all-ports Service -- Check operator logs.") + return *res, fmt.Errorf("ChiaHarvesterReconciler ChiaHarvester=%s encountered error reconciling harvester all-ports Service: %v", req.NamespacedName, err) + } + } else { + // Need to check if the resource exists and delete if it does + var srv corev1.Service + err := r.Get(ctx, types.NamespacedName{ + Namespace: req.NamespacedName.Namespace, + Name: fmt.Sprintf(chiaharvesterNamePattern, harvester.Name) + "-all", + }, &srv) + if err != nil { + if !errors.IsNotFound(err) { + log.Error(err, fmt.Sprintf("ChiaHarvesterReconciler ChiaHarvester=%s unable to GET ChiaHarvester all-ports Service resource", req.NamespacedName)) + } + } else { + err = r.Delete(ctx, &srv) + if err != nil { + log.Error(err, fmt.Sprintf("ChiaHarvesterReconciler ChiaHarvester=%s unable to DELETE ChiaHarvester all-ports Service resource", req.NamespacedName)) + } + } + } + if kube.ShouldMakeService(harvester.Spec.ChiaConfig.DaemonService, true) { srv := assembleDaemonService(harvester) if err := controllerutil.SetControllerReference(&harvester, &srv, r.Scheme); err != nil { diff --git a/internal/controller/chiaintroducer/assemblers.go b/internal/controller/chiaintroducer/assemblers.go index 0b40490..f987932 100644 --- a/internal/controller/chiaintroducer/assemblers.go +++ b/internal/controller/chiaintroducer/assemblers.go @@ -27,7 +27,7 @@ func assemblePeerService(introducer k8schianetv1.ChiaIntroducer) corev1.Service Namespace: introducer.Namespace, Ports: []corev1.ServicePort{ { - Port: getFullNodePort(introducer), + Port: kube.GetFullNodePort(introducer.Spec.ChiaConfig.CommonSpecChia), TargetPort: intstr.FromString("peers"), Protocol: "TCP", Name: "peers", @@ -57,6 +57,44 @@ func assemblePeerService(introducer k8schianetv1.ChiaIntroducer) corev1.Service return kube.AssembleCommonService(inputs) } +// assembleAllService assembles the all-port Service resource for a ChiaIntroducer CR +func assembleAllService(introducer k8schianetv1.ChiaIntroducer) corev1.Service { + inputs := kube.AssembleCommonServiceInputs{ + Name: fmt.Sprintf(chiaintroducerNamePattern, introducer.Name) + "-all", + Namespace: introducer.Namespace, + Ports: []corev1.ServicePort{ + { + Port: kube.GetFullNodePort(introducer.Spec.ChiaConfig.CommonSpecChia), + TargetPort: intstr.FromString("peers"), + Protocol: "TCP", + Name: "peers", + }, + }, + } + inputs.Ports = append(inputs.Ports, kube.GetChiaDaemonServicePorts()...) + + inputs.ServiceType = introducer.Spec.ChiaConfig.AllService.ServiceType + inputs.IPFamilyPolicy = introducer.Spec.ChiaConfig.AllService.IPFamilyPolicy + inputs.IPFamilies = introducer.Spec.ChiaConfig.AllService.IPFamilies + + // Labels + var additionalServiceLabels = make(map[string]string) + if introducer.Spec.ChiaConfig.AllService.Labels != nil { + additionalServiceLabels = introducer.Spec.ChiaConfig.AllService.Labels + } + inputs.Labels = kube.GetCommonLabels(introducer.Kind, introducer.ObjectMeta, introducer.Spec.AdditionalMetadata.Labels, additionalServiceLabels) + inputs.SelectorLabels = kube.GetCommonLabels(introducer.Kind, introducer.ObjectMeta, introducer.Spec.AdditionalMetadata.Labels) + + // Annotations + var additionalServiceAnnotations = make(map[string]string) + if introducer.Spec.ChiaConfig.AllService.Annotations != nil { + additionalServiceAnnotations = introducer.Spec.ChiaConfig.AllService.Annotations + } + inputs.Annotations = kube.CombineMaps(introducer.Spec.AdditionalMetadata.Annotations, additionalServiceAnnotations) + + return kube.AssembleCommonService(inputs) +} + // assembleDaemonService assembles the daemon Service resource for a ChiaIntroducer CR func assembleDaemonService(introducer k8schianetv1.ChiaIntroducer) corev1.Service { inputs := kube.AssembleCommonServiceInputs{ diff --git a/internal/controller/chiaintroducer/controller.go b/internal/controller/chiaintroducer/controller.go index 5f5771b..d794ff4 100644 --- a/internal/controller/chiaintroducer/controller.go +++ b/internal/controller/chiaintroducer/controller.go @@ -106,6 +106,39 @@ func (r *ChiaIntroducerReconciler) Reconcile(ctx context.Context, req ctrl.Reque } } + if kube.ShouldMakeService(introducer.Spec.ChiaConfig.AllService, true) { + srv := assembleAllService(introducer) + if err := controllerutil.SetControllerReference(&introducer, &srv, r.Scheme); err != nil { + return ctrl.Result{}, err + } + res, err := kube.ReconcileService(ctx, resourceReconciler, srv) + if err != nil { + if res == nil { + res = &reconcile.Result{} + } + metrics.OperatorErrors.Add(1.0) + r.Recorder.Event(&introducer, corev1.EventTypeWarning, "Failed", "Failed to create introducer all-ports Service -- Check operator logs.") + return *res, fmt.Errorf("ChiaIntroducerReconciler ChiaIntroducer=%s encountered error reconciling introducer all-ports Service: %v", req.NamespacedName, err) + } + } else { + // Need to check if the resource exists and delete if it does + var srv corev1.Service + err := r.Get(ctx, types.NamespacedName{ + Namespace: req.NamespacedName.Namespace, + Name: fmt.Sprintf(chiaintroducerNamePattern, introducer.Name) + "-all", + }, &srv) + if err != nil { + if !errors.IsNotFound(err) { + log.Error(err, fmt.Sprintf("ChiaIntroducerReconciler ChiaIntroducer=%s unable to GET ChiaIntroducer all-ports Service resource", req.NamespacedName)) + } + } else { + err = r.Delete(ctx, &srv) + if err != nil { + log.Error(err, fmt.Sprintf("ChiaIntroducerReconciler ChiaIntroducer=%s unable to DELETE ChiaIntroducer all-ports Service resource", req.NamespacedName)) + } + } + } + if kube.ShouldMakeService(introducer.Spec.ChiaConfig.DaemonService, true) { srv := assembleDaemonService(introducer) if err := controllerutil.SetControllerReference(&introducer, &srv, r.Scheme); err != nil { diff --git a/internal/controller/chianode/assemblers.go b/internal/controller/chianode/assemblers.go index 83a007d..c0e81cb 100644 --- a/internal/controller/chianode/assemblers.go +++ b/internal/controller/chianode/assemblers.go @@ -62,6 +62,50 @@ func assemblePeerService(node k8schianetv1.ChiaNode) corev1.Service { return kube.AssembleCommonService(inputs) } +// assembleAllService assembles the all-port Service resource for a ChiaNode CR +func assembleAllService(node k8schianetv1.ChiaNode) corev1.Service { + inputs := kube.AssembleCommonServiceInputs{ + Name: fmt.Sprintf(chianodeNamePattern, node.Name) + "-all", + Namespace: node.Namespace, + Ports: []corev1.ServicePort{ + { + Port: kube.GetFullNodePort(node.Spec.ChiaConfig.CommonSpecChia), + TargetPort: intstr.FromString("peers"), + Protocol: "TCP", + Name: "peers", + }, + { + Port: consts.NodeRPCPort, + TargetPort: intstr.FromString("rpc"), + Protocol: "TCP", + Name: "rpc", + }, + }, + } + inputs.Ports = append(inputs.Ports, kube.GetChiaDaemonServicePorts()...) + + inputs.ServiceType = node.Spec.ChiaConfig.AllService.ServiceType + inputs.IPFamilyPolicy = node.Spec.ChiaConfig.AllService.IPFamilyPolicy + inputs.IPFamilies = node.Spec.ChiaConfig.AllService.IPFamilies + + // Labels + var additionalServiceLabels = make(map[string]string) + if node.Spec.ChiaConfig.AllService.Labels != nil { + additionalServiceLabels = node.Spec.ChiaConfig.AllService.Labels + } + inputs.Labels = kube.GetCommonLabels(node.Kind, node.ObjectMeta, node.Spec.AdditionalMetadata.Labels, additionalServiceLabels) + inputs.SelectorLabels = kube.GetCommonLabels(node.Kind, node.ObjectMeta, node.Spec.AdditionalMetadata.Labels) + + // Annotations + var additionalServiceAnnotations = make(map[string]string) + if node.Spec.ChiaConfig.AllService.Annotations != nil { + additionalServiceAnnotations = node.Spec.ChiaConfig.AllService.Annotations + } + inputs.Annotations = kube.CombineMaps(node.Spec.AdditionalMetadata.Annotations, additionalServiceAnnotations) + + return kube.AssembleCommonService(inputs) +} + // assembleDaemonService assembles the daemon Service resource for a ChiaNode CR func assembleDaemonService(node k8schianetv1.ChiaNode) corev1.Service { inputs := kube.AssembleCommonServiceInputs{ diff --git a/internal/controller/chianode/controller.go b/internal/controller/chianode/controller.go index 37cdca7..cc384b6 100644 --- a/internal/controller/chianode/controller.go +++ b/internal/controller/chianode/controller.go @@ -107,6 +107,39 @@ func (r *ChiaNodeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c } } + if kube.ShouldMakeService(node.Spec.ChiaConfig.AllService, true) { + srv := assembleAllService(node) + if err := controllerutil.SetControllerReference(&node, &srv, r.Scheme); err != nil { + return ctrl.Result{}, err + } + res, err := kube.ReconcileService(ctx, resourceReconciler, srv) + if err != nil { + if res == nil { + res = &reconcile.Result{} + } + metrics.OperatorErrors.Add(1.0) + r.Recorder.Event(&node, corev1.EventTypeWarning, "Failed", "Failed to create node all-ports Service -- Check operator logs.") + return *res, fmt.Errorf("ChiaNodeReconciler ChiaNode=%s encountered error reconciling node all-ports Service: %v", req.NamespacedName, err) + } + } else { + // Need to check if the resource exists and delete if it does + var srv corev1.Service + err := r.Get(ctx, types.NamespacedName{ + Namespace: req.NamespacedName.Namespace, + Name: fmt.Sprintf(chianodeNamePattern, node.Name) + "-all", + }, &srv) + if err != nil { + if !errors.IsNotFound(err) { + log.Error(err, fmt.Sprintf("ChiaNodeReconciler ChiaNode=%s unable to GET ChiaNode all-ports Service resource", req.NamespacedName)) + } + } else { + err = r.Delete(ctx, &srv) + if err != nil { + log.Error(err, fmt.Sprintf("ChiaNodeReconciler ChiaNode=%s unable to DELETE ChiaNode all-ports Service resource", req.NamespacedName)) + } + } + } + if kube.ShouldMakeService(node.Spec.ChiaConfig.PeerService, true) { srv := assembleHeadlessPeerService(node) if err := controllerutil.SetControllerReference(&node, &srv, r.Scheme); err != nil { diff --git a/internal/controller/chiaseeder/assemblers.go b/internal/controller/chiaseeder/assemblers.go index dad6b5d..4b92a23 100644 --- a/internal/controller/chiaseeder/assemblers.go +++ b/internal/controller/chiaseeder/assemblers.go @@ -74,6 +74,62 @@ func assemblePeerService(seeder k8schianetv1.ChiaSeeder) corev1.Service { return kube.AssembleCommonService(inputs) } +// assembleAllService assembles the all-port Service resource for a ChiaSeeder CR +func assembleAllService(seeder k8schianetv1.ChiaSeeder) corev1.Service { + inputs := kube.AssembleCommonServiceInputs{ + Name: fmt.Sprintf(chiaseederNamePattern, seeder.Name) + "-all", + Namespace: seeder.Namespace, + Ports: []corev1.ServicePort{ + { + Port: 53, + TargetPort: intstr.FromString("dns"), + Protocol: "UDP", + Name: "dns", + }, + { + Port: 53, + TargetPort: intstr.FromString("dns-tcp"), + Protocol: "TCP", + Name: "dns-tcp", + }, + { + Port: kube.GetFullNodePort(seeder.Spec.ChiaConfig.CommonSpecChia), + TargetPort: intstr.FromString("peers"), + Protocol: "TCP", + Name: "peers", + }, + { + Port: consts.CrawlerRPCPort, + TargetPort: intstr.FromString("rpc"), + Protocol: "TCP", + Name: "rpc", + }, + }, + } + inputs.Ports = append(inputs.Ports, kube.GetChiaDaemonServicePorts()...) + + inputs.ServiceType = seeder.Spec.ChiaConfig.AllService.ServiceType + inputs.IPFamilyPolicy = seeder.Spec.ChiaConfig.AllService.IPFamilyPolicy + inputs.IPFamilies = seeder.Spec.ChiaConfig.AllService.IPFamilies + + // Labels + var additionalServiceLabels = make(map[string]string) + if seeder.Spec.ChiaConfig.AllService.Labels != nil { + additionalServiceLabels = seeder.Spec.ChiaConfig.AllService.Labels + } + inputs.Labels = kube.GetCommonLabels(seeder.Kind, seeder.ObjectMeta, seeder.Spec.AdditionalMetadata.Labels, additionalServiceLabels) + inputs.SelectorLabels = kube.GetCommonLabels(seeder.Kind, seeder.ObjectMeta, seeder.Spec.AdditionalMetadata.Labels) + + // Annotations + var additionalServiceAnnotations = make(map[string]string) + if seeder.Spec.ChiaConfig.AllService.Annotations != nil { + additionalServiceAnnotations = seeder.Spec.ChiaConfig.AllService.Annotations + } + inputs.Annotations = kube.CombineMaps(seeder.Spec.AdditionalMetadata.Annotations, additionalServiceAnnotations) + + return kube.AssembleCommonService(inputs) +} + // assembleDaemonService assembles the daemon Service resource for a ChiaSeeder CR func assembleDaemonService(seeder k8schianetv1.ChiaSeeder) corev1.Service { inputs := kube.AssembleCommonServiceInputs{ diff --git a/internal/controller/chiaseeder/controller.go b/internal/controller/chiaseeder/controller.go index baea4c1..319df4d 100644 --- a/internal/controller/chiaseeder/controller.go +++ b/internal/controller/chiaseeder/controller.go @@ -122,6 +122,39 @@ func (r *ChiaSeederReconciler) Reconcile(ctx context.Context, req ctrl.Request) } } + if kube.ShouldMakeService(seeder.Spec.ChiaConfig.AllService, true) { + srv := assembleAllService(seeder) + if err := controllerutil.SetControllerReference(&seeder, &srv, r.Scheme); err != nil { + return ctrl.Result{}, err + } + res, err := kube.ReconcileService(ctx, resourceReconciler, srv) + if err != nil { + if res == nil { + res = &reconcile.Result{} + } + metrics.OperatorErrors.Add(1.0) + r.Recorder.Event(&seeder, corev1.EventTypeWarning, "Failed", "Failed to create seeder all-ports Service -- Check operator logs.") + return *res, fmt.Errorf("ChiaSeederReconciler ChiaSeeder=%s encountered error reconciling seeder all-ports Service: %v", req.NamespacedName, err) + } + } else { + // Need to check if the resource exists and delete if it does + var srv corev1.Service + err := r.Get(ctx, types.NamespacedName{ + Namespace: req.NamespacedName.Namespace, + Name: fmt.Sprintf(chiaseederNamePattern, seeder.Name) + "-all", + }, &srv) + if err != nil { + if !errors.IsNotFound(err) { + log.Error(err, fmt.Sprintf("ChiaSeederReconciler ChiaSeeder=%s unable to GET ChiaSeeder all-ports Service resource", req.NamespacedName)) + } + } else { + err = r.Delete(ctx, &srv) + if err != nil { + log.Error(err, fmt.Sprintf("ChiaSeederReconciler ChiaSeeder=%s unable to DELETE ChiaSeeder all-ports Service resource", req.NamespacedName)) + } + } + } + if kube.ShouldMakeService(seeder.Spec.ChiaConfig.DaemonService, true) { srv := assembleDaemonService(seeder) if err := controllerutil.SetControllerReference(&seeder, &srv, r.Scheme); err != nil { diff --git a/internal/controller/chiatimelord/assemblers.go b/internal/controller/chiatimelord/assemblers.go index 754d91e..51faf9b 100644 --- a/internal/controller/chiatimelord/assemblers.go +++ b/internal/controller/chiatimelord/assemblers.go @@ -57,6 +57,50 @@ func assemblePeerService(tl k8schianetv1.ChiaTimelord) corev1.Service { return kube.AssembleCommonService(inputs) } +// assembleAllService assembles the all-port Service resource for a ChiaTimelord CR +func assembleAllService(timelord k8schianetv1.ChiaTimelord) corev1.Service { + inputs := kube.AssembleCommonServiceInputs{ + Name: fmt.Sprintf(chiatimelordNamePattern, timelord.Name) + "-all", + Namespace: timelord.Namespace, + Ports: []corev1.ServicePort{ + { + Port: consts.TimelordPort, + TargetPort: intstr.FromString("peers"), + Protocol: "TCP", + Name: "peers", + }, + { + Port: consts.TimelordRPCPort, + TargetPort: intstr.FromString("rpc"), + Protocol: "TCP", + Name: "rpc", + }, + }, + } + inputs.Ports = append(inputs.Ports, kube.GetChiaDaemonServicePorts()...) + + inputs.ServiceType = timelord.Spec.ChiaConfig.AllService.ServiceType + inputs.IPFamilyPolicy = timelord.Spec.ChiaConfig.AllService.IPFamilyPolicy + inputs.IPFamilies = timelord.Spec.ChiaConfig.AllService.IPFamilies + + // Labels + var additionalServiceLabels = make(map[string]string) + if timelord.Spec.ChiaConfig.AllService.Labels != nil { + additionalServiceLabels = timelord.Spec.ChiaConfig.AllService.Labels + } + inputs.Labels = kube.GetCommonLabels(timelord.Kind, timelord.ObjectMeta, timelord.Spec.AdditionalMetadata.Labels, additionalServiceLabels) + inputs.SelectorLabels = kube.GetCommonLabels(timelord.Kind, timelord.ObjectMeta, timelord.Spec.AdditionalMetadata.Labels) + + // Annotations + var additionalServiceAnnotations = make(map[string]string) + if timelord.Spec.ChiaConfig.AllService.Annotations != nil { + additionalServiceAnnotations = timelord.Spec.ChiaConfig.AllService.Annotations + } + inputs.Annotations = kube.CombineMaps(timelord.Spec.AdditionalMetadata.Annotations, additionalServiceAnnotations) + + return kube.AssembleCommonService(inputs) +} + // assembleDaemonService assembles the daemon Service resource for a ChiaTimelord CR func assembleDaemonService(tl k8schianetv1.ChiaTimelord) corev1.Service { inputs := kube.AssembleCommonServiceInputs{ diff --git a/internal/controller/chiatimelord/controller.go b/internal/controller/chiatimelord/controller.go index 8f035a7..a05528d 100644 --- a/internal/controller/chiatimelord/controller.go +++ b/internal/controller/chiatimelord/controller.go @@ -86,7 +86,7 @@ func (r *ChiaTimelordReconciler) Reconcile(ctx context.Context, req ctrl.Request } metrics.OperatorErrors.Add(1.0) r.Recorder.Event(&tl, corev1.EventTypeWarning, "Failed", "Failed to create timelord peer Service -- Check operator logs.") - return *res, fmt.Errorf("ChiaFarmerReconciler ChiaFarmer=%s encountered error reconciling timelord peer Service: %v", req.NamespacedName, err) + return *res, fmt.Errorf("ChiaTimelordReconciler ChiaTimelord=%s encountered error reconciling timelord peer Service: %v", req.NamespacedName, err) } } else { // Need to check if the resource exists and delete if it does @@ -107,6 +107,39 @@ func (r *ChiaTimelordReconciler) Reconcile(ctx context.Context, req ctrl.Request } } + if kube.ShouldMakeService(tl.Spec.ChiaConfig.AllService, true) { + srv := assembleAllService(tl) + if err := controllerutil.SetControllerReference(&tl, &srv, r.Scheme); err != nil { + return ctrl.Result{}, err + } + res, err := kube.ReconcileService(ctx, resourceReconciler, srv) + if err != nil { + if res == nil { + res = &reconcile.Result{} + } + metrics.OperatorErrors.Add(1.0) + r.Recorder.Event(&tl, corev1.EventTypeWarning, "Failed", "Failed to create timelord all-ports Service -- Check operator logs.") + return *res, fmt.Errorf("ChiaTimelordReconciler ChiaTimelord=%s encountered error reconciling timelord all-ports Service: %v", req.NamespacedName, err) + } + } else { + // Need to check if the resource exists and delete if it does + var srv corev1.Service + err := r.Get(ctx, types.NamespacedName{ + Namespace: req.NamespacedName.Namespace, + Name: fmt.Sprintf(chiatimelordNamePattern, tl.Name) + "-all", + }, &srv) + if err != nil { + if !errors.IsNotFound(err) { + log.Error(err, fmt.Sprintf("ChiaTimelordReconciler ChiaTimelord=%s unable to GET ChiaTimelord all-ports Service resource", req.NamespacedName)) + } + } else { + err = r.Delete(ctx, &srv) + if err != nil { + log.Error(err, fmt.Sprintf("ChiaTimelordReconciler ChiaTimelord=%s unable to DELETE ChiaTimelord all-ports Service resource", req.NamespacedName)) + } + } + } + if kube.ShouldMakeService(tl.Spec.ChiaConfig.DaemonService, true) { srv := assembleDaemonService(tl) if err := controllerutil.SetControllerReference(&tl, &srv, r.Scheme); err != nil { @@ -119,7 +152,7 @@ func (r *ChiaTimelordReconciler) Reconcile(ctx context.Context, req ctrl.Request } metrics.OperatorErrors.Add(1.0) r.Recorder.Event(&tl, corev1.EventTypeWarning, "Failed", "Failed to create timelord daemon Service -- Check operator logs.") - return *res, fmt.Errorf("ChiaFarmerReconciler ChiaFarmer=%s encountered error reconciling timelord daemon Service: %v", req.NamespacedName, err) + return *res, fmt.Errorf("ChiaTimelordReconciler ChiaTimelord=%s encountered error reconciling timelord daemon Service: %v", req.NamespacedName, err) } } else { // Need to check if the resource exists and delete if it does @@ -154,7 +187,7 @@ func (r *ChiaTimelordReconciler) Reconcile(ctx context.Context, req ctrl.Request } metrics.OperatorErrors.Add(1.0) r.Recorder.Event(&tl, corev1.EventTypeWarning, "Failed", "Failed to create timelord RPC Service -- Check operator logs.") - return *res, fmt.Errorf("ChiaFarmerReconciler ChiaFarmer=%s encountered error reconciling timelord RPC Service: %v", req.NamespacedName, err) + return *res, fmt.Errorf("ChiaTimelordReconciler ChiaTimelord=%s encountered error reconciling timelord RPC Service: %v", req.NamespacedName, err) } } else { // Need to check if the resource exists and delete if it does @@ -189,7 +222,7 @@ func (r *ChiaTimelordReconciler) Reconcile(ctx context.Context, req ctrl.Request } metrics.OperatorErrors.Add(1.0) r.Recorder.Event(&tl, corev1.EventTypeWarning, "Failed", "Failed to create timelord metrics Service -- Check operator logs.") - return *res, fmt.Errorf("ChiaFarmerReconciler ChiaFarmer=%s encountered error reconciling timelord chia-exporter Service: %v", req.NamespacedName, err) + return *res, fmt.Errorf("ChiaTimelordReconciler ChiaTimelord=%s encountered error reconciling timelord chia-exporter Service: %v", req.NamespacedName, err) } } else { // Need to check if the resource exists and delete if it does diff --git a/internal/controller/chiawallet/assemblers.go b/internal/controller/chiawallet/assemblers.go index c55d072..c463c2c 100644 --- a/internal/controller/chiawallet/assemblers.go +++ b/internal/controller/chiawallet/assemblers.go @@ -57,6 +57,50 @@ func assemblePeerService(wallet k8schianetv1.ChiaWallet) corev1.Service { return kube.AssembleCommonService(inputs) } +// assembleAllService assembles the all-port Service resource for a ChiaWallet CR +func assembleAllService(wallet k8schianetv1.ChiaWallet) corev1.Service { + inputs := kube.AssembleCommonServiceInputs{ + Name: fmt.Sprintf(chiawalletNamePattern, wallet.Name) + "-all", + Namespace: wallet.Namespace, + Ports: []corev1.ServicePort{ + { + Port: consts.WalletPort, + TargetPort: intstr.FromString("peers"), + Protocol: "TCP", + Name: "peers", + }, + { + Port: consts.WalletRPCPort, + TargetPort: intstr.FromString("rpc"), + Protocol: "TCP", + Name: "rpc", + }, + }, + } + inputs.Ports = append(inputs.Ports, kube.GetChiaDaemonServicePorts()...) + + inputs.ServiceType = wallet.Spec.ChiaConfig.AllService.ServiceType + inputs.IPFamilyPolicy = wallet.Spec.ChiaConfig.AllService.IPFamilyPolicy + inputs.IPFamilies = wallet.Spec.ChiaConfig.AllService.IPFamilies + + // Labels + var additionalServiceLabels = make(map[string]string) + if wallet.Spec.ChiaConfig.AllService.Labels != nil { + additionalServiceLabels = wallet.Spec.ChiaConfig.AllService.Labels + } + inputs.Labels = kube.GetCommonLabels(wallet.Kind, wallet.ObjectMeta, wallet.Spec.AdditionalMetadata.Labels, additionalServiceLabels) + inputs.SelectorLabels = kube.GetCommonLabels(wallet.Kind, wallet.ObjectMeta, wallet.Spec.AdditionalMetadata.Labels) + + // Annotations + var additionalServiceAnnotations = make(map[string]string) + if wallet.Spec.ChiaConfig.AllService.Annotations != nil { + additionalServiceAnnotations = wallet.Spec.ChiaConfig.AllService.Annotations + } + inputs.Annotations = kube.CombineMaps(wallet.Spec.AdditionalMetadata.Annotations, additionalServiceAnnotations) + + return kube.AssembleCommonService(inputs) +} + // assembleDaemonService assembles the daemon Service resource for a ChiaWallet CR func assembleDaemonService(wallet k8schianetv1.ChiaWallet) corev1.Service { inputs := kube.AssembleCommonServiceInputs{ diff --git a/internal/controller/chiawallet/controller.go b/internal/controller/chiawallet/controller.go index 52e0539..834d4de 100644 --- a/internal/controller/chiawallet/controller.go +++ b/internal/controller/chiawallet/controller.go @@ -107,6 +107,39 @@ func (r *ChiaWalletReconciler) Reconcile(ctx context.Context, req ctrl.Request) } } + if kube.ShouldMakeService(wallet.Spec.ChiaConfig.AllService, true) { + srv := assembleAllService(wallet) + if err := controllerutil.SetControllerReference(&wallet, &srv, r.Scheme); err != nil { + return ctrl.Result{}, err + } + res, err := kube.ReconcileService(ctx, resourceReconciler, srv) + if err != nil { + if res == nil { + res = &reconcile.Result{} + } + metrics.OperatorErrors.Add(1.0) + r.Recorder.Event(&wallet, corev1.EventTypeWarning, "Failed", "Failed to create wallet all-ports Service -- Check operator logs.") + return *res, fmt.Errorf("ChiaWalletReconciler ChiaWallet=%s encountered error reconciling wallet all-ports Service: %v", req.NamespacedName, err) + } + } else { + // Need to check if the resource exists and delete if it does + var srv corev1.Service + err := r.Get(ctx, types.NamespacedName{ + Namespace: req.NamespacedName.Namespace, + Name: fmt.Sprintf(chiawalletNamePattern, wallet.Name) + "-all", + }, &srv) + if err != nil { + if !errors.IsNotFound(err) { + log.Error(err, fmt.Sprintf("ChiaWalletReconciler ChiaWallet=%s unable to GET ChiaWallet all-ports Service resource", req.NamespacedName)) + } + } else { + err = r.Delete(ctx, &srv) + if err != nil { + log.Error(err, fmt.Sprintf("ChiaWalletReconciler ChiaWallet=%s unable to DELETE ChiaWallet all-ports Service resource", req.NamespacedName)) + } + } + } + if kube.ShouldMakeService(wallet.Spec.ChiaConfig.DaemonService, true) { srv := assembleDaemonService(wallet) if err := controllerutil.SetControllerReference(&wallet, &srv, r.Scheme); err != nil { diff --git a/internal/controller/common/consts/consts.go b/internal/controller/common/consts/consts.go index 89e70e0..6ecd495 100644 --- a/internal/controller/common/consts/consts.go +++ b/internal/controller/common/consts/consts.go @@ -97,7 +97,7 @@ const ( // WalletPort defines the port for wallet instances WalletPort = 8449 - // walletRPCPort defines the port for the wallet RPC + // WalletRPCPort defines the port for the wallet RPC WalletRPCPort = 9256 // ChiaExporterPort defines the port for Chia Exporter instances