Skip to content
Draft
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 PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,16 @@ resources:
controller: true
domain: splunk.com
group: enterprise
kind: BusConfiguration
kind: Queue
path: github.com/splunk/splunk-operator/api/v4
version: v4
- api:
crdVersion: v1
namespaced: true
controller: true
domain: splunk.com
group: enterprise
kind: ObjectStorage
path: github.com/splunk/splunk-operator/api/v4
version: v4
version: "3"
17 changes: 13 additions & 4 deletions api/v4/indexercluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,18 @@ const (
IndexerClusterPausedAnnotation = "indexercluster.enterprise.splunk.com/paused"
)

// +kubebuilder:validation:XValidation:rule="has(self.queueRef) == has(self.objectStorageRef)",message="queueRef and objectStorageRef must both be set or both be empty"
// IndexerClusterSpec defines the desired state of a Splunk Enterprise indexer cluster
type IndexerClusterSpec struct {
CommonSplunkSpec `json:",inline"`

// Bus configuration reference
BusConfigurationRef corev1.ObjectReference `json:"busConfigurationRef,omitempty"`
// +optional
// Queue reference
QueueRef corev1.ObjectReference `json:"queueRef"`

// +optional
// Object Storage reference
ObjectStorageRef corev1.ObjectReference `json:"objectStorageRef"`

// Number of search head pods; a search head cluster will be created if > 1
Replicas int32 `json:"replicas"`
Expand Down Expand Up @@ -115,8 +121,11 @@ type IndexerClusterStatus struct {
// Auxillary message describing CR status
Message string `json:"message"`

// Bus configuration
BusConfiguration BusConfigurationSpec `json:"busConfiguration,omitempty"`
// Queue
Queue *QueueSpec `json:"queue,omitempty"`

// Object Storage
ObjectStorage *ObjectStorageSpec `json:"objectStorage,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand Down
16 changes: 12 additions & 4 deletions api/v4/ingestorcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,13 @@ type IngestorClusterSpec struct {
// Splunk Enterprise app repository that specifies remote app location and scope for Splunk app management
AppFrameworkConfig AppFrameworkSpec `json:"appRepo,omitempty"`

// Bus configuration reference
BusConfigurationRef corev1.ObjectReference `json:"busConfigurationRef"`
// +kubebuilder:validation:Required
// Queue reference
QueueRef corev1.ObjectReference `json:"queueRef"`

// +kubebuilder:validation:Required
// Object Storage reference
ObjectStorageRef corev1.ObjectReference `json:"objectStorageRef"`
}

// IngestorClusterStatus defines the observed state of Ingestor Cluster
Expand Down Expand Up @@ -69,8 +74,11 @@ type IngestorClusterStatus struct {
// Auxillary message describing CR status
Message string `json:"message"`

// Bus configuration
BusConfiguration BusConfigurationSpec `json:"busConfiguration,omitempty"`
// Queue
Queue *QueueSpec `json:"queue,omitempty"`

// Object Storage
ObjectStorage *ObjectStorageSpec `json:"objectStorage,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
138 changes: 138 additions & 0 deletions api/v4/objectstorage_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
Copyright 2025.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v4

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

const (
// ObjectStoragePausedAnnotation is the annotation that pauses the reconciliation (triggers
// an immediate requeue)
ObjectStoragePausedAnnotation = "objectstorage.enterprise.splunk.com/paused"
)

// +kubebuilder:validation:XValidation:rule="self.provider != 's3' || has(self.s3)",message="s3 must be provided when provider is s3"
// ObjectStorageSpec defines the desired state of ObjectStorage
type ObjectStorageSpec struct {
// +kubebuilder:validation:Required
// +kubebuilder:validation:Enum=s3
// Provider of queue resources
Provider string `json:"provider"`

// +kubebuilder:validation:Required
// s3 specific inputs
S3 S3Spec `json:"s3"`
}

type S3Spec struct {
// +optional
// +kubebuilder:validation:Pattern=`^https?://[^\s/$.?#].[^\s]*$`
// S3-compatible Service endpoint
Endpoint string `json:"endpoint"`

// +kubebuilder:validation:Required
// +kubebuilder:validation:Pattern=`^s3://[a-z0-9.-]{3,63}(?:/[^\s]+)?$`
// S3 bucket path
Path string `json:"path"`
}

// ObjectStorageStatus defines the observed state of ObjectStorage.
type ObjectStorageStatus struct {
// Phase of the large message store
Phase Phase `json:"phase"`

// Resource revision tracker
ResourceRevMap map[string]string `json:"resourceRevMap"`

// Auxillary message describing CR status
Message string `json:"message"`
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// ObjectStorage is the Schema for a Splunk Enterprise object storage
// +k8s:openapi-gen=true
// +kubebuilder:subresource:status
// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector
// +kubebuilder:resource:path=objectstorages,scope=Namespaced,shortName=os
// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="Status of object storage"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Age of object storage resource"
// +kubebuilder:printcolumn:name="Message",type="string",JSONPath=".status.message",description="Auxillary message describing CR status"
// +kubebuilder:storageversion

// ObjectStorage is the Schema for the objectstorages API
type ObjectStorage struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty,omitzero"`

Spec ObjectStorageSpec `json:"spec"`
Status ObjectStorageStatus `json:"status,omitempty,omitzero"`
}

// DeepCopyObject implements runtime.Object
func (in *ObjectStorage) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}

// +kubebuilder:object:root=true

// ObjectStorageList contains a list of ObjectStorage
type ObjectStorageList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ObjectStorage `json:"items"`
}

func init() {
SchemeBuilder.Register(&ObjectStorage{}, &ObjectStorageList{})
}

// NewEvent creates a new event associated with the object and ready
// to be published to Kubernetes API
func (os *ObjectStorage) NewEvent(eventType, reason, message string) corev1.Event {
t := metav1.Now()
return corev1.Event{
ObjectMeta: metav1.ObjectMeta{
GenerateName: reason + "-",
Namespace: os.ObjectMeta.Namespace,
},
InvolvedObject: corev1.ObjectReference{
Kind: "ObjectStorage",
Namespace: os.Namespace,
Name: os.Name,
UID: os.UID,
APIVersion: GroupVersion.String(),
},
Reason: reason,
Message: message,
Source: corev1.EventSource{
Component: "splunk-object-storage-controller",
},
FirstTimestamp: t,
LastTimestamp: t,
Count: 1,
Type: eventType,
ReportingController: "enterprise.splunk.com/object-storage-controller",
}
}
88 changes: 51 additions & 37 deletions api/v4/busconfiguration_types.go → api/v4/queue_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,35 +23,49 @@ import (
)

const (
// BusConfigurationPausedAnnotation is the annotation that pauses the reconciliation (triggers
// QueuePausedAnnotation is the annotation that pauses the reconciliation (triggers
// an immediate requeue)
BusConfigurationPausedAnnotation = "busconfiguration.enterprise.splunk.com/paused"
QueuePausedAnnotation = "queue.enterprise.splunk.com/paused"
)

// BusConfigurationSpec defines the desired state of BusConfiguration
type BusConfigurationSpec struct {
Type string `json:"type"`
// +kubebuilder:validation:XValidation:rule="self.provider != 'sqs' || has(self.sqs)",message="sqs must be provided when provider is sqs"
// QueueSpec defines the desired state of Queue
type QueueSpec struct {
// +kubebuilder:validation:Required
// +kubebuilder:validation:Enum=sqs
// Provider of queue resources
Provider string `json:"provider"`

// +kubebuilder:validation:Required
// sqs specific inputs
SQS SQSSpec `json:"sqs"`
}

type SQSSpec struct {
QueueName string `json:"queueName"`

// +kubebuilder:validation:Required
// +kubebuilder:validation:MinLength=1
// Name of the queue
Name string `json:"name"`

// +optional
// +kubebuilder:validation:Pattern=`^(?:us|ap|eu|me|af|sa|ca|cn|il)(?:-[a-z]+){1,3}-\d$`
// Auth Region of the resources
AuthRegion string `json:"authRegion"`

Endpoint string `json:"endpoint"`

LargeMessageStoreEndpoint string `json:"largeMessageStoreEndpoint"`
// +kubebuilder:validation:Required
// +kubebuilder:validation:MinLength=1
// Name of the dead letter queue resource
DLQ string `json:"dlq"`

LargeMessageStorePath string `json:"largeMessageStorePath"`

DeadLetterQueueName string `json:"deadLetterQueueName"`
// +optional
// +kubebuilder:validation:Pattern=`^https?://[^\s/$.?#].[^\s]*$`
// Amazon SQS Service endpoint
Endpoint string `json:"endpoint"`
}

// BusConfigurationStatus defines the observed state of BusConfiguration.
type BusConfigurationStatus struct {
// Phase of the bus configuration
// QueueStatus defines the observed state of Queue
type QueueStatus struct {
// Phase of the queue
Phase Phase `json:"phase"`

// Resource revision tracker
Expand All @@ -64,27 +78,27 @@ type BusConfigurationStatus struct {
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// BusConfiguration is the Schema for a Splunk Enterprise bus configuration
// Queue is the Schema for a Splunk Enterprise queue
// +k8s:openapi-gen=true
// +kubebuilder:subresource:status
// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector
// +kubebuilder:resource:path=busconfigurations,scope=Namespaced,shortName=bus
// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="Status of bus configuration"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Age of bus configuration resource"
// +kubebuilder:resource:path=queues,scope=Namespaced,shortName=queue
// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="Status of queue"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Age of queue resource"
// +kubebuilder:printcolumn:name="Message",type="string",JSONPath=".status.message",description="Auxillary message describing CR status"
// +kubebuilder:storageversion

// BusConfiguration is the Schema for the busconfigurations API
type BusConfiguration struct {
// Queue is the Schema for the queues API
type Queue struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty,omitzero"`

Spec BusConfigurationSpec `json:"spec"`
Status BusConfigurationStatus `json:"status,omitempty,omitzero"`
Spec QueueSpec `json:"spec"`
Status QueueStatus `json:"status,omitempty,omitzero"`
}

// DeepCopyObject implements runtime.Object
func (in *BusConfiguration) DeepCopyObject() runtime.Object {
func (in *Queue) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
Expand All @@ -93,42 +107,42 @@ func (in *BusConfiguration) DeepCopyObject() runtime.Object {

// +kubebuilder:object:root=true

// BusConfigurationList contains a list of BusConfiguration
type BusConfigurationList struct {
// QueueList contains a list of Queue
type QueueList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []BusConfiguration `json:"items"`
Items []Queue `json:"items"`
}

func init() {
SchemeBuilder.Register(&BusConfiguration{}, &BusConfigurationList{})
SchemeBuilder.Register(&Queue{}, &QueueList{})
}

// NewEvent creates a new event associated with the object and ready
// to be published to Kubernetes API
func (bc *BusConfiguration) NewEvent(eventType, reason, message string) corev1.Event {
func (os *Queue) NewEvent(eventType, reason, message string) corev1.Event {
t := metav1.Now()
return corev1.Event{
ObjectMeta: metav1.ObjectMeta{
GenerateName: reason + "-",
Namespace: bc.ObjectMeta.Namespace,
Namespace: os.ObjectMeta.Namespace,
},
InvolvedObject: corev1.ObjectReference{
Kind: "BusConfiguration",
Namespace: bc.Namespace,
Name: bc.Name,
UID: bc.UID,
Kind: "Queue",
Namespace: os.Namespace,
Name: os.Name,
UID: os.UID,
APIVersion: GroupVersion.String(),
},
Reason: reason,
Message: message,
Source: corev1.EventSource{
Component: "splunk-busconfiguration-controller",
Component: "splunk-queue-controller",
},
FirstTimestamp: t,
LastTimestamp: t,
Count: 1,
Type: eventType,
ReportingController: "enterprise.splunk.com/busconfiguration-controller",
ReportingController: "enterprise.splunk.com/queue-controller",
}
}
Loading
Loading