Skip to content

Commit

Permalink
Don't fail on listing namespaces (#549)
Browse files Browse the repository at this point in the history
* Don't fail on listing namespaces

* Remove debugging

* Single HasNamespace()

* Don't log error, return it

* review, and handle ns 'not found'

* Generalise list.Namespace() func

* Doh.

* errors.As and report missing namespace
  • Loading branch information
malcolmholmes authored Mar 30, 2021
1 parent 9a252b9 commit 8040711
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 3 deletions.
4 changes: 4 additions & 0 deletions pkg/kubernetes/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ type Client interface {

// Namespaces the cluster currently has
Namespaces() (map[string]bool, error)

// Namespace retrieves a namespace from the cluster
Namespace(namespace string) (manifest.Manifest, error)

// Resources returns all known api-resources of the cluster
Resources() (Resources, error)

Expand Down
38 changes: 36 additions & 2 deletions pkg/kubernetes/client/kubectl.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package client
import (
"bytes"
"encoding/json"
"fmt"
"os"
"regexp"

Expand Down Expand Up @@ -51,12 +52,13 @@ func (k Kubectl) Namespaces() (map[string]bool, error) {
cmd := k.ctl("get", "namespaces", "-o", "json")

var sout bytes.Buffer
var serr bytes.Buffer
cmd.Stdout = &sout
cmd.Stderr = os.Stderr
cmd.Stderr = &serr

err := cmd.Run()
if err != nil {
return nil, err
return nil, errors.Wrap(err, string(serr.Bytes()))
}

var list manifest.Manifest
Expand All @@ -76,6 +78,38 @@ func (k Kubectl) Namespaces() (map[string]bool, error) {
return namespaces, nil
}

type ErrNamespaceNotFound struct {
Namespace string
}

func (e ErrNamespaceNotFound) Error() string {
return fmt.Sprintf("Namespace not found: %s", e.Namespace)
}

// Namespace finds a single namespace in the cluster
func (k Kubectl) Namespace(namespace string) (manifest.Manifest, error) {
cmd := k.ctl("get", "namespaces", namespace, "-o", "json", "--ignore-not-found")

var sout bytes.Buffer
cmd.Stdout = &sout
cmd.Stderr = os.Stderr

err := cmd.Run()
if err != nil {
return nil, err
}
if len(sout.Bytes()) == 0 {
return nil, ErrNamespaceNotFound{
Namespace: namespace,
}
}
var ns manifest.Manifest
if err := json.Unmarshal(sout.Bytes(), &ns); err != nil {
return nil, err
}
return ns, nil
}

// FilterWriter is an io.Writer that discards every message that matches at
// least one of the regular expressions.
type FilterWriter struct {
Expand Down
13 changes: 12 additions & 1 deletion pkg/kubernetes/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,18 @@ Please upgrade kubectl to at least version 1.18.1.`)
// required for separating
namespaces, err := k.ctl.Namespaces()
if err != nil {
return nil, errors.Wrap(err, "listing namespaces")
resourceNamespaces := state.Namespaces()
namespaces = map[string]bool{}
for _, namespace := range resourceNamespaces {
_, err = k.ctl.Namespace(namespace)
if err != nil {
if errors.As(err, client.ErrNamespaceNotFound{}) {
continue
}
return nil, errors.Wrap(err, "retrieving namespaces")
}
namespaces[namespace] = true
}
}
resources, err := k.ctl.Resources()
if err != nil {
Expand Down
14 changes: 14 additions & 0 deletions pkg/kubernetes/manifest/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,20 @@ func (m List) String() string {
return buf.String()
}

func (m List) Namespaces() []string {
namespaces := map[string]struct{}{}
for _, manifest := range m {
if namespace := manifest.Metadata().Namespace(); namespace != "" {
namespaces[namespace] = struct{}{}
}
}
keys := []string{}
for k := range namespaces {
keys = append(keys, k)
}
return keys
}

func m2o(m interface{}) objx.Map {
switch mm := m.(type) {
case Metadata:
Expand Down

0 comments on commit 8040711

Please sign in to comment.