Skip to content

Commit 4d8fa44

Browse files
Merge pull request #177 from tremes/CCXDEV-2392
Bug 1879068: Collect hostsubnet information
2 parents 74cfdcf + 3b2456f commit 4d8fa44

33 files changed

+5710
-2
lines changed

pkg/controller/operator.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"k8s.io/client-go/rest"
1818

1919
configv1client "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
20+
networkv1client "github.com/openshift/client-go/network/clientset/versioned/typed/network/v1"
2021
"github.com/openshift/library-go/pkg/controller/controllercmd"
2122

2223
imageregistryv1client "github.com/openshift/client-go/imageregistry/clientset/versioned"
@@ -110,6 +111,11 @@ func (s *Support) Run(ctx context.Context, controller *controllercmd.ControllerC
110111
return err
111112
}
112113

114+
gatherNetworkClient, err := networkv1client.NewForConfig(gatherKubeConfig)
115+
if err != nil {
116+
return err
117+
}
118+
113119
registryClient, err := imageregistryv1client.NewForConfig(gatherKubeConfig)
114120
if err != nil {
115121
return err
@@ -142,7 +148,7 @@ func (s *Support) Run(ctx context.Context, controller *controllercmd.ControllerC
142148

143149
// the gatherers periodically check the state of the cluster and report any
144150
// config to the recorder
145-
configPeriodic := clusterconfig.New(gatherConfigClient, gatherKubeClient.CoreV1(), gatherKubeClient.CertificatesV1beta1(), metricsClient, registryClient.ImageregistryV1(), crdClient)
151+
configPeriodic := clusterconfig.New(gatherConfigClient, gatherKubeClient.CoreV1(), gatherKubeClient.CertificatesV1beta1(), metricsClient, registryClient.ImageregistryV1(), crdClient, gatherNetworkClient)
146152
periodic := periodic.New(configObserver, recorder, map[string]gather.Interface{
147153
"config": configPeriodic,
148154
})

pkg/gather/clusterconfig/clusterconfig.go

+59-1
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ import (
3232

3333
configv1 "github.com/openshift/api/config/v1"
3434
registryv1 "github.com/openshift/api/imageregistry/v1"
35+
networkv1 "github.com/openshift/api/network/v1"
3536
openshiftscheme "github.com/openshift/client-go/config/clientset/versioned/scheme"
3637
configv1client "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
3738
imageregistryv1 "github.com/openshift/client-go/imageregistry/clientset/versioned/typed/imageregistry/v1"
39+
networkv1client "github.com/openshift/client-go/network/clientset/versioned/typed/network/v1"
3840

3941
"github.com/openshift/insights-operator/pkg/record"
4042
"github.com/openshift/insights-operator/pkg/record/diskrecorder"
@@ -66,7 +68,9 @@ var (
6668
maxEventTimeInterval = 1 * time.Hour
6769

6870
registrySerializer serializer.CodecFactory
71+
networkSerializer serializer.CodecFactory
6972
registryScheme = runtime.NewScheme()
73+
networkScheme = runtime.NewScheme()
7074

7175
// logTailLines sets maximum number of lines to fetch from pod logs
7276
logTailLines = int64(100)
@@ -79,13 +83,16 @@ var (
7983

8084
func init() {
8185
utilruntime.Must(registryv1.AddToScheme(registryScheme))
86+
utilruntime.Must(networkv1.AddToScheme(networkScheme))
87+
networkSerializer = serializer.NewCodecFactory(networkScheme)
8288
registrySerializer = serializer.NewCodecFactory(registryScheme)
8389
}
8490

8591
// Gatherer is a driving instance invoking collection of data
8692
type Gatherer struct {
8793
client configv1client.ConfigV1Interface
8894
coreClient corev1client.CoreV1Interface
95+
networkClient networkv1client.NetworkV1Interface
8996
metricsClient rest.Interface
9097
certClient certificatesv1beta1.CertificatesV1beta1Interface
9198
registryClient imageregistryv1.ImageregistryV1Interface
@@ -96,14 +103,15 @@ type Gatherer struct {
96103

97104
// New creates new Gatherer
98105
func New(client configv1client.ConfigV1Interface, coreClient corev1client.CoreV1Interface, certClient certificatesv1beta1.CertificatesV1beta1Interface, metricsClient rest.Interface,
99-
registryClient imageregistryv1.ImageregistryV1Interface, crdClient apixv1beta1client.ApiextensionsV1beta1Interface) *Gatherer {
106+
registryClient imageregistryv1.ImageregistryV1Interface, crdClient apixv1beta1client.ApiextensionsV1beta1Interface, networkClient networkv1client.NetworkV1Interface) *Gatherer {
100107
return &Gatherer{
101108
client: client,
102109
coreClient: coreClient,
103110
certClient: certClient,
104111
metricsClient: metricsClient,
105112
registryClient: registryClient,
106113
crdClient: crdClient,
114+
networkClient: networkClient,
107115
}
108116
}
109117

@@ -130,6 +138,7 @@ func (i *Gatherer) Gather(ctx context.Context, recorder record.Interface) error
130138
GatherClusterProxy(i),
131139
GatherCertificateSigningRequests(i),
132140
GatherCRD(i),
141+
GatherHostSubnet(i),
133142
)
134143
}
135144

@@ -509,6 +518,30 @@ func GatherClusterNetwork(i *Gatherer) func() ([]record.Record, []error) {
509518
}
510519
}
511520

521+
// GatherHostSubnet collects HostSubnet information
522+
//
523+
// The Kubernetes api https://github.com/openshift/client-go/blob/master/network/clientset/versioned/typed/network/v1/hostsubnet.go
524+
// Response see https://docs.openshift.com/container-platform/4.3/rest_api/index.html#hostsubnet-v1-network-openshift-io
525+
//
526+
// Location in archive: config/hostsubnet/
527+
func GatherHostSubnet(i *Gatherer) func() ([]record.Record, []error) {
528+
return func() ([]record.Record, []error) {
529+
530+
hostSubnetList, err := i.networkClient.HostSubnets().List(metav1.ListOptions{})
531+
if errors.IsNotFound(err) {
532+
return nil, nil
533+
}
534+
if err != nil {
535+
return nil, []error{err}
536+
}
537+
records := make([]record.Record, 0, len(hostSubnetList.Items))
538+
for _, h := range hostSubnetList.Items {
539+
records = append(records, record.Record{Name: fmt.Sprintf("config/hostsubnet/%s", h.Host), Item: HostSubnetAnonymizer{&h}})
540+
}
541+
return records, nil
542+
}
543+
}
544+
512545
// GatherClusterAuthentication fetches the cluster Authentication - the Authentication with name cluster.
513546
//
514547
// The Kubernetes api https://github.com/openshift/client-go/blob/master/config/clientset/versioned/typed/config/v1/authentication.go#L50
@@ -1027,6 +1060,14 @@ func anonymizeString(s string) string {
10271060
return strings.Repeat("x", len(s))
10281061
}
10291062

1063+
func anonymizeSliceOfStrings(slice []string) []string {
1064+
anonymizedSlice := make([]string, len(slice), len(slice))
1065+
for i, s := range slice {
1066+
anonymizedSlice[i] = anonymizeString(s)
1067+
}
1068+
return anonymizedSlice
1069+
}
1070+
10301071
func isProductNamespacedKey(key string) bool {
10311072
return strings.Contains(key, "openshift.io/") || strings.Contains(key, "k8s.io/") || strings.Contains(key, "kubernetes.io/")
10321073
}
@@ -1123,6 +1164,23 @@ func (a ConfigMapAnonymizer) GetExtension() string {
11231164
return ""
11241165
}
11251166

1167+
// HostSubnetAnonymizer implements HostSubnet serialization wiht anonymization
1168+
type HostSubnetAnonymizer struct{ *networkv1.HostSubnet }
1169+
1170+
// Marshal implements HostSubnet serialization
1171+
func (a HostSubnetAnonymizer) Marshal(_ context.Context) ([]byte, error) {
1172+
a.HostSubnet.HostIP = anonymizeString(a.HostSubnet.HostIP)
1173+
a.HostSubnet.Subnet = anonymizeString(a.HostSubnet.Subnet)
1174+
a.HostSubnet.EgressIPs = anonymizeSliceOfStrings(a.HostSubnet.EgressIPs)
1175+
a.HostSubnet.EgressCIDRs = anonymizeSliceOfStrings(a.HostSubnet.EgressCIDRs)
1176+
return runtime.Encode(networkSerializer.LegacyCodec(networkv1.SchemeGroupVersion), a.HostSubnet)
1177+
}
1178+
1179+
// GetExtension returns extension for HostSubnet object
1180+
func (a HostSubnetAnonymizer) GetExtension() string {
1181+
return "json"
1182+
}
1183+
11261184
func anonymizeConfigMap(dv []byte) string {
11271185
anonymizedPemBlock := `-----BEGIN CERTIFICATE-----
11281186
ANONYMIZED

pkg/gather/clusterconfig/clusterconfig_test.go

+59
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"testing"
1111

1212
imageregistryv1 "github.com/openshift/api/imageregistry/v1"
13+
networkv1 "github.com/openshift/api/network/v1"
1314
corev1 "k8s.io/api/core/v1"
1415
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
1516
apixv1beta1clientfake "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
@@ -19,6 +20,7 @@ import (
1920
"k8s.io/klog"
2021

2122
imageregistryfake "github.com/openshift/client-go/imageregistry/clientset/versioned/fake"
23+
networkfake "github.com/openshift/client-go/network/clientset/versioned/fake"
2224
"github.com/openshift/insights-operator/pkg/record"
2325
"github.com/openshift/insights-operator/pkg/utils"
2426
)
@@ -478,6 +480,63 @@ func TestCollectVolumeSnapshotCRD(t *testing.T) {
478480
}
479481
}
480482

483+
func TestGatherHostSubnet(t *testing.T) {
484+
testHostSubnet := networkv1.HostSubnet{
485+
Host: "test.host",
486+
HostIP: "10.0.0.0",
487+
Subnet: "10.0.0.0/23",
488+
EgressIPs: []string{"10.0.0.0", "10.0.0.1"},
489+
EgressCIDRs: []string{"10.0.0.0/24", "10.0.0.0/24"},
490+
}
491+
client := networkfake.NewSimpleClientset()
492+
_, err := client.NetworkV1().HostSubnets().Create(&testHostSubnet)
493+
if err != nil {
494+
t.Fatal("unable to create fake hostsubnet")
495+
}
496+
497+
gatherer := &Gatherer{networkClient: client.NetworkV1()}
498+
499+
records, errs := GatherHostSubnet(gatherer)()
500+
if len(errs) > 0 {
501+
t.Errorf("unexpected errors: %#v", errs)
502+
return
503+
}
504+
if len(records) != 1 {
505+
t.Fatalf("unexpected number or records %d", len(records))
506+
}
507+
item, err := records[0].Item.Marshal(context.TODO())
508+
var gatheredHostSubnet networkv1.HostSubnet
509+
_, _, err = networkSerializer.LegacyCodec(networkv1.SchemeGroupVersion).Decode(item, nil, &gatheredHostSubnet)
510+
if err != nil {
511+
t.Fatalf("failed to decode object: %v", err)
512+
}
513+
if gatheredHostSubnet.HostIP != "xxxxxxxx" {
514+
t.Fatalf("Host IP is not anonymized %s", gatheredHostSubnet.HostIP)
515+
}
516+
if gatheredHostSubnet.Subnet != "xxxxxxxxxxx" {
517+
t.Fatalf("Host Subnet is not anonymized %s", gatheredHostSubnet.Subnet)
518+
}
519+
if len(gatheredHostSubnet.EgressIPs) != len(testHostSubnet.EgressIPs) {
520+
t.Fatalf("unexpected number of egress IPs gathered %s", gatheredHostSubnet.EgressIPs)
521+
}
522+
523+
if len(gatheredHostSubnet.EgressCIDRs) != len(testHostSubnet.EgressCIDRs) {
524+
t.Fatalf("unexpected number of egress CIDRs gathered %s", gatheredHostSubnet.EgressCIDRs)
525+
}
526+
527+
for _, ip := range gatheredHostSubnet.EgressIPs {
528+
if ip != "xxxxxxxx" {
529+
t.Fatalf("Egress IP is not anonymized %s", ip)
530+
}
531+
}
532+
533+
for _, cidr := range gatheredHostSubnet.EgressCIDRs {
534+
if cidr != "xxxxxxxxxxx" {
535+
t.Fatalf("Egress CIDR is not anonymized %s", cidr)
536+
}
537+
}
538+
}
539+
481540
func ExampleGatherMostRecentMetrics_Test() {
482541
b, err := ExampleMostRecentMetrics()
483542
if err != nil {

vendor/github.com/openshift/api/network/v1/constants.go

+17
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/openshift/api/network/v1/doc.go

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)