diff --git a/cmd/preflight/cli/run.go b/cmd/preflight/cli/run.go index d21bdf213..4eb946b9b 100644 --- a/cmd/preflight/cli/run.go +++ b/cmd/preflight/cli/run.go @@ -11,7 +11,7 @@ import ( "strings" "time" - "github.com/ahmetalpbalkan/go-cursor" + cursor "github.com/ahmetalpbalkan/go-cursor" "github.com/fatih/color" "github.com/pkg/errors" analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze" @@ -19,7 +19,7 @@ import ( "github.com/replicatedhq/troubleshoot/pkg/collect" "github.com/replicatedhq/troubleshoot/pkg/logger" "github.com/spf13/viper" - "github.com/tj/go-spin" + spin "github.com/tj/go-spin" "gopkg.in/yaml.v2" ) @@ -199,7 +199,11 @@ func runCollectors(v *viper.Viper, preflight troubleshootv1beta1.Preflight, prog // Run preflights collectors synchronously for _, collector := range collectors { if len(collector.RBACErrors) > 0 { - continue + // don't skip clusterResources collector due to RBAC issues + if collector.Collect.ClusterResources == nil { + progressChan <- fmt.Sprintf("skipping collector %s with insufficient RBAC permissions", collector.GetDisplayName()) + continue + } } result, err := collector.RunCollectorSync() diff --git a/cmd/troubleshoot/cli/run.go b/cmd/troubleshoot/cli/run.go index 4bbf5fcee..50d8dde55 100644 --- a/cmd/troubleshoot/cli/run.go +++ b/cmd/troubleshoot/cli/run.go @@ -191,7 +191,11 @@ func runCollectors(v *viper.Viper, collector troubleshootv1beta1.Collector, prog // Run preflights collectors synchronously for _, collector := range collectors { if len(collector.RBACErrors) > 0 { - continue + // don't skip clusterResources collector due to RBAC issues + if collector.Collect.ClusterResources == nil { + progressChan <- fmt.Sprintf("skipping collector %s with insufficient RBAC permissions", collector.GetDisplayName()) + continue + } } progressChan <- collector.GetDisplayName() diff --git a/pkg/collect/cluster_resources.go b/pkg/collect/cluster_resources.go index c42816c5d..1e5efd85f 100644 --- a/pkg/collect/cluster_resources.go +++ b/pkg/collect/cluster_resources.go @@ -34,6 +34,9 @@ type ClusterResourcesOutput struct { ImagePullSecretsErrors []byte `json:"cluster-resources/image-pull-secrets-errors.json,omitempty"` Nodes []byte `json:"cluster-resources/nodes.json,omitempty"` NodesErrors []byte `json:"cluster-resources/nodes-errors.json,omitempty"` + Groups []byte `json:"cluster-resources/groups.json,omitempty"` + Resources []byte `json:"cluster-resources/resources.json,omitempty"` + GroupsResourcesErrors []byte `json:"cluster-resources/groups-resources-errors.json,omitempty"` // TODO these should be considered for relocation to an rbac or auth package. cluster resources might not be the right place AuthCanI map[string][]byte `json:"cluster-resources/auth-cani-list,omitempty"` @@ -137,6 +140,14 @@ func ClusterResources(ctx *Context) ([]byte, error) { return nil, err } + groups, resources, groupsResourcesErrors := apiResources(client) + clusterResourcesOutput.Groups = groups + clusterResourcesOutput.Resources = resources + clusterResourcesOutput.GroupsResourcesErrors, err = marshalNonNil(groupsResourcesErrors) + if err != nil { + return nil, err + } + // auth cani authCanI, authCanIErrors := authCanI(client, namespaceNames) clusterResourcesOutput.AuthCanI = authCanI @@ -374,6 +385,27 @@ func nodes(client *kubernetes.Clientset) ([]byte, []string) { return b, nil } +// get the list of API resources, similar to 'kubectl api-resources' +func apiResources(client *kubernetes.Clientset) ([]byte, []byte, []string) { + var errorArray []string + groups, resources, err := client.Discovery().ServerGroupsAndResources() + if err != nil { + errorArray = append(errorArray, err.Error()) + } + + groupBytes, err := json.MarshalIndent(groups, "", " ") + if err != nil { + errorArray = append(errorArray, err.Error()) + } + + resourcesBytes, err := json.MarshalIndent(resources, "", " ") + if err != nil { + errorArray = append(errorArray, err.Error()) + } + + return groupBytes, resourcesBytes, errorArray +} + func authCanI(client *kubernetes.Clientset, namespaces []string) (map[string][]byte, map[string]string) { // https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/auth/cani.go @@ -464,6 +496,14 @@ func (c *ClusterResourcesOutput) Redact() (*ClusterResourcesOutput, error) { if err != nil { return nil, err } + groups, err := redact.Redact(c.Groups) + if err != nil { + return nil, err + } + resources, err := redact.Redact(c.Resources) + if err != nil { + return nil, err + } return &ClusterResourcesOutput{ Namespaces: namespaces, @@ -486,5 +526,8 @@ func (c *ClusterResourcesOutput) Redact() (*ClusterResourcesOutput, error) { ImagePullSecretsErrors: c.ImagePullSecretsErrors, AuthCanI: c.AuthCanI, AuthCanIErrors: c.AuthCanIErrors, + Groups: groups, + Resources: resources, + GroupsResourcesErrors: c.GroupsResourcesErrors, }, nil } diff --git a/sample-troubleshoot.yaml b/sample-troubleshoot.yaml new file mode 100644 index 000000000..a96a2ffdb --- /dev/null +++ b/sample-troubleshoot.yaml @@ -0,0 +1,14 @@ +apiVersion: troubleshoot.replicated.com/v1beta1 +kind: Collector +metadata: + name: my-application-name +spec: + collectors: + - clusterInfo: + collectorName: my-cluster-info + - clusterResources: + collectorName: my-cluster-resources + - http: + name: healthz + get: + url: http://api:3000/healthz