Skip to content

Commit

Permalink
[release-4.5] Bug 1880352: collect hostsubnet information
Browse files Browse the repository at this point in the history
  • Loading branch information
tremes committed Sep 23, 2020
1 parent 6b4743c commit d569e87
Show file tree
Hide file tree
Showing 36 changed files with 5,721 additions and 2 deletions.
10 changes: 10 additions & 0 deletions docs/gathered-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,16 @@ Location in archive: config/configmaps/
See: docs/insights-archive-sample/config/configmaps


## HostSubnet

collects HostSubnet information

The Kubernetes api https://github.com/openshift/client-go/blob/master/network/clientset/versioned/typed/network/v1/hostsubnet.go
Response see https://docs.openshift.com/container-platform/4.3/rest_api/index.html#hostsubnet-v1-network-openshift-io

Location in archive: config/hostsubnet/


## MostRecentMetrics

gathers cluster Federated Monitoring metrics.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"kind":"HostSubnet","apiVersion":"network.openshift.io/v1","metadata":{"name":"worker-0.cluster.lab.upshift.rdu2.redhat.com","selfLink":"/apis/network.openshift.io/v1/hostsubnets/worker-0.cluster.lab.upshift.rdu2.redhat.com","uid":"23df6019-9397-4ae0-b77f-40d61fa047ce","resourceVersion":"13896","generation":1,"creationTimestamp":"2020-09-18T14:51:45Z","annotations":{"pod.network.openshift.io/node-uid":"5d190ab9-e0c2-4371-bb89-1760884b508c"},"managedFields":[{"manager":"openshift-sdn-controller","operation":"Update","apiVersion":"network.openshift.io/v1","time":"2020-09-18T14:51:45Z","fieldsType":"FieldsV1","fieldsV1":{"f:host":{},"f:hostIP":{},"f:metadata":{"f:annotations":{".":{},"f:pod.network.openshift.io/node-uid":{}}},"f:subnet":{}}}]},"host":"worker-0.cluster.lab.upshift.rdu2.redhat.com","hostIP":"xxxxxxxxxx","subnet":"xxxxxxxxxxxxx"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"kind":"HostSubnet","apiVersion":"network.openshift.io/v1","metadata":{"name":"worker-0.cluster.lab.upshift.rdu2.redhat.com","selfLink":"/apis/network.openshift.io/v1/hostsubnets/worker-0.cluster.lab.upshift.rdu2.redhat.com","uid":"23df6019-9397-4ae0-b77f-40d61fa047ce","resourceVersion":"13896","generation":1,"creationTimestamp":"2020-09-18T14:51:45Z","annotations":{"pod.network.openshift.io/node-uid":"5d190ab9-e0c2-4371-bb89-1760884b508c"},"managedFields":[{"manager":"openshift-sdn-controller","operation":"Update","apiVersion":"network.openshift.io/v1","time":"2020-09-18T14:51:45Z","fieldsType":"FieldsV1","fieldsV1":{"f:host":{},"f:hostIP":{},"f:metadata":{"f:annotations":{".":{},"f:pod.network.openshift.io/node-uid":{}}},"f:subnet":{}}}]},"host":"worker-0.cluster.lab.upshift.rdu2.redhat.com","hostIP":"xxxxxxxxxx","subnet":"xxxxxxxxxxxxx"}
8 changes: 7 additions & 1 deletion pkg/controller/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"k8s.io/client-go/rest"

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

imageregistryv1client "github.com/openshift/client-go/imageregistry/clientset/versioned"
Expand Down Expand Up @@ -109,6 +110,11 @@ func (s *Support) Run(ctx context.Context, controller *controllercmd.ControllerC
return err
}

gatherNetworkClient, err := networkv1client.NewForConfig(gatherKubeConfig)
if err != nil {
return err
}

registryClient, err := imageregistryv1client.NewForConfig(gatherKubeConfig)
if err != nil {
return err
Expand Down Expand Up @@ -136,7 +142,7 @@ func (s *Support) Run(ctx context.Context, controller *controllercmd.ControllerC

// the gatherers periodically check the state of the cluster and report any
// config to the recorder
configPeriodic := clusterconfig.New(gatherConfigClient, gatherKubeClient.CoreV1(), gatherKubeClient.CertificatesV1beta1(), metricsClient, registryClient.ImageregistryV1())
configPeriodic := clusterconfig.New(gatherConfigClient, gatherKubeClient.CoreV1(), gatherKubeClient.CertificatesV1beta1(), metricsClient, registryClient.ImageregistryV1(), gatherNetworkClient)
periodic := periodic.New(configObserver, recorder, map[string]gather.Interface{
"config": configPeriodic,
})
Expand Down
59 changes: 58 additions & 1 deletion pkg/gather/clusterconfig/clusterconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ import (

configv1 "github.com/openshift/api/config/v1"
registryv1 "github.com/openshift/api/imageregistry/v1"
networkv1 "github.com/openshift/api/network/v1"
openshiftscheme "github.com/openshift/client-go/config/clientset/versioned/scheme"
configv1client "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
imageregistryv1 "github.com/openshift/client-go/imageregistry/clientset/versioned/typed/imageregistry/v1"
networkv1client "github.com/openshift/client-go/network/clientset/versioned/typed/network/v1"

"github.com/openshift/insights-operator/pkg/record"
"github.com/openshift/insights-operator/pkg/record/diskrecorder"
Expand Down Expand Up @@ -62,7 +64,9 @@ var (
maxEventTimeInterval = 1 * time.Hour

registrySerializer serializer.CodecFactory
networkSerializer serializer.CodecFactory
registryScheme = runtime.NewScheme()
networkScheme = runtime.NewScheme()

// logTailLines sets maximum number of lines to fetch from pod logs
logTailLines = int64(100)
Expand All @@ -73,13 +77,16 @@ var (

func init() {
utilruntime.Must(registryv1.AddToScheme(registryScheme))
utilruntime.Must(networkv1.AddToScheme(networkScheme))
networkSerializer = serializer.NewCodecFactory(networkScheme)
registrySerializer = serializer.NewCodecFactory(registryScheme)
}

// Gatherer is a driving instance invoking collection of data
type Gatherer struct {
client configv1client.ConfigV1Interface
coreClient corev1client.CoreV1Interface
networkClient networkv1client.NetworkV1Interface
metricsClient rest.Interface
certClient certificatesv1beta1.CertificatesV1beta1Interface
registryClient imageregistryv1.ImageregistryV1Interface
Expand All @@ -89,13 +96,14 @@ type Gatherer struct {

// New creates new Gatherer
func New(client configv1client.ConfigV1Interface, coreClient corev1client.CoreV1Interface, certClient certificatesv1beta1.CertificatesV1beta1Interface, metricsClient rest.Interface,
registryClient imageregistryv1.ImageregistryV1Interface) *Gatherer {
registryClient imageregistryv1.ImageregistryV1Interface, networkClient networkv1client.NetworkV1Interface) *Gatherer {
return &Gatherer{
client: client,
coreClient: coreClient,
certClient: certClient,
metricsClient: metricsClient,
registryClient: registryClient,
networkClient: networkClient,
}
}

Expand All @@ -120,6 +128,7 @@ func (i *Gatherer) Gather(ctx context.Context, recorder record.Interface) error
GatherClusterIngress(i),
GatherClusterProxy(i),
GatherCertificateSigningRequests(i),
GatherHostSubnet(i),
)
}

Expand Down Expand Up @@ -437,6 +446,29 @@ func GatherClusterNetwork(i *Gatherer) func() ([]record.Record, []error) {
}
}

// GatherHostSubnet collects HostSubnet information
//
// The Kubernetes api https://github.com/openshift/client-go/blob/master/network/clientset/versioned/typed/network/v1/hostsubnet.go
// Response see https://docs.openshift.com/container-platform/4.3/rest_api/index.html#hostsubnet-v1-network-openshift-io
//
// Location in archive: config/hostsubnet/
func GatherHostSubnet(i *Gatherer) func() ([]record.Record, []error) {
return func() ([]record.Record, []error) {
hostSubnetList, err := i.networkClient.HostSubnets().List(metav1.ListOptions{})
if errors.IsNotFound(err) {
return nil, nil
}
if err != nil {
return nil, []error{err}
}
records := make([]record.Record, 0, len(hostSubnetList.Items))
for _, h := range hostSubnetList.Items {
records = append(records, record.Record{Name: fmt.Sprintf("config/hostsubnet/%s", h.Host), Item: HostSubnetAnonymizer{&h}})
}
return records, nil
}
}

// GatherClusterAuthentication fetches the cluster Authentication - the Authentication with name cluster.
//
// The Kubernetes api https://github.com/openshift/client-go/blob/master/config/clientset/versioned/typed/config/v1/authentication.go#L50
Expand Down Expand Up @@ -925,6 +957,14 @@ func anonymizeString(s string) string {
return strings.Repeat("x", len(s))
}

func anonymizeSliceOfStrings(slice []string) []string {
anonymizedSlice := make([]string, len(slice), len(slice))
for i, s := range slice {
anonymizedSlice[i] = anonymizeString(s)
}
return anonymizedSlice
}

func isProductNamespacedKey(key string) bool {
return strings.Contains(key, "openshift.io/") || strings.Contains(key, "k8s.io/") || strings.Contains(key, "kubernetes.io/")
}
Expand Down Expand Up @@ -1021,6 +1061,23 @@ func (a ConfigMapAnonymizer) GetExtension() string {
return ""
}

// HostSubnetAnonymizer implements HostSubnet serialization wiht anonymization
type HostSubnetAnonymizer struct{ *networkv1.HostSubnet }

// Marshal implements HostSubnet serialization
func (a HostSubnetAnonymizer) Marshal(_ context.Context) ([]byte, error) {
a.HostSubnet.HostIP = anonymizeString(a.HostSubnet.HostIP)
a.HostSubnet.Subnet = anonymizeString(a.HostSubnet.Subnet)
a.HostSubnet.EgressIPs = anonymizeSliceOfStrings(a.HostSubnet.EgressIPs)
a.HostSubnet.EgressCIDRs = anonymizeSliceOfStrings(a.HostSubnet.EgressCIDRs)
return runtime.Encode(networkSerializer.LegacyCodec(networkv1.SchemeGroupVersion), a.HostSubnet)
}

// GetExtension returns extension for HostSubnet object
func (a HostSubnetAnonymizer) GetExtension() string {
return "json"
}

func anonymizeConfigMap(dv []byte) string {
anonymizedPemBlock := `-----BEGIN CERTIFICATE-----
ANONYMIZED
Expand Down
59 changes: 59 additions & 0 deletions pkg/gather/clusterconfig/clusterconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import (

imageregistryv1 "github.com/openshift/api/imageregistry/v1"
v1 "k8s.io/api/core/v1"
networkv1 "github.com/openshift/api/network/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog"

imageregistryfake "github.com/openshift/client-go/imageregistry/clientset/versioned/fake"
networkfake "github.com/openshift/client-go/network/clientset/versioned/fake"
"github.com/openshift/insights-operator/pkg/record"
"github.com/openshift/insights-operator/pkg/utils"
)
Expand Down Expand Up @@ -307,6 +309,63 @@ func TestGatherClusterImageRegistry(t *testing.T) {

}

func TestGatherHostSubnet(t *testing.T) {
testHostSubnet := networkv1.HostSubnet{
Host: "test.host",
HostIP: "10.0.0.0",
Subnet: "10.0.0.0/23",
EgressIPs: []string{"10.0.0.0", "10.0.0.1"},
EgressCIDRs: []string{"10.0.0.0/24", "10.0.0.0/24"},
}
client := networkfake.NewSimpleClientset()
_, err := client.NetworkV1().HostSubnets().Create(&testHostSubnet)
if err != nil {
t.Fatal("unable to create fake hostsubnet")
}

gatherer := &Gatherer{networkClient: client.NetworkV1()}

records, errs := GatherHostSubnet(gatherer)()
if len(errs) > 0 {
t.Errorf("unexpected errors: %#v", errs)
return
}
if len(records) != 1 {
t.Fatalf("unexpected number or records %d", len(records))
}
item, err := records[0].Item.Marshal(context.TODO())
var gatheredHostSubnet networkv1.HostSubnet
_, _, err = networkSerializer.LegacyCodec(networkv1.SchemeGroupVersion).Decode(item, nil, &gatheredHostSubnet)
if err != nil {
t.Fatalf("failed to decode object: %v", err)
}
if gatheredHostSubnet.HostIP != "xxxxxxxx" {
t.Fatalf("Host IP is not anonymized %s", gatheredHostSubnet.HostIP)
}
if gatheredHostSubnet.Subnet != "xxxxxxxxxxx" {
t.Fatalf("Host Subnet is not anonymized %s", gatheredHostSubnet.Subnet)
}
if len(gatheredHostSubnet.EgressIPs) != len(testHostSubnet.EgressIPs) {
t.Fatalf("unexpected number of egress IPs gathered %s", gatheredHostSubnet.EgressIPs)
}

if len(gatheredHostSubnet.EgressCIDRs) != len(testHostSubnet.EgressCIDRs) {
t.Fatalf("unexpected number of egress CIDRs gathered %s", gatheredHostSubnet.EgressCIDRs)
}

for _, ip := range gatheredHostSubnet.EgressIPs {
if ip != "xxxxxxxx" {
t.Fatalf("Egress IP is not anonymized %s", ip)
}
}

for _, cidr := range gatheredHostSubnet.EgressCIDRs {
if cidr != "xxxxxxxxxxx" {
t.Fatalf("Egress CIDR is not anonymized %s", cidr)
}
}
}

func ExampleGatherMostRecentMetrics_Test() {
b, err := ExampleMostRecentMetrics()
if err != nil {
Expand Down
17 changes: 17 additions & 0 deletions vendor/github.com/openshift/api/network/v1/constants.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions vendor/github.com/openshift/api/network/v1/doc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d569e87

Please sign in to comment.