Skip to content

Commit cfd3cd7

Browse files
committed
CSPL-4022 Addressing PR comments
1 parent c6972f7 commit cfd3cd7

File tree

7 files changed

+144
-22
lines changed

7 files changed

+144
-22
lines changed

cmd/main.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ import (
4848

4949
enterpriseApiV3 "github.com/splunk/splunk-operator/api/v3"
5050
enterpriseApi "github.com/splunk/splunk-operator/api/v4"
51-
enterprisev4 "github.com/splunk/splunk-operator/api/v4"
5251
"github.com/splunk/splunk-operator/internal/controller"
5352
//+kubebuilder:scaffold:imports
5453
//extapi "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
@@ -63,7 +62,6 @@ func init() {
6362
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
6463
utilruntime.Must(enterpriseApi.AddToScheme(scheme))
6564
utilruntime.Must(enterpriseApiV3.AddToScheme(scheme))
66-
utilruntime.Must(enterprisev4.AddToScheme(scheme))
6765
//+kubebuilder:scaffold:scheme
6866
//utilruntime.Must(extapi.AddToScheme(scheme))
6967
}

docs/AppFramework.md

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
- [App Framework Fields](#description-of-app-framework-specification-fields)
2222
- [App Framework Examples](#examples-of-app-framework-usage)
2323
- [Standalone](#how-to-use-the-app-framework-on-a-standalone-cr)
24+
- [Ingestor Cluster](#how-to-use-the-app-framework-on-ingestor-cluster)
2425
- [Cluster Manager](#how-to-use-the-app-framework-on-indexer-cluster)
2526
- [Search Head Cluster](#how-to-use-the-app-framework-on-search-head-cluster)
2627
- [Multiple Scopes](#how-to-install-apps-for-both-local-and-cluster-scopes)
@@ -812,11 +813,11 @@ Copy your Splunk App or Add-on archive files to the unique folders on the remote
812813
813814
814815
## Description of App Framework Specification fields
815-
The App Framework configuration is supported on the following Custom Resources: Standalone, ClusterManager, SearchHeadCluster, MonitoringConsole and LicenseManager. Configuring the App framework requires:
816+
The App Framework configuration is supported on the following Custom Resources: Standalone, IngestorCluster, ClusterManager, SearchHeadCluster, MonitoringConsole and LicenseManager. Configuring the App framework requires:
816817
817818
* Remote Source of Apps: Define the remote storage location, including unique folders, and the path to each folder.
818819
* Destination of Apps: Define which Custom Resources need to be configured.
819-
* Scope of Apps: Define if the apps need to be installed and run locally (such as Standalone, Monitoring Console and License Manager,) or cluster-wide (such as Indexer Cluster, and Search Head Cluster.)
820+
* Scope of Apps: Define if the apps need to be installed and run locally (such as Standalone, Monitoring Console, License Manager and Ingestor Cluster) or cluster-wide (such as Indexer Cluster, and Search Head Cluster.)
820821
821822
Here is a typical App framework configuration in a Custom Resource definition:
822823
@@ -931,6 +932,7 @@ NOTE: If an app source name needs to be changed, make sure the name change is pe
931932
| Standalone | local | Yes | $SPLUNK_HOME/etc/apps | N/A |
932933
| LicenseManager | local | Yes | $SPLUNK_HOME/etc/apps | N/A |
933934
| MonitoringConsole | local | Yes | $SPLUNK_HOME/etc/apps | N/A |
935+
| IngestorCluster | local | Yes | $SPLUNK_HOME/etc/apps | N/A |
934936
| IndexerCluster | N/A | No | N/A | $SPLUNK_HOME/etc/peer-apps |
935937
936938
* `volume` refers to the remote storage volume name configured under the `volumes` stanza (see previous section.)
@@ -1008,6 +1010,69 @@ volumes:
10081010

10091011
Apply the Custom Resource specification: `kubectl apply -f Standalone.yaml`
10101012

1013+
### How to use the App Framework on Ingestor Cluster
1014+
1015+
In this example, you'll deploy Ingestor Cluster with a remote storage volume, the location of the app archive, and set the installation location for the Splunk Enterprise Pod instance by using `scope`.
1016+
1017+
Example using s3: IngestorCluster.yaml
1018+
1019+
```yaml
1020+
apiVersion: enterprise.splunk.com/v4
1021+
kind: IngestorCluster
1022+
metadata:
1023+
name: ic
1024+
finalizers:
1025+
- enterprise.splunk.com/delete-pvc
1026+
spec:
1027+
replicas: 1
1028+
appRepo:
1029+
appsRepoPollIntervalSeconds: 600
1030+
defaults:
1031+
volumeName: volume_app_repo
1032+
scope: local
1033+
appSources:
1034+
- name: networkApps
1035+
location: networkAppsLoc/
1036+
- name: authApps
1037+
location: authAppsLoc/
1038+
volumes:
1039+
- name: volume_app_repo
1040+
storageType: s3
1041+
provider: aws
1042+
path: bucket-app-framework/IngestorCluster-us/
1043+
endpoint: https://s3-us-west-2.amazonaws.com
1044+
region: us-west-2
1045+
secretRef: s3-secret
1046+
```
1047+
1048+
Volume variants for other providers (replace only the volumes stanza):
1049+
1050+
Azure Blob volumes snippet:
1051+
1052+
```yaml
1053+
volumes:
1054+
- name: volume_app_repo
1055+
storageType: blob
1056+
provider: azure
1057+
path: bucket-app-framework/IngestorCluster-us/
1058+
endpoint: https://mystorageaccount.blob.core.windows.net
1059+
secretRef: azureblob-secret
1060+
```
1061+
1062+
GCP GCS volumes snippet:
1063+
1064+
```yaml
1065+
volumes:
1066+
- name: volume_app_repo
1067+
storageType: gcs
1068+
provider: gcp
1069+
path: bucket-app-framework/IngestorCluster-us/
1070+
endpoint: https://storage.googleapis.com
1071+
secretRef: gcs-secret
1072+
```
1073+
1074+
Apply the Custom Resource specification: `kubectl apply -f IngestorCluster.yaml`
1075+
10111076
### How to use the App Framework on Indexer Cluster
10121077
10131078
This example describes the installation of apps on an Indexer Cluster and Cluster Manager. This is achieved by deploying a ClusterManager CR with a remote storage volume, setting the location of the app archives, and the installation scope to support both local and cluster app path distribution.

docs/CustomResources.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ you can use to manage Splunk Enterprise deployments in your Kubernetes cluster.
1313
- [SearchHeadCluster Resource Spec Parameters](#searchheadcluster-resource-spec-parameters)
1414
- [ClusterManager Resource Spec Parameters](#clustermanager-resource-spec-parameters)
1515
- [IndexerCluster Resource Spec Parameters](#indexercluster-resource-spec-parameters)
16+
- [IngestorCluster Resource Spec Parameters](#ingestorcluster-resource-spec-parameters)
1617
- [MonitoringConsole Resource Spec Parameters](#monitoringconsole-resource-spec-parameters)
1718
- [Examples of Guaranteed and Burstable QoS](#examples-of-guaranteed-and-burstable-qos)
1819
- [A Guaranteed QoS Class example:](#a-guaranteed-qos-class-example)
@@ -134,7 +135,7 @@ spec:
134135

135136
The following additional configuration parameters may be used for all Splunk
136137
Enterprise resources, including: `Standalone`, `LicenseManager`,
137-
`SearchHeadCluster`, `ClusterManager` and `IndexerCluster`:
138+
`SearchHeadCluster`, `ClusterManager`, `IndexerCluster` and `IngestorCluster`:
138139

139140
| Key | Type | Description |
140141
| ------------------ | ------- | ----------------------------------------------------------------------------- |
@@ -321,6 +322,27 @@ the `IndexerCluster` resource provides the following `Spec` configuration parame
321322
| ---------- | ------- | ----------------------------------------------------- |
322323
| replicas | integer | The number of indexer cluster members (minimum of 3, which is the default) |
323324

325+
## IngestorCluster Resource Spec Parameters
326+
327+
```yaml
328+
apiVersion: enterprise.splunk.com/v4
329+
kind: IngestorCluster
330+
metadata:
331+
name: ic
332+
spec:
333+
replicas: 3
334+
busConfigurationRef:
335+
name: bus-config
336+
```
337+
Note: `busConfigurationRef` is required field in case of IngestorCluster resource since it will be used to connect the IngestorCluster to BusConfiguration resource.
338+
339+
In addition to [Common Spec Parameters for All Resources](#common-spec-parameters-for-all-resources)
340+
and [Common Spec Parameters for All Splunk Enterprise Resources](#common-spec-parameters-for-all-splunk-enterprise-resources),
341+
the `IngestorCluster` resource provides the following `Spec` configuration parameters:
342+
343+
| Key | Type | Description |
344+
| ---------- | ------- | ----------------------------------------------------- |
345+
| replicas | integer | The number of ingestor peers (minimum of 3 which is the default) |
324346

325347
## MonitoringConsole Resource Spec Parameters
326348

@@ -436,6 +458,7 @@ The Splunk Operator controller reconciles every Splunk Enterprise CR. However, t
436458
| clustermaster.enterprise.splunk.com | "clustermaster.enterprise.splunk.com/paused" |
437459
| clustermanager.enterprise.splunk.com | "clustermanager.enterprise.splunk.com/paused" |
438460
| indexercluster.enterprise.splunk.com | "indexercluster.enterprise.splunk.com/paused" |
461+
| ingestorcluster.enterprise.splunk.com | "ingestorcluster.enterprise.splunk.com/paused" |
439462
| licensemaster.enterprise.splunk.com | "licensemaster.enterprise.splunk.com/paused" |
440463
| monitoringconsole.enterprise.splunk.com | "monitoringconsole.enterprise.splunk.com/paused" |
441464
| searchheadcluster.enterprise.splunk.com | "searchheadcluster.enterprise.splunk.com/paused" |
@@ -505,6 +528,7 @@ Below is a table listing `app.kubernetes.io/name` values mapped to CRDs
505528
| clustermanager.enterprise.splunk.com | cluster-manager |
506529
| clustermaster.enterprise.splunk.com | cluster-master |
507530
| indexercluster.enterprise.splunk.com | indexer-cluster |
531+
| ingestorcluster.enterprise.splunk.com | ingestor-cluster |
508532
| licensemanager.enterprise.splunk.com | license-manager |
509533
| licensemaster.enterprise.splunk.com | license-master |
510534
| monitoringconsole.enterprise.splunk.com | monitoring-console |

pkg/splunk/client/enterprise.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"strings"
2727
"time"
2828

29+
"github.com/go-logr/logr"
2930
splcommon "github.com/splunk/splunk-operator/pkg/splunk/common"
3031
)
3132

@@ -969,19 +970,23 @@ func (c *SplunkClient) RestartSplunk() error {
969970

970971
// Updates conf files and their properties
971972
// See https://help.splunk.com/en/splunk-enterprise/leverage-rest-apis/rest-api-reference/10.0/configuration-endpoints/configuration-endpoint-descriptions
972-
func (c *SplunkClient) UpdateConfFile(fileName, property string, propertyKVList [][]string) error {
973+
func (c *SplunkClient) UpdateConfFile(scopedLog logr.Logger, fileName, property string, propertyKVList [][]string) error {
973974
// Creates an object in a conf file if it doesn't exist
974975
endpoint := fmt.Sprintf("%s/servicesNS/nobody/system/configs/conf-%s", c.ManagementURI, fileName)
975976
body := fmt.Sprintf("name=%s", property)
976977

978+
scopedLog.Info("Creating conf file object if it does not exist", "fileName", fileName, "property", property)
977979
request, err := http.NewRequest("POST", endpoint, strings.NewReader(body))
978980
if err != nil {
981+
scopedLog.Error(err, "Failed to create conf file object if it does not exist", "fileName", fileName, "property", property)
979982
return err
980983
}
981984

985+
scopedLog.Info("Validating conf file object creation", "fileName", fileName, "property", property)
982986
expectedStatus := []int{200, 201, 409}
983987
err = c.Do(request, expectedStatus, nil)
984988
if err != nil {
989+
scopedLog.Error(err, fmt.Sprintf("Status not in %v for conf file object creation", expectedStatus), "fileName", fileName, "property", property)
985990
return err
986991
}
987992

@@ -995,25 +1000,37 @@ func (c *SplunkClient) UpdateConfFile(fileName, property string, propertyKVList
9951000
body = body[:len(body)-1]
9961001
}
9971002

1003+
scopedLog.Info("Updating conf file object", "fileName", fileName, "property", property, "body", body)
9981004
request, err = http.NewRequest("POST", endpoint, strings.NewReader(body))
9991005
if err != nil {
1006+
scopedLog.Error(err, "Failed to update conf file object", "fileName", fileName, "property", property, "body", body)
10001007
return err
10011008
}
10021009

1010+
scopedLog.Info("Validating conf file object update", "fileName", fileName, "property", property)
10031011
expectedStatus = []int{200, 201}
10041012
err = c.Do(request, expectedStatus, nil)
1013+
if err != nil {
1014+
scopedLog.Error(err, fmt.Sprintf("Status not in %v for conf file object update", expectedStatus), "fileName", fileName, "property", property, "body", body)
1015+
}
10051016
return err
10061017
}
10071018

10081019
// Deletes conf files properties
1009-
func (c *SplunkClient) DeleteConfFileProperty(fileName, property string) error {
1020+
func (c *SplunkClient) DeleteConfFileProperty(scopedLog logr.Logger, fileName, property string) error {
10101021
endpoint := fmt.Sprintf("%s/servicesNS/nobody/system/configs/conf-%s/%s", c.ManagementURI, fileName, property)
10111022

1023+
scopedLog.Info("Deleting conf file object", "fileName", fileName, "property", property)
10121024
request, err := http.NewRequest("DELETE", endpoint, nil)
10131025
if err != nil {
1026+
scopedLog.Error(err, "Failed to delete conf file object", "fileName", fileName, "property", property)
10141027
return err
10151028
}
10161029

10171030
expectedStatus := []int{200, 201, 404}
1018-
return c.Do(request, expectedStatus, nil)
1031+
err = c.Do(request, expectedStatus, nil)
1032+
if err != nil {
1033+
scopedLog.Error(err, fmt.Sprintf("Status not in %v for conf file object deletion", expectedStatus), "fileName", fileName, "property", property)
1034+
}
1035+
return err
10191036
}

pkg/splunk/client/enterprise_test.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
package client
1717

1818
import (
19+
"context"
1920
"fmt"
2021
"net/http"
2122
"net/url"
2223
"strings"
2324
"testing"
2425

2526
splcommon "github.com/splunk/splunk-operator/pkg/splunk/common"
27+
"sigs.k8s.io/controller-runtime/pkg/log"
2628

2729
spltest "github.com/splunk/splunk-operator/pkg/splunk/test"
2830
)
@@ -660,6 +662,9 @@ func TestUpdateConfFile(t *testing.T) {
660662
value := "myvalue"
661663
fileName := "outputs"
662664

665+
reqLogger := log.FromContext(context.TODO())
666+
scopedLog := reqLogger.WithName("TestUpdateConfFile")
667+
663668
// First request: create the property (object) if it doesn't exist
664669
createBody := strings.NewReader(fmt.Sprintf("name=%s", property))
665670
wantCreateRequest, _ := http.NewRequest("POST", "https://localhost:8089/servicesNS/nobody/system/configs/conf-outputs", createBody)
@@ -675,7 +680,7 @@ func TestUpdateConfFile(t *testing.T) {
675680
c := NewSplunkClient("https://localhost:8089", "admin", "p@ssw0rd")
676681
c.Client = mockSplunkClient
677682

678-
err := c.UpdateConfFile(fileName, property, [][]string{{key, value}})
683+
err := c.UpdateConfFile(scopedLog, fileName, property, [][]string{{key, value}})
679684
if err != nil {
680685
t.Errorf("UpdateConfFile err = %v", err)
681686
}
@@ -685,7 +690,7 @@ func TestUpdateConfFile(t *testing.T) {
685690
mockSplunkClient = &spltest.MockHTTPClient{}
686691
mockSplunkClient.AddHandler(wantCreateRequest, 500, "", nil)
687692
c.Client = mockSplunkClient
688-
err = c.UpdateConfFile(fileName, property, [][]string{{key, value}})
693+
err = c.UpdateConfFile(scopedLog, fileName, property, [][]string{{key, value}})
689694
if err == nil {
690695
t.Errorf("UpdateConfFile expected error on create, got nil")
691696
}
@@ -695,7 +700,7 @@ func TestUpdateConfFile(t *testing.T) {
695700
mockSplunkClient.AddHandler(wantCreateRequest, 201, "", nil)
696701
mockSplunkClient.AddHandler(wantUpdateRequest, 500, "", nil)
697702
c.Client = mockSplunkClient
698-
err = c.UpdateConfFile(fileName, property, [][]string{{key, value}})
703+
err = c.UpdateConfFile(scopedLog, fileName, property, [][]string{{key, value}})
699704
if err == nil {
700705
t.Errorf("UpdateConfFile expected error on update, got nil")
701706
}
@@ -706,6 +711,9 @@ func TestDeleteConfFileProperty(t *testing.T) {
706711
property := "myproperty"
707712
fileName := "outputs"
708713

714+
reqLogger := log.FromContext(context.TODO())
715+
scopedLog := reqLogger.WithName("TestDeleteConfFileProperty")
716+
709717
wantDeleteRequest, _ := http.NewRequest("DELETE", fmt.Sprintf("https://localhost:8089/servicesNS/nobody/system/configs/conf-outputs/%s", property), nil)
710718

711719
mockSplunkClient := &spltest.MockHTTPClient{}
@@ -714,7 +722,7 @@ func TestDeleteConfFileProperty(t *testing.T) {
714722
c := NewSplunkClient("https://localhost:8089", "admin", "p@ssw0rd")
715723
c.Client = mockSplunkClient
716724

717-
err := c.DeleteConfFileProperty(fileName, property)
725+
err := c.DeleteConfFileProperty(scopedLog, fileName, property)
718726
if err != nil {
719727
t.Errorf("DeleteConfFileProperty err = %v", err)
720728
}
@@ -724,7 +732,7 @@ func TestDeleteConfFileProperty(t *testing.T) {
724732
mockSplunkClient = &spltest.MockHTTPClient{}
725733
mockSplunkClient.AddHandler(wantDeleteRequest, 500, "", nil)
726734
c.Client = mockSplunkClient
727-
err = c.DeleteConfFileProperty(fileName, property)
735+
err = c.DeleteConfFileProperty(scopedLog, fileName, property)
728736
if err == nil {
729737
t.Errorf("DeleteConfFileProperty expected error on delete, got nil")
730738
}

0 commit comments

Comments
 (0)