Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POP-188: fix #188 and #178 #189

Merged
merged 1 commit into from Jul 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 18 additions & 9 deletions internal/client/config.go
Expand Up @@ -283,17 +283,16 @@ func (c *Config) RawConfig() (clientcmdapi.Config, error) {
log.Debug().Msgf("Context switch detected... %s vs %s", c.rawConfig.CurrentContext, c.currentContext)
c.currentContext = c.rawConfig.CurrentContext
c.reset()
return *c.rawConfig, nil
}

if c.rawConfig == nil {
c.ensureConfig()
cfg, err := c.clientConfig.RawConfig()
if err != nil {
return cfg, err
}
c.rawConfig = &cfg
c.currentContext = cfg.CurrentContext
c.ensureConfig()
cfg, err := c.clientConfig.RawConfig()
if err != nil {
return cfg, err
}
c.rawConfig = &cfg
c.currentContext = cfg.CurrentContext

return *c.rawConfig, nil
}
Expand All @@ -311,12 +310,22 @@ func (c *Config) RESTConfig() (*restclient.Config, error) {
c.restConfig.QPS = defaultQPS
c.restConfig.Burst = defaultBurst
c.restConfig.Timeout = defaultCallTimeoutDuration

restclient.SetDefaultWarningHandler(newLoggerHandler())
log.Debug().Msgf("Connecting to API Server %s", c.restConfig.Host)

return c.restConfig, nil
}

type loggerHandler struct{}

func newLoggerHandler() loggerHandler {
return loggerHandler{}
}

func (l loggerHandler) HandleWarningHeader(code int, agent string, text string) {
log.Warn().Msgf("[%d] (%q) -- %s", code, agent, text)
}

func (c *Config) ensureConfig() {
if c.clientConfig != nil {
return
Expand Down
32 changes: 32 additions & 0 deletions internal/client/revision.go
@@ -0,0 +1,32 @@
package client

import (
"fmt"
"regexp"
"strconv"

"k8s.io/apimachinery/pkg/version"
)

type Revision struct {
Info *version.Info
Major, Minor int
}

var minorRX = regexp.MustCompile(`(\d+)\+?`)

func NewRevision(info *version.Info) (*Revision, error) {
major, err := strconv.Atoi(info.Major)
if err != nil {
return nil, fmt.Errorf("unable to extract major %q", info.Major)
}
minors := minorRX.FindStringSubmatch(info.Minor)
if len(minors) < 2 {
return nil, fmt.Errorf("unable to extract minor %q", info.Minor)
}
minor, err := strconv.Atoi(minors[1])
if err != nil {
return nil, err
}
return &Revision{Info: info, Major: major, Minor: minor}, nil
}
37 changes: 37 additions & 0 deletions internal/client/revision_test.go
@@ -0,0 +1,37 @@
package client_test

import (
"testing"

"github.com/derailed/popeye/internal/client"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/version"
)

func TestNewRevision(t *testing.T) {
uu := map[string]struct {
info *version.Info
major, minor int
}{
"plain": {
info: &version.Info{Major: "1", Minor: "18+"},
major: 1,
minor: 18,
},
"no-plus": {
info: &version.Info{Major: "1", Minor: "18"},
major: 1,
minor: 18,
},
}

for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
r, err := client.NewRevision(u.info)
assert.Nil(t, err)
assert.Equal(t, u.major, r.Major)
assert.Equal(t, u.minor, r.Minor)
})
}
}
48 changes: 30 additions & 18 deletions pkg/popeye.go
Expand Up @@ -17,9 +17,6 @@ import (
"strings"
"time"

"github.com/prometheus/common/expfmt"
"k8s.io/apimachinery/pkg/version"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
Expand All @@ -30,6 +27,7 @@ import (
"github.com/derailed/popeye/internal/scrub"
"github.com/derailed/popeye/pkg/config"
"github.com/derailed/popeye/types"
"github.com/prometheus/common/expfmt"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
Expand Down Expand Up @@ -86,7 +84,7 @@ func (p *Popeye) Init() error {
return err
}
}
rev, err := p.factory.Client().ServerVersion()
rev, err := p.revision()
if err != nil {
return err
}
Expand All @@ -111,7 +109,7 @@ func (p *Popeye) SetFactory(f types.Factory) {
p.factory = f
}

func (p *Popeye) scannedGVRs(rev *version.Info) []string {
func (p *Popeye) scannedGVRs(rev *client.Revision) []string {
mm := []string{
"v1/limitranges",
"v1/services",
Expand All @@ -137,12 +135,12 @@ func (p *Popeye) scannedGVRs(rev *version.Info) []string {
"rbac.authorization.k8s.io/v1/rolebindings",
}

if rev.Minor == "18" || rev.Minor == "17" {
if rev.Minor <= 18 {
mm = append(mm, "networking.k8s.io/v1beta1/ingresses")
} else {
mm = append(mm, "networking.k8s.io/v1/ingresses")
}
if rev.Minor == "21" {
if rev.Minor >= 21 {
mm = append(mm, "policy/v1/poddisruptionbudgets")
} else {
mm = append(mm, "policy/v1beta1/poddisruptionbudgets")
Expand All @@ -162,15 +160,21 @@ func (p *Popeye) initFactory() error {
if p.flags.StandAlone {
return nil
}
ns := client.AllNamespaces
if p.flags.ConfigFlags.Namespace != nil {
ns = *p.flags.ConfigFlags.Namespace

info, err := p.factory.Client().ServerVersion()
if err != nil {
return err
}
rev, err := p.factory.Client().ServerVersion()
rev, err := client.NewRevision(info)
if err != nil {
return err
}

ns := client.AllNamespaces
if p.flags.ConfigFlags.Namespace != nil {
ns = *p.flags.ConfigFlags.Namespace
}

f.Start(ns)
for _, gvr := range p.scannedGVRs(rev) {
ok, err := clt.CanI(client.AllNamespaces, gvr, types.ReadAllAccess)
Expand All @@ -186,7 +190,16 @@ func (p *Popeye) initFactory() error {
return nil
}

func (p *Popeye) sanitizers(rev *version.Info) map[string]scrubFn {
func (p *Popeye) revision() (*client.Revision, error) {
info, err := p.factory.Client().ServerVersion()
if err != nil {
return nil, err
}

return client.NewRevision(info)
}

func (p *Popeye) sanitizers(rev *client.Revision) map[string]scrubFn {
mm := map[string]scrubFn{
"cluster": scrub.NewCluster,
"v1/configmaps": scrub.NewConfigMap,
Expand All @@ -213,10 +226,10 @@ func (p *Popeye) sanitizers(rev *version.Info) map[string]scrubFn {
"rbac.authorization.k8s.io/v1/rolebindings": scrub.NewRoleBinding,
}

if rev.Minor == "18" || rev.Minor == "17" {
if rev.Minor <= 18 {
mm["networking.k8s.io/v1beta1/ingresses"] = scrub.NewIngress
}
if rev.Minor == "21" {
if rev.Minor >= 21 {
mm["policy/v1/poddisruptionbudgets"] = scrub.NewPodDisruptionBudget
}

Expand Down Expand Up @@ -294,17 +307,16 @@ func (p *Popeye) sanitize() (int, int, error) {
var total, errCount int
var nodeGVR = client.NewGVR("v1/nodes")
cache := scrub.NewCache(p.factory, p.config)
rev, err := p.factory.Client().ServerVersion()

rev, err := p.revision()
if err != nil {
return 0, 0, err
}

for k, fn := range p.sanitizers(rev) {
gvr := client.NewGVR(k)
if p.aliases.Exclude(gvr, p.config.Sections()) {
continue
}

// Skip node sanitizer if active namespace is set.
if gvr == nodeGVR && p.factory.Client().ActiveNamespace() != client.AllNamespaces {
continue
Expand All @@ -330,10 +342,10 @@ func (p *Popeye) sanitize() (int, int, error) {
close(c)
}
}

if count == 0 {
return errCount, 0, nil
}

return errCount, score / count, nil
}

Expand Down