Skip to content

Commit c73cf1b

Browse files
Merge pull request #218 from tremes/statefulsets
Gather StatefulSet configs from default & openshift namespaces
2 parents 2c0a428 + 37f16b6 commit c73cf1b

File tree

8 files changed

+1370
-121
lines changed

8 files changed

+1370
-121
lines changed

docs/insights-archive-sample/config/statefulsets/openshift-monitoring/prometheus-k8s.json

+1,147
Large diffs are not rendered by default.

pkg/controller/operator.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"k8s.io/client-go/dynamic"
1515
"k8s.io/client-go/kubernetes"
1616
"k8s.io/client-go/kubernetes/scheme"
17+
appsclient "k8s.io/client-go/kubernetes/typed/apps/v1"
1718
policyclient "k8s.io/client-go/kubernetes/typed/policy/v1beta1"
1819
"k8s.io/client-go/pkg/version"
1920
"k8s.io/client-go/rest"
@@ -139,6 +140,10 @@ func (s *Support) Run(ctx context.Context, controller *controllercmd.ControllerC
139140
return err
140141
}
141142

143+
appsClient, err := appsclient.NewForConfig(gatherKubeConfig)
144+
if err != nil {
145+
return err
146+
}
142147
// ensure the insight snapshot directory exists
143148
if _, err := os.Stat(s.StoragePath); err != nil && os.IsNotExist(err) {
144149
if err := os.MkdirAll(s.StoragePath, 0777); err != nil {
@@ -161,7 +166,7 @@ func (s *Support) Run(ctx context.Context, controller *controllercmd.ControllerC
161166

162167
// the gatherers periodically check the state of the cluster and report any
163168
// config to the recorder
164-
configPeriodic := clusterconfig.New(gatherConfigClient, gatherKubeClient.CoreV1(), gatherKubeClient.CertificatesV1beta1(), metricsClient, registryClient.ImageregistryV1(), crdClient, gatherNetworkClient, dynamicClient, gatherPolicyClient)
169+
configPeriodic := clusterconfig.New(gatherConfigClient, gatherKubeClient.CoreV1(), gatherKubeClient.CertificatesV1beta1(), metricsClient, registryClient.ImageregistryV1(), crdClient, gatherNetworkClient, dynamicClient, gatherPolicyClient, appsClient)
165170
periodic := periodic.New(configObserver, recorder, map[string]gather.Interface{
166171
"config": configPeriodic,
167172
})

pkg/controllerstatus/controllerstatus.go

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ type Interface interface {
1313

1414
type Operation string
1515

16-
1716
const (
1817
// DownloadingReport specific flag for Smart Proxy report downloading process.
1918
DownloadingReport Operation = "DownloadingReport"

pkg/gather/clusterconfig/clusterconfig.go

+61-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"k8s.io/apimachinery/pkg/util/sets"
3030
"k8s.io/client-go/dynamic"
3131
kubescheme "k8s.io/client-go/kubernetes/scheme"
32+
appsclient "k8s.io/client-go/kubernetes/typed/apps/v1"
3233
certificatesv1beta1 "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
3334
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
3435
policyclient "k8s.io/client-go/kubernetes/typed/policy/v1beta1"
@@ -42,6 +43,7 @@ import (
4243
configv1client "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
4344
imageregistryv1 "github.com/openshift/client-go/imageregistry/clientset/versioned/typed/imageregistry/v1"
4445
networkv1client "github.com/openshift/client-go/network/clientset/versioned/typed/network/v1"
46+
appsv1 "k8s.io/api/apps/v1"
4547
_ "k8s.io/apimachinery/pkg/runtime/serializer/yaml"
4648

4749
"github.com/openshift/insights-operator/pkg/record"
@@ -81,6 +83,7 @@ var (
8183
openshiftSerializer = openshiftscheme.Codecs.LegacyCodec(configv1.SchemeGroupVersion)
8284
kubeSerializer = kubescheme.Codecs.LegacyCodec(corev1.SchemeGroupVersion)
8385
policyV1Beta1Serializer = kubescheme.Codecs.LegacyCodec(policyv1beta1.SchemeGroupVersion)
86+
appsV1Serializer = kubescheme.Codecs.LegacyCodec(appsv1.SchemeGroupVersion)
8487
// maxEventTimeInterval represents the "only keep events that are maximum 1h old"
8588
// TODO: make this dynamic like the reporting window based on configured interval
8689
maxEventTimeInterval = 1 * time.Hour
@@ -120,14 +123,15 @@ type Gatherer struct {
120123
registryClient imageregistryv1.ImageregistryV1Interface
121124
crdClient apixv1beta1client.ApiextensionsV1beta1Interface
122125
policyClient policyclient.PolicyV1beta1Interface
126+
appsClient appsclient.AppsV1Interface
123127
lock sync.Mutex
124128
lastVersion *configv1.ClusterVersion
125129
}
126130

127131
// New creates new Gatherer
128132
func New(client configv1client.ConfigV1Interface, coreClient corev1client.CoreV1Interface, certClient certificatesv1beta1.CertificatesV1beta1Interface, metricsClient rest.Interface,
129133
registryClient imageregistryv1.ImageregistryV1Interface, crdClient apixv1beta1client.ApiextensionsV1beta1Interface, networkClient networkv1client.NetworkV1Interface,
130-
dynamicClient dynamic.Interface, policyClient policyclient.PolicyV1beta1Interface) *Gatherer {
134+
dynamicClient dynamic.Interface, policyClient policyclient.PolicyV1beta1Interface, appsclient appsclient.AppsV1Interface) *Gatherer {
131135
return &Gatherer{
132136
client: client,
133137
coreClient: coreClient,
@@ -138,6 +142,7 @@ func New(client configv1client.ConfigV1Interface, coreClient corev1client.CoreV1
138142
networkClient: networkClient,
139143
dynamicClient: dynamicClient,
140144
policyClient: policyClient,
145+
appsClient: appsclient,
141146
}
142147
}
143148

@@ -172,6 +177,7 @@ func (i *Gatherer) Gather(ctx context.Context, recorder record.Interface) error
172177
GatherServiceAccounts(i),
173178
GatherMachineConfigPool(i),
174179
GatherContainerRuntimeConfig(i),
180+
GatherStatefulSets(i),
175181
)
176182
}
177183

@@ -1054,6 +1060,47 @@ func GatherContainerRuntimeConfig(i *Gatherer) func() ([]record.Record, []error)
10541060
}
10551061
}
10561062

1063+
//GatherStatefulSets collects StatefulSet configs from default namespaces
1064+
//
1065+
// The Kubernetes API https://github.com/kubernetes/api/blob/master/apps/v1/types.go
1066+
// Response see https://docs.openshift.com/container-platform/4.5/rest_api/workloads_apis/statefulset-apps-v1.html#statefulset-apps-v1
1067+
//
1068+
// Location in archive: config/statefulsets/
1069+
func GatherStatefulSets(i *Gatherer) func() ([]record.Record, []error) {
1070+
return func() ([]record.Record, []error) {
1071+
namespaces, err := getAllNamespaces(i)
1072+
if errors.IsNotFound(err) {
1073+
return nil, nil
1074+
}
1075+
if err != nil {
1076+
return nil, []error{err}
1077+
}
1078+
1079+
osNamespaces := defaultNamespaces
1080+
for _, item := range namespaces.Items {
1081+
if strings.HasPrefix(item.Name, "openshift") {
1082+
osNamespaces = append(osNamespaces, item.Name)
1083+
}
1084+
}
1085+
records := []record.Record{}
1086+
for _, namespace := range osNamespaces {
1087+
sets, err := i.appsClient.StatefulSets(namespace).List(i.ctx, metav1.ListOptions{})
1088+
if err != nil {
1089+
klog.V(2).Infof("Unable to read StatefulSets in namespace %s error %s", namespace, err)
1090+
continue
1091+
}
1092+
1093+
for _, i := range sets.Items {
1094+
records = append(records, record.Record{
1095+
Name: fmt.Sprintf("config/statefulsets/%s/%s", namespace, i.GetName()),
1096+
Item: StatefulSetAnonymizer{&i},
1097+
})
1098+
}
1099+
}
1100+
return records, nil
1101+
}
1102+
}
1103+
10571104
func (i *Gatherer) gatherNamespaceEvents(namespace string) ([]record.Record, []error) {
10581105
// do not accidentally collect events for non-openshift namespace
10591106
if !strings.HasPrefix(namespace, "openshift-") {
@@ -1837,3 +1884,16 @@ func (a ServiceAccountsMarshaller) Marshal(_ context.Context) ([]byte, error) {
18371884
func (a ServiceAccountsMarshaller) GetExtension() string {
18381885
return "json"
18391886
}
1887+
1888+
// StatefulSetAnonymizer implements StatefulSet serialization without anonymization
1889+
type StatefulSetAnonymizer struct{ *appsv1.StatefulSet }
1890+
1891+
// Marshal implements StatefulSet serialization
1892+
func (a StatefulSetAnonymizer) Marshal(_ context.Context) ([]byte, error) {
1893+
return runtime.Encode(appsV1Serializer, a.StatefulSet)
1894+
}
1895+
1896+
// GetExtension returns extension for StatefulSet object
1897+
func (a StatefulSetAnonymizer) GetExtension() string {
1898+
return "json"
1899+
}

pkg/gather/clusterconfig/clusterconfig_test.go

+38
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
imageregistryv1 "github.com/openshift/api/imageregistry/v1"
1313
networkv1 "github.com/openshift/api/network/v1"
14+
appsv1 "k8s.io/api/apps/v1"
1415
corev1 "k8s.io/api/core/v1"
1516
policyv1beta1 "k8s.io/api/policy/v1beta1"
1617
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
@@ -873,6 +874,43 @@ func TestGatherServiceAccounts(t *testing.T) {
873874
}
874875
}
875876

877+
func TestGatherStatefulSet(t *testing.T) {
878+
testSet := appsv1.StatefulSet{
879+
ObjectMeta: metav1.ObjectMeta{
880+
Name: "test-statefulset",
881+
Namespace: "openshift-test",
882+
},
883+
}
884+
client := kubefake.NewSimpleClientset()
885+
_, err := client.CoreV1().Namespaces().Create(context.Background(), &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "openshift-test"}}, metav1.CreateOptions{})
886+
if err != nil {
887+
t.Fatal("unable to create fake namespace", err)
888+
}
889+
_, err = client.AppsV1().StatefulSets("openshift-test").Create(context.Background(), &testSet, metav1.CreateOptions{})
890+
if err != nil {
891+
t.Fatal("unable to create fake statefulset", err)
892+
}
893+
894+
gatherer := &Gatherer{ctx: context.Background(), coreClient: client.CoreV1(), appsClient: client.AppsV1()}
895+
896+
records, errs := GatherStatefulSets(gatherer)()
897+
if len(errs) > 0 {
898+
t.Errorf("unexpected errors: %#v", errs)
899+
return
900+
}
901+
902+
item, err := records[0].Item.Marshal(context.TODO())
903+
var gatheredStatefulSet appsv1.StatefulSet
904+
_, _, err = appsV1Serializer.Decode(item, nil, &gatheredStatefulSet)
905+
if err != nil {
906+
t.Fatalf("failed to decode object: %v", err)
907+
}
908+
if gatheredStatefulSet.Name != "test-statefulset" {
909+
t.Fatalf("unexpected statefulset name %s", gatheredStatefulSet.Name)
910+
}
911+
912+
}
913+
876914
func ExampleGatherMostRecentMetrics_Test() {
877915
b, err := ExampleMostRecentMetrics()
878916
if err != nil {

test/integration/basic_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func TestPullSecretExists(t *testing.T) {
4242
}
4343

4444
func TestIsIOHealthy(t *testing.T) {
45-
checkPodsLogs(t, `The operator is healthy`)
45+
checkPodsLogs(t, `The operator is healthy`)
4646
}
4747

4848
// Check if opt-in/opt-out works

test/integration/bugs_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func TestUploadNotDelayedAfterStart(t *testing.T) {
2828
time1 := logLineTime(t, `Reporting status periodically to .* every`)
2929
time2 := logLineTime(t, `Successfully reported id=`)
3030
delay := time2.Sub(time1)
31-
allowedDelay := 3*time.Minute
31+
allowedDelay := 3 * time.Minute
3232
t.Logf("Archive upload delay was %d seconds", delay/time.Second)
3333
if delay > allowedDelay && delay < time.Hour*24-allowedDelay {
3434
t.Fatal("Upload after start took too much time")

0 commit comments

Comments
 (0)