Skip to content

Commit c62ae2d

Browse files
committed
Gather ODF config data
1 parent 95961e7 commit c62ae2d

File tree

6 files changed

+309
-0
lines changed

6 files changed

+309
-0
lines changed

docs/gathered-data.md

+13
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,19 @@ API Reference:
652652
* Since versions:
653653
* 4.9+
654654

655+
## OpenshiftStorage
656+
657+
collects `storageclusters.ocs.openshift.io` resources
658+
from Openshift Data Foundation Stack.
659+
660+
API Reference:
661+
https://github.com/red-hat-storage/ocs-operator/blob/main/api/v1/storagecluster_types.go
662+
663+
* Location in archive: config/storage/<namespace>/<name>.json
664+
* Id in config: clusterconfig/openshift_storage
665+
* Since versions:
666+
* 4.11+
667+
655668

656669
## OpenshiftSDNControllerLogs
657670

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
{
2+
"apiVersion": "ocs.openshift.io/v1",
3+
"kind": "StorageCluster",
4+
"metadata": {
5+
"annotations": {
6+
"storagesystem.odf.openshift.io/watched-by": "ocs-storagecluster-storagesystem",
7+
"uninstall.ocs.openshift.io/cleanup-policy": "delete",
8+
"uninstall.ocs.openshift.io/mode": "graceful"
9+
},
10+
"creationTimestamp": "2022-02-24T05:31:35Z",
11+
"finalizers": ["storagecluster.ocs.openshift.io"],
12+
"generation": 4,
13+
"name": "ocs-storagecluster",
14+
"namespace": "openshift-storage",
15+
"ownerReferences": [
16+
{
17+
"apiVersion": "odf.openshift.io/v1alpha1",
18+
"blockOwnerDeletion": true,
19+
"controller": true,
20+
"kind": "StorageSystem",
21+
"name": "ocs-storagecluster-storagesystem",
22+
"uid": "395e3b8f-37ad-4ddb-af67-b2a7d3324ae9"
23+
}
24+
],
25+
"resourceVersion": "56661474",
26+
"uid": "a0bfbbc1-0d25-4a8a-806d-cc42e6183a39"
27+
},
28+
"spec": {
29+
"arbiter": {},
30+
"encryption": { "kms": {} },
31+
"externalStorage": {},
32+
"managedResources": {
33+
"cephBlockPools": {},
34+
"cephConfig": {},
35+
"cephDashboard": {},
36+
"cephFilesystems": {},
37+
"cephObjectStoreUsers": {},
38+
"cephObjectStores": {}
39+
},
40+
"mirroring": {},
41+
"nodeTopologies": {},
42+
"storageDeviceSets": [
43+
{
44+
"config": {},
45+
"count": 1,
46+
"dataPVCTemplate": {
47+
"metadata": {},
48+
"spec": {
49+
"accessModes": ["ReadWriteOnce"],
50+
"resources": { "requests": { "storage": "512Gi" } },
51+
"storageClassName": "thin",
52+
"volumeMode": "Block"
53+
},
54+
"status": {}
55+
},
56+
"name": "ocs-deviceset-thin",
57+
"placement": {},
58+
"portable": true,
59+
"preparePlacement": {},
60+
"replica": 3,
61+
"resources": {}
62+
}
63+
],
64+
"version": "4.9.0"
65+
},
66+
"status": {
67+
"conditions": [
68+
{
69+
"lastHeartbeatTime": "2022-04-26T12:41:51Z",
70+
"lastTransitionTime": "2022-04-26T06:38:23Z",
71+
"message": "Reconcile completed successfully",
72+
"reason": "ReconcileCompleted",
73+
"status": "True",
74+
"type": "ReconcileComplete"
75+
},
76+
{
77+
"lastHeartbeatTime": "2022-04-26T12:41:51Z",
78+
"lastTransitionTime": "2022-02-24T05:40:14Z",
79+
"message": "Reconcile completed successfully",
80+
"reason": "ReconcileCompleted",
81+
"status": "True",
82+
"type": "Available"
83+
},
84+
{
85+
"lastHeartbeatTime": "2022-04-26T12:41:51Z",
86+
"lastTransitionTime": "2022-03-22T06:29:53Z",
87+
"message": "Reconcile completed successfully",
88+
"reason": "ReconcileCompleted",
89+
"status": "False",
90+
"type": "Progressing"
91+
},
92+
{
93+
"lastHeartbeatTime": "2022-04-26T12:41:51Z",
94+
"lastTransitionTime": "2022-02-24T05:31:36Z",
95+
"message": "Reconcile completed successfully",
96+
"reason": "ReconcileCompleted",
97+
"status": "False",
98+
"type": "Degraded"
99+
},
100+
{
101+
"lastHeartbeatTime": "2022-04-26T12:41:51Z",
102+
"lastTransitionTime": "2022-02-28T08:21:42Z",
103+
"message": "Reconcile completed successfully",
104+
"reason": "ReconcileCompleted",
105+
"status": "True",
106+
"type": "Upgradeable"
107+
}
108+
],
109+
"failureDomain": "rack",
110+
"failureDomainKey": "topology.rook.io/rack",
111+
"failureDomainValues": ["rack0", "rack1", "rack2"],
112+
"images": {
113+
"ceph": {
114+
"actualImage": "registry.redhat.io/rhceph/rhceph-5-rhel8@sha256:2296c19fbd3a0be84d6030dff789ce3e79b38cc30c39f45913aec97967b65cce",
115+
"desiredImage": "registry.redhat.io/rhceph/rhceph-5-rhel8@sha256:2296c19fbd3a0be84d6030dff789ce3e79b38cc30c39f45913aec97967b65cce"
116+
},
117+
"noobaaCore": {
118+
"actualImage": "registry.redhat.io/odf4/mcg-core-rhel8@sha256:b0726c457b0fda796014b2743910ad12130a60be361796c90479e8954d8bfe99",
119+
"desiredImage": "registry.redhat.io/odf4/mcg-core-rhel8@sha256:b0726c457b0fda796014b2743910ad12130a60be361796c90479e8954d8bfe99"
120+
},
121+
"noobaaDB": {
122+
"actualImage": "registry.redhat.io/rhel8/postgresql-12@sha256:da0b8d525b173ef472ff4c71fae60b396f518860d6313c4f3287b844aab6d622",
123+
"desiredImage": "registry.redhat.io/rhel8/postgresql-12@sha256:da0b8d525b173ef472ff4c71fae60b396f518860d6313c4f3287b844aab6d622"
124+
}
125+
},
126+
"nodeTopologies": {
127+
"labels": {
128+
"kubernetes.io/hostname": [
129+
"perf6-fhz82-ocs-5q98p",
130+
"perf6-fhz82-ocs-jnmf4",
131+
"perf6-fhz82-ocs-kbbc4"
132+
],
133+
"topology.rook.io/rack": ["rack0", "rack1", "rack2"]
134+
}
135+
},
136+
"phase": "Ready",
137+
"relatedObjects": [
138+
{
139+
"apiVersion": "ceph.rook.io/v1",
140+
"kind": "CephCluster",
141+
"name": "ocs-storagecluster-cephcluster",
142+
"namespace": "openshift-storage",
143+
"resourceVersion": "56661470",
144+
"uid": "221d739b-d2d9-4cd9-864d-59da7c766fcb"
145+
},
146+
{
147+
"apiVersion": "noobaa.io/v1alpha1",
148+
"kind": "NooBaa",
149+
"name": "noobaa",
150+
"namespace": "openshift-storage",
151+
"resourceVersion": "29319336",
152+
"uid": "62c1c608-ef52-4b90-b6c5-cd60490d3dc9"
153+
}
154+
]
155+
}
156+
}

pkg/gatherers/clusterconfig/clusterconfig_gatherer.go

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ var gatheringFunctions = map[string]gathererFuncPtr{
6666
"pod_network_connectivity_checks": (*Gatherer).GatherPNCC,
6767
"machine_autoscalers": (*Gatherer).GatherMachineAutoscalers,
6868
"openshift_logging": (*Gatherer).GatherOpenshiftLogging,
69+
"openshift_storage": (*Gatherer).GatherOpenshiftStorage,
6970
"jaegers": (*Gatherer).GatherJaegerCR,
7071
"validating_webhook_configurations": (*Gatherer).GatherValidatingWebhookConfigurations,
7172
"mutating_webhook_configurations": (*Gatherer).GatherMutatingWebhookConfigurations,

pkg/gatherers/clusterconfig/const.go

+3
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ var (
4949
openshiftLoggingResource = schema.GroupVersionResource{
5050
Group: "logging.openshift.io", Version: "v1", Resource: "clusterloggings",
5151
}
52+
openshiftStorageResource = schema.GroupVersionResource{
53+
Group: "ocs.openshift.io", Version: "v1", Resource: "storageclusters",
54+
}
5255

5356
jaegerResource = schema.GroupVersionResource{
5457
Group: "jaegertracing.io", Version: "v1", Resource: "jaegers",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package clusterconfig
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"k8s.io/apimachinery/pkg/api/errors"
8+
"k8s.io/klog/v2"
9+
10+
"github.com/openshift/insights-operator/pkg/record"
11+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12+
"k8s.io/client-go/dynamic"
13+
)
14+
15+
// GatherOpenshiftStorage collects `storageclusters.ocs.openshift.io` resources
16+
// from Openshift Data Foundation Stack.
17+
//
18+
// API Reference:
19+
// https://github.com/red-hat-storage/ocs-operator/blob/main/api/v1/storagecluster_types.go
20+
//
21+
// * Location in archive: config/storage/<namespace>/<name>.json
22+
// * Id in config: clusterconfig/openshift_storage
23+
// * Since versions:
24+
// * 4.11+
25+
func (g *Gatherer) GatherOpenshiftStorage(ctx context.Context) ([]record.Record, []error) {
26+
gatherDynamicClient, err := dynamic.NewForConfig(g.gatherKubeConfig)
27+
if err != nil {
28+
return nil, []error{err}
29+
}
30+
31+
return gatherOpenshiftStorage(ctx, gatherDynamicClient)
32+
}
33+
34+
func gatherOpenshiftStorage(ctx context.Context, dynamicClient dynamic.Interface) ([]record.Record, []error) {
35+
loggingResourceList, err := dynamicClient.Resource(openshiftStorageResource).List(ctx, metav1.ListOptions{})
36+
if errors.IsNotFound(err) {
37+
return nil, nil
38+
}
39+
if err != nil {
40+
klog.V(2).Infof("Unable to list %s resource due to: %s", openshiftStorageResource, err)
41+
return nil, []error{err}
42+
}
43+
44+
var records []record.Record
45+
for _, item := range loggingResourceList.Items {
46+
records = append(records, record.Record{
47+
Name: fmt.Sprintf("config/storage/%s/%s", item.GetNamespace(), item.GetName()),
48+
Item: record.ResourceMarshaller{Resource: &item},
49+
})
50+
}
51+
return records, nil
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package clusterconfig
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"k8s.io/apimachinery/pkg/runtime"
8+
"k8s.io/apimachinery/pkg/runtime/schema"
9+
"k8s.io/apimachinery/pkg/runtime/serializer/yaml"
10+
"k8s.io/client-go/dynamic"
11+
dynamicfake "k8s.io/client-go/dynamic/fake"
12+
13+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
15+
)
16+
17+
func Test_GatherOpenshiftStorage(t *testing.T) {
18+
var openshiftStorageYAML = `
19+
apiVersion: ocs.openshift.io/v1
20+
kind: StorageCluster
21+
metadata:
22+
name: ocs-storagecluster
23+
namespace: openshift-storage
24+
`
25+
type args struct {
26+
ctx context.Context
27+
dynamicClient dynamic.Interface
28+
}
29+
30+
tests := []struct {
31+
name string
32+
args args
33+
totalRecords int
34+
recordName string
35+
expectedError error
36+
}{
37+
{
38+
name: "check for storagecluster resource",
39+
args: args{
40+
ctx: context.TODO(),
41+
dynamicClient: dynamicfake.NewSimpleDynamicClientWithCustomListKinds(runtime.NewScheme(), map[schema.GroupVersionResource]string{
42+
openshiftStorageResource: "StorageClusterList",
43+
}),
44+
},
45+
totalRecords: 1,
46+
recordName: "config/storage/openshift-storage/ocs-storagecluster",
47+
expectedError: nil,
48+
},
49+
}
50+
for _, tt := range tests {
51+
tt := tt
52+
t.Run(tt.name, func(t *testing.T) {
53+
t.Parallel()
54+
55+
decUnstructured := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme)
56+
testOpenshiftStorageResource := &unstructured.Unstructured{}
57+
58+
_, _, err := decUnstructured.Decode([]byte(openshiftStorageYAML), nil, testOpenshiftStorageResource)
59+
if err != nil {
60+
t.Fatal("unable to decode storagecluster ", err)
61+
}
62+
_, err = tt.args.dynamicClient.
63+
Resource(openshiftStorageResource).
64+
Namespace("openshift-storage").
65+
Create(context.Background(), testOpenshiftStorageResource, metav1.CreateOptions{})
66+
if err != nil {
67+
t.Fatalf("unable to create fake resource %s", err)
68+
}
69+
70+
records, errs := gatherOpenshiftStorage(tt.args.ctx, tt.args.dynamicClient)
71+
if len(errs) > 0 {
72+
if errs[0].Error() != tt.expectedError.Error() {
73+
t.Fatalf("unexpected errors: %v", errs[0].Error())
74+
}
75+
}
76+
if len(records) != tt.totalRecords {
77+
t.Errorf("gatherOpenshiftStorage() got = %v, want %v", len(records), tt.totalRecords)
78+
}
79+
if records[0].Name != tt.recordName {
80+
t.Errorf("gatherOpenshiftStorage() name = %v, want %v ", records[0].Name, tt.recordName)
81+
}
82+
})
83+
}
84+
}

0 commit comments

Comments
 (0)